web-dev-qa-db-ja.com

テンプレートクラスのフレンド演算子<<をオーバーロードしています

テンプレートクラスPairのフレンドとして演算子<<をオーバーロードしようとしていますが、コンパイラの警告が表示され続けます

friend declaration std::ostream& operator<<(ostream& out, Pair<T,U>& v) declares a non template function

このコードの場合:

friend ostream& operator<<(ostream&, Pair<T,U>&);

推奨事項として2番目の警告を出します

if this is not what you intended, make sure the function template has already been declared and add <> after the function name here

これが関数の定義です

template <class T, class U>
ostream& operator<<(ostream& out, Pair<T,U>& v)
{
    out << v.val1 << " " << v.val2;
}

これがクラス全体です。

template <class T, class U>
class Pair{
public:
    Pair(T v1, U v2) : val1(v1), val2(v2){}
    ~Pair(){}
    Pair& operator=(const Pair&);
    friend ostream& operator<<(ostream&, Pair<T,U>&);

private:
    T val1;
    U val2;
};

推奨警告から何を引き出すべきかわからなかったが、それ以外は、友達宣言のどこかに入れなければならないかもしれない。誰かがこれの適切な構文を知っていますか?ありがとう。

28
trikker

Operator <<をostream&を返すものとして宣言しましたが、メソッドにはreturnステートメントがまったくありません。する必要があります:

template <class T, class U>
ostream& operator<<(ostream& out, Pair<T,U>& v)
{
    return out << v.val1 << " " << v.val2;
}

それ以外は、Visual Studio 2008でコードをコンパイルしてレベル4の警告を表示しても、問題や警告はありません。古典的なリンカーエラーがありますが、説明したように、テンプレート関数定義をクラス宣言に移動することで簡単に回避できます。 C++ FAQ で。

私のテストコード:

#include <iostream>
using namespace std;

template <class T, class U>
class Pair{ 
public:
    Pair(T v1, U v2) : val1(v1), val2(v2){}
    ~Pair(){}
    Pair& operator=(const Pair&);
    friend ostream& operator<<(ostream& out, Pair<T,U>& v)
    {
        return out << v.val1 << " " << v.val2;
    }
private:    
    T val1;
    U val2;
};

int main() {
    Pair<int, int> a(3, 4);
    cout << a;      
}
20
Asik

そのテンプレートの単一のインスタンス(一般的な用語では「特殊化」と呼ばれます)を友達にします。あなたはそれを次のようにします

template <class T, class U>
class Pair{
public:
    Pair(T v1, U v2) : val1(v1), val2(v2){}
    ~Pair(){}
    Pair& operator=(const Pair&);
    friend ostream& operator<< <> (ostream&, Pair<T,U>&);

private:
    T val1;
    U val2;
};

コンパイラはパラメータリストからテンプレート引数がTUであることを知っているので、それらを<...>の間に置く必要はなく、空のままにしておくことができます。次のように、Pairテンプレートの上にoperator<<の宣言を配置する必要があることに注意してください。

template <class T, class U> class Pair;

template <class T, class U>
ostream& operator<<(ostream& out, Pair<T,U>& v);

// now the Pair template definition...

シンプルなインラインバージョン:

template<typename T> class HasFriend {
    private:
        T item;
    public:
       ~HasFriend() {}
       HasFriend(const T &i) : item(i) {}
    friend ostream& operator<<(ostream& os, const HasFriend<T>& x) {
        return os << "s(" << sizeof(x) << ").op<<" << x.item << endl;
    }
};

改訂されたテンプレートバージョン:

template<template<typename /**/> class U, typename V>
ostream& operator<<(ostream &os, const U<V> &x) {
    return os << "s(" << sizeof(x) << ").op<<" << x.item << endl;
}

template<typename T> class HasFriend {
    private:
        T item;
    public:
       ~HasFriend() {}
       HasFriend(const T &i) : item(i) {}
    friend ostream& operator<<<>(ostream&, const HasFriend<T>&);
};
1
wkliang