I'm a little new to C++ templating, and I'm having trouble understanding this behaviour. Basically, I have a templated class, and I want to define the = operator between the class and the same class with any template parameter. The problem is that the overloaded version of the = operator is only being used when the two instances of the class have distinct template parameters. It's not being called when the same class types are being used.

I've isolated the problem as much as I can in the following code:

include <iostream>
using namespace std;

template <class T> 
class A
    template <class X> A<T>& operator=(const A<X>& a);

template <class T> 
template <class X> 
A<T>& A<T>::operator=(const A<X>& a) 
    cout << "A's operator= called" << endl;
    return *this;

int main()
    A<double> ad1;
    A<double> ad2;
    A<float> af;
    cout << "Assigning an A<double> to an A<float>:" << endl;
    ad1 = af;
    cout << "Assigning an A<double> to an A<double>:" << endl;
    ad1 = ad2;
    return 0; 

Which has the output:

Assigning an A<double> to an A<float>:
A's operator= called
Assigning an A<double> to an A<double>:

Is this the way C++ is supposed to work? I'm using the GNU C++ compiler. Shouldn't the compiler recognise that the operator='s template parameters can be made to match the requested operation? Or do I just have to define an operator= for the specific case of when the template parameters are equal?

The reason for this to happen is that the compiler generates a default = operator for any class that doesn't provide one. So, in this case, the compiler generates a = operator for A<double> = A<double> that has a better match than the A<double> = A<X>. So you would have to implement the non-template operator =(const A<T>& a) too.

I don't know a trick to get it to work without that second operator definition. Maybe template specialization of the operator will work, but would effectively be the same (still have two implementations of the operator).

This article has been dead for over six months. Start a new discussion instead.