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

Multiple definitions of friend operator in templated class

我有以下代码片段:

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

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* 的两个 non-template 重载,一个用于 Test 的每个实例化。