模板化类中友元运算符的多个定义

Multiple definitions of friend operator in templated class

本文关键字:定义 运算符 友元      更新时间:2023-10-16

我有以下代码片段:

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,我如何在类中正确声明模板化运算符*。类内定义对我来说对于参数依赖查找是必要的。

GCC 是正确的,因为Test的每个实例化都定义了模板operator*,这些模板是相同的,因为它们的签名不依赖于T1T2operator*在这里不需要是模板,只是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的每个实例化。