Definition
The precise implementation details of the assignment operator depend, of course, on how your template stores its elements. However, the general idea is to break down the collection to its individual elements, assigning every
Array<T2>[n] to its matching
Array<T>[n]. Here is a complete
definition of the assignment operator you've just declared:
template <class T>
template <class T2>
Array<T>& Array<T>::operator=(const Array<T2>& t2)
{
if (this == (void*) &t2) //avoid self assignment
return *this;
clear(); //remove existing elements
for (size_t i=0; i<t2.size(); ++i)
v.push_back(t2[i]); //implicit conversion of T2 to T1
return *this;
}
Pay attention to the first two lines of the definition. This part:
template <class T>
template <class T2>
indicates a definition of a member template of a class template.
Now, you can assign different Array specializations:
Array<int> a;
Array<double> d;
a.add_element(10);
a.add_element(20);
d=a; //OK, d contains the elements 10.0 and 20.0
The asymmetric assignment operator doesn't disable type safety. If you try to assign the following objects:
Array <string> words;
Array <int> num;
num=words; //compilation error
Your compiler will complain because there is no implicit
string to
int conversion.
Design Refinements
The compiler-generated assignment operator, not the asymmetric one, is still used when you assign objects of the same type:
Array<int> a1, a2;
a2=a1; //calls compiler-generated operator=
Remember: the asymmetric assignment operator is called only when the operands have different types. This discovery leads to a picking question. If the two operands have different types, don't they always have different addresses as well? In other words, isn't the code that checks for self-assignment redundant? In the overwhelming majority of cases, it is, indeed, redundant. Yet it's still possible to write codehowever uncommonthat assigns the same object to itself using the asymmetric assignment operator. Here's an example:
a=*(Array<long>*)&a;
You wouldn't write such code. However, third-party libraries might contain gems like this. Therefore, the self-assignment test protects you from unpleasant runtime surprises.