web-dev-qa-db-ja.com

friend宣言が非テンプレート関数を宣言しています

以下のコードに似た基本クラスがあります。 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;
}

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

45
mike_b

変更したいようです:

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

に:

template<class T>
friend ostream& operator << (ostream& out, const Base<T>& e);
33
Nathan Pitman

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に等しくない条件に解決することはできません(呼び出しがこのクラスに関連しないコンテキスト、たとえば 'main'関数からである限り)

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; 
} 
17
Chubsdad

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

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;
}

これは、オペレーターのテンプレートパラメーターがクラスのテンプレートパラメーターと一致するテンプレートの1つのインスタンス化のみに対応しています。

更新:残念ながら、それは違法です。 MSVCとComeauはどちらも拒否します。これは、元のエラーメッセージがこのアプローチをまったく正確に示唆した理由の問題を提起します。

10
Ben Voigt

変化

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

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

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

4

変化

friend ostream& operator << (ostream &out, Base<T> *e)`

template<T> friend ostream& operator << (ostream &out, Base *e)
0
Elías Arriaga