In C++, even though a function generated from a function template has the same name and the same type as the ordinary function, they are never equivalent. Besides, the non-template function is more preferred:
1 | template <typename T> |
On top of that, it is not easy to templify a copy/move constructor because the compiler may implicitly define a copy/move constructor.
Example
1 | class Obj { |
It still uses the predefined copy constructor:
1 | Obj a; |
The reason is that a member function template is never a special member function and can be ignored when the latter is needed. Taking the above for an instance, the implicitly generated copy constructor is chosen.
Deleting Predefined Copy Constructor
One may want to delete the the predefined copy constructor:
1 | class Obj { |
However, this would result in an error when trying to copy
Obj
:
1 | Obj a; |
const volatile
Trick
There is a tricky solution for this: deleting the copy constructor
with const volatile
type. With this, it prevents another
copy constructor from being implicitly generated1 and
the template copy constuctor can be preferred over the deleted copy
constructor for non-volatile types:
1 | class Obj { |
The overload resolution candidates now are
Obj(const volatile Obj&)
and
Obj<Obj&>(const Obj&)
, and the latter is a
better match:
1 | Obj a; |
Similarly, we can templify move constructor or other special member
functions by deleting the predefined special member functions for
const volatile
type.
1 | class Obj { |
Note that this still leads to error if we try to operate
Obj
with volatile type. Fortunately, it is rarely used.
A non-template constructor for class X is a copy constructor if its first parameter is of type
X&
,const X&
,volatile X&
orconst volatile X&
↩︎