本当に演算子を外部で定義し、このテンプレートのインスタンス化とタイプが一致する演算子のインスタンス化のみと友達にしたい場合、正しい構文は次のとおりです。
template <typename T> class test; // forward declare template class
template <typename T> // forward declare the templated operator
std::ostream& operator<<( std::ostream&, test<T> const & );
template <typename T>
class test { // define the template
friend std::ostream& operator<< <T>( std::ostream&, test<T> const & ); // befriend
};
template <typename T> // define the operator
std::ostream& operator<<( std::ostream& o, test<T> const & ) {
return o;
}
ほとんどの場合、定義をクラスから引き出すのは面倒な価値はありません。それでもヘッダーで定義を提供する必要があり、追加の作業が必要になることを考慮してください。
また、ルックアップに関してコンパイラーにはわずかな違いがあることに注意してください。関数がクラス定義内にインライン化されている場合、引数の1つが実際にテンプレートのタイプでない限り、コンパイラーはその関数を検出しないため、コンパイラーが行う必要のある可視性と作業量が効果的に減少します。 do(テンプレートoperator<<
がクラスの外部で定義されている場合、コンパイラは、見つかったすべての場所でオーバーロード解決の候補としてそれを見つけますa << b
が、2番目の引数がaでない場合はすべて破棄しますtest<T>
(そして、一致できないすべてのエラーメッセージの候補としてのテンプレート演算子operator<<
。これはすでに十分な長さのリストです)。