2017-02-03 26 views
1

У меня есть следующий фрагмент коды:Несколько определений оператора друга в шаблонном классе

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; 
    } 
} 

С лязгом 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, что я подозреваю, как я могу правильно объявить шаблонный оператор * в классе. Определение внутри класса необходимо для зависимого от аргумента поиска.

ответ

3

НКУ является правильным, так как каждый конкретизацией 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.

+0

Мне нужен шаблон для шаблонов. Однако объявление класса в классе и определение класса решали ошибку компиляции. Спасибо! – Trevir

+0

@Trevir зачем вам шаблон? –

+0

Для умножения объектов разного типа. 'Тест < int, int > t1, Тест t2; auto t3 = t1 * t2' является действительным и должен компилироваться. – Trevir