First look at the difference between the real pointer below and the smart pointer created by the template:
1 class top{...}; 2 public top{...}; 3 public middle{...}; 4 Top * p1 = new Bottom (); 5 Top * p2 = new Middle (); 6 // ok, there is no problem, there is really a relationship between the pointer and the object that is actually meant
But:
1Template<typename t>2 classsmartptr{3 Public:4 ExplicitSmartptr (T *ptr);5 ...6 };7smartptr<top> pt1 = smartptr<middle> (Newmiddle);8Smartptr<top> pt2 = smartptr<bottom> (NewBottom);9smartptr<Consttop> cp2 = pt1;
There is no relationship between the real facts on the left and right side of the equation, just a different template instance of the same template.
1 template<typename t>2class smartptr{3public: 4 template<typename u>5 smartptr (const smartptr<u> & Other ); 6 ... 7 };
The above Smartptr constructor is not explicit, because the default pointers can be implicitly converted to each other, so it is understandable to extend this to the smart pointer.
1Template<typename t>2 classsmartptr{3 Public:4Template<typename u>5Smartptr (ConstSmartptr<u> &Other )6: Heldptr (Other.Get()){...}7t*Get()Const{returnheldptr;}8 ...9 Private:TenS Mheldptr; One};
In this case, the definition of the above constructor means that there is an implicit conversion relationship where you can convert a pointer of type U to a pointer of type T, which is exactly the same behavior that we want to convert the pointers in an inheritance system to each other. Summary:use member function templates to generate and accept functions of all compatible typesfor member function template if you want to define a copy constructor and copy assignment operator (template version), you should also define generic constructors and copy assignment operators (not template versions).
Clause 45: Use member function templates to combine all compatible types