operator<< <T, TSIZE>
テンプレートの特殊化であるあなたのように参照するには、プライマリテンプレートの宣言が表示されている必要があります。次に、パラメータとして表示されるためoperator<<
、の宣言が必要です。MyTest
// Declare MyTest because operator<< needs it
template<class T, unsigned int TSIZE> class MyTest;
// Declare primary template
template<class T, unsigned int TSIZE>
inline std::ostream& operator<<(std::ostream& lhs, const MyText<T, TSIZE>& rhs);
template<class T, unsigned int TSIZE> class MyTest
{
// Specialization MyTest<T, TSIZE> only declares
// specialization operator<< <T, TSIZE> as friend
// Note that you can just use '<>' to designate the specialization,
// template parameters are deduced from the argument list in this case
inline friend std::ostream& operator<< <> (std::ostream &lhs, const MyTest<T, TSIZE> &rhs);
};
あなたが持っている定義はそれらの宣言と一致する必要があります。operator<<
テンプレートであるため、その定義はすべての可能性でヘッダーに含まれている必要があることに注意してください。
これらすべてのプリエンプティブ宣言を作成する際に必要な作業が少なくて済む代替手段は、を必要とするMyTest<T, TSIZE>
特殊化だけでなく、テンプレート全体をフレンドとして宣言することMyTest<T, TSIZE>
です。
// in MyTest definition
template<typename U, unsigned USIZE>
inline friend std::ostream& operator<<(std::ostream& lhs, const MyTest<U, USIZE>& rhs);
使用する定義もそのような宣言と一致する必要があります(テンプレートパラメーターの名前は、宣言と定義の一致とは関係ありません)。
完全を期すために、クラステンプレートの友達になると、別の方法はクラステンプレート定義で定義することです。これは、各専門分野に固有の非テンプレートフレンド関数を定義します。
// in MyTest definition
friend std::ostream& operator<<(std::ostream& lhs, MyTest const& rhs)
{ /* implementation */ }
このような関数を参照することは不可能であり(たとえば&ns::operator<<
、他のオプションとは異なり、機能しません)、ADLを介してのみ検出されます。