One common mistake is that a template constructor or assignment operator will not suppress the compiler generated one:
template <typename T>
class A {
public:
template <typename S>
A(A<S> const &);
template <typename S>
A & operator=(A<S> const &);
private:
int * i;
};
Although these functions look like the copy constructor and copy assignment operator, the compiler does not see it that way and generates the implicit versions anyway. The result is that any actions performed by these functions (eg. deep copy of a member) will not take place when the object is copied or assigned to from the same type:
void foo (A<int>);
void bar () {
A<int> a1;
foo (a1); // Implicitly generated copy ctor called
A<long> a2;
foo (a2); // Template ctor called.
A<int> a3;
a3 = a1; // Implicitly generated copy assignment operator called
a3 = a2; // Template assignment operator called
}
The reason for this behaviour is due to a special rule in overload resolution (13.3.3):
Given these definitions, a viable
function F1 is defined to be a better
function than another viable function
F2 if for all arguments i, ICSi(F1) is
not a worse conversion sequence than
ICSi(F2), and then
[...]
— F1 is a non-template function
and F2 is a function template
specialization, or, if not that,
In the examples above, overload resolution sees two functions with the same signature, one of which is a template. The non template function (the implicitly generated copy constructor/copy assignment operator) wins and so is called.