我有以下代码段:
template < typename T1, typename T2 >
class Test
{
public:
Test() = default;
private:
template < typename T1_, typename T2_ >
friend Test< T1_, T2_ > operator*( const Test< T1_, T2_ >& lhs, const Test< T1_, T2_ >& rhs )
{
return Test< T1_, T2_ >();
}
};
int main( int argc, char* argv[] )
{
{
Test< int, int > t1;
Test< int, int > t2;
Test< int, int > t3 = t1 * t2;
}
{
Test< double, double > t1;
Test< double, double > t2;
Test< double, double > t3 = t1 * t2;
}
}
使用clang 3.9,代码编译正常,使用gcc 6.3.1我收到以下错误:
redefinition of ‘template<class T1_, class T2_> Test<T1_, T2_> operator*(const Test<T1_, T2_>&, const Test<T1_, T2_>&)’
friend Test< T1_, T2_ > operator*( const Test< T1_, T2_ >& lhs, const Test< T1_, T2_ >& rhs )
哪种编译器是对的?
如果是gcc,我怀疑,如何在课堂上正确声明模板化运算符*。对于依赖于参数的查找,我需要使用类内定义。
答案 0 :(得分:3)
GCC是正确的,因为Test
的每个实例都定义了模板operator*
,它们的签名完全相同,不依赖于T1
或T2
。 operator*
不一定是这里的模板,只是Test
的特定实例化的重载:
template < typename T1, typename T2 >
class Test
{
friend Test operator*(const Test& lhs, const Test& rhs)
{
return Test();
}
};
int main( int argc, char* argv[] )
{
{
Test< int, int > t1;
Test< int, int > t2;
Test< int, int > t3 = t1 * t2;
}
{
Test< double, double > t1;
Test< double, double > t2;
Test< double, double > t3 = t1 * t2;
}
}
这将定义operator*
的两个非模板重载,每个实例化Test
一个。