Presenting the Problem
Suppose you've designed a class template that represents a collection of some sort, for instance, an array:
template <class T> class Array
{
std::vector<T> v;
public:
explicit Array(size_t n=0) : v(n) {}
~Array();
//accessors
const T& operator[] (int idx) const;
size_t size() const;
//mutators
T& operator[] (int idx);
void add_element(const T& t);
void clear();
//..
};
Assigning two
Array objects works fine so long as they have exactly the same type:
Array<int> a1, a2;
a1.add_element(5);
a2=a1; //OK, using implicit assignment operator
Notice that
Array doesn't even declare an assignment operatorthe
compiler generated assignment operator is called in this case. Now, suppose you want to assign two different
Array objects, one containing
int and the other one containing
double:
Array<int> a;
Array<double> d;
a.add_element(5);
d=a; //compilation error
Although C++ allows you to assign plain
int to
double, it won't let you assign
Array<int> to
Array<double>. Intuitively, you know what such an assignment should do: copy every
a[n] to its matching
d[n].
Declaring an Asymmetrical Assignment Operator
In C++ 101, you learned that a canonical assignment operator of class X takes const X& as its parameter and returns X&. However, to enable the assignment of different specializations, you need to use a different type of an assignment operator. Such an assignment operator has no special name in the C++ literature, so I will refer to it as an asymmetrical assignment operator. The asymmetry is accomplished by using two different template parameters within the same member template. Let's call these template parameters T and T2.
First, add a declaration of a member template operator= to Array (highlighted):
template <class T> class Array
{
std::vector<T> v;
public:
explicit Array(size_t n=0) : v(n) {}
~Array();
//accessors
const T& operator[] (int idx) const;
size_t size() const;
//mutators
T& operator[] (int idx);
void add_element(const T& t);
void clear();
//..
template <class T2>
Array<T>& operator=(const Array<T2> &);
};
Notice that the assignment operator's return type and its parameter aren't the same.