In order to implicitly convert all compatible types for a template class, we neet not a constructor function but a constructor template - member functoin templates that generate member functions of a class.
Implicit conversion is a big convenient advantage offered by pointers: derived class pointers convert into base class pointers implicitly, pointers to non-
const objects convert into pointers to
const implicitly, etc. For a three-level hierarchy, following code makes perfect sense:
In the world of template, we’d really like to emulate such conversions for our user-defined smart pointer classes:
However, there’s no inherent relationship among different instantiations of the same template, so compilers view
SmartPtr<Top> as completely different classes. We need to write smart pointer constructors that is not only able to construct
SmartPtr<Middle>, but also capable to convert any compatible types in the hierarchy (we may extend the hierarchy in the future and add
class BelowBottom: public Bottom). In principle, such constructors are countless.
Considering the fact that a template can be instantiated to generate an unlimited number of functions, what we need here is not a constructor function, but a constructor template, the member function templates (also known as member templates) that generate member functions of a class:
Constructors like this - ones that create one object from anothe object whose type is a different instantiation of the same template (e.g., create a
SmartPtr<T> from a
SmartPtr<U>) - are known as generalized copy constructors.
However, this member template will generate more member functions than we need: as declared, it is possible to create a
SmartPtr<Bottom> from a
SmartPtr<Top>, which is contrary to the meaning of public inheritance (item 32). We need to restrict the conversions to those we want:
Since we initialize
SmartPtr<T>'s data member of type
T* with the pointer of type
U* held by
SmartPtr<U>, the code above will compile only if there is an implicit conversion from a
U* pointer to a
T* pointer, and this is exactly what we want.
Apart from constructors, we can also apply member function tmeplates to assignment. A good example is from TR1’s
shared_ptr (item 13):
- the generalized copy constructor is not declared
explicitin order to support implicit conversion from one type of
- All other constructors are
explicit, so implicit conversion from a built-in pointer or other smart pointer type is not permitted (explicit conversion via a cast is okey).
tr1::shared_ptrconstructors and assignment operators are not declared
auto_ptrwill be modifies when they’re copyed (item 13).
- both a generalized copy constructor (and assignment) as well as the “normal” copy constructor (and copy assignment) are declared, because declaring a generalized copy constructor (a member template) in a class doesn’t keep compilers from generating their own copy constructor (a non-template version), so if we want to control all aspect of copy construction, we declare both.