56

以下のコードに似た基本クラスがあります。coutで使用するために<<をオーバーロードしようとしています。ただし、g++は次のように言っています。

base.h:24: warning: friend declaration ‘std::ostream& operator<<(std::ostream&, Base<T>*)’ declares a non-template function
base.h:24: warning: (if this is not what you intended, make sure the function template has already been declared and add <> after the function name here) -Wno-non-template-friend disables this warning

クラス宣言/プロトタイプの<<の後に<>を追加してみました。しかし、私はそれを取得しdoes not match any template declarationます。演算子定義を完全にテンプレート化しようとしましたが(必要です)、演算子を手動でインスタンス化して、次のコードでのみ機能させることができました。

base.h

template <typename T>
class Base {
  public:
    friend ostream& operator << (ostream &out, Base<T> *e);
};

base.cpp

ostream& operator<< (ostream &out, Base<int> *e) {
    out << e->data;
return out;
}

ヘッダーbase.hにこれまたは類似のものを入れたいだけです。

template <typename T>
class Base {
  public:
    friend ostream& operator << (ostream &out, Base<T> *e);
};

template <typename T>
ostream& operator<< (ostream &out, Base<T> *e) {
    out << e->data;
return out;
}

プロトタイプの<<と()の間に<>を入れるとこれが修正されるはずだとオンラインで読んだことがありますが、修正されません。これを単一の関数テンプレートにまとめることはできますか?

4

6 に答える 6

39

変更したいようです:

friend ostream& operator << (ostream& out, const Base<T>& e);

に:

template<class T>
friend ostream& operator << (ostream& out, const Base<T>& e);
于 2010-10-28T04:58:58.400 に答える
22

Gcc は正しく警告しています。見た目は (Base 引数を取ります) にもかかわらず、関数テンプレートではありません。

クラス定義には、フレンド関数の非テンプレート宣言 (テンプレートなし) がありますが、後のフレンド関数定義は関数テンプレートです (つまり、template.. で始まります)。

また、 operator<< は Base * を取ります。これは正しくありません。組み込みのセマンティクスを保持するには、Base const & である必要があります

おそらく、あなたは以下のようなものを見ているでしょう:

template <typename T> 
class Base { 
  public: 
    friend ostream& operator << (ostream &out, Base<T> const &e){
       return out;
    }; 
}; 

int main(){
   Base<int> b;
   cout << b;
}

完全にテンプレート化したい場合は、おそらくこれが必要です。しかし、これが以前のものよりもどれほど有用かはわかりません。ルックアップには ADL が含まれるため、T が U と等しくない条件を解決することはできません (呼び出しがこのクラスに関連しないコンテキストからのもの、たとえば「メイン」関数からのものである限り)。

template <typename T>  
class Base {  
  public:  
    template<class U> friend ostream& operator << (ostream &out, Base<U> const &e){ 
       return out; 
    };  
};

int main(){ 
   Base<int> b; 
   cout << b; 
} 
于 2010-10-28T05:00:05.550 に答える
9

おそらくあなたが探しているのは:

template <typename T>
class Base;

template <typename T>
ostream& operator<< (ostream &, const Base<T>&);

template <typename T>
class Base
{
  public:
    template<>
    friend ostream& operator << <T>(ostream &, const Base<T> &);
};

template <typename T>
ostream& operator<< ( ostream &out, const Base<T>& e )
{
    return out << e->data;
}

これは、テンプレートの単一のインスタンス化、つまりオペレーターのテンプレートパラメーターがクラスのテンプレートパラメーターと一致するインスタンス化のみを友達にします。

更新:残念ながら、それは違法です。MSVCとComeauの両方がそれを拒否します。これは、元のエラーメッセージがこのアプローチをほぼ正確に示唆している理由の疑問を提起します。

于 2010-10-28T05:08:21.500 に答える
6

変化

friend ostream& operator << (ostream& out, const Base<T>& e);

friend ostream& operator << <T>(ostream& out, const Base<T>& e);

同様に機能するはずです-私はこの方法で同じ問題を解決しました。

于 2012-12-13T15:06:32.577 に答える
-3

変化する

ostream& operator<< (ostream &out, Base<int> *e) {
    out << e->data;
    return out;
}

ostream& operator<< (ostream &out, T *e) {
    out << e->data;
    return out;
}
于 2010-10-28T04:46:44.070 に答える