Browse DevX
Sign up for e-mail newsletters from DevX


Use an Asymmetric Assignment Operator to Assign Containers of Different Types-3 : Page 3

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;
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 code—however uncommon—that assigns the same object to itself using the asymmetric assignment operator. Here's an example:

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.

Danny Kalev is a certified system analyst and software engineer specializing in C++. He was a member of the C++ standards committee between 1997 and 2000 and has since been involved informally in the C++0x standardization process. He is the author of "The ANSI/ISO Professional C++ Programmer's Handbook" and "The Informit C++ Reference Guide: Techniques, Insight, and Practical Advice on C++."
Thanks for your registration, follow us on our social networks to keep up-to-date