The topic of this section is to use member templates to accept all compatible types
The author explains his point of view through a sample of smart pointers.
Before we learn the terms of this section, we need to clarify the issue of implicit conversion.
For example, the following code:
#include<iostream>using namespace std;class A{public: explicitA(int i):a(i){}; A(const A&obj):a(obj.a) { }private: int a;};int main(){ intvalue =0; value;//编译不通过。由于构造函数中有explicit限定符 return0; }
We know that the compilation does not pass because of the existence of the explicit qualifier.
Let's look at the code in another section of the book:
template<typename T> class SmartPrt{ public: explicit SmartPtr(T* realPtr); …… }; SmartPtr<Top> pt1=SmartPtr<Middle>(new Middle); SmartPrt<Top> pt2=SmartPrt<Bottom>(new Bottom); SmartPrt<const Top> pct2=pt1;
我们能够知道,由于`SmartPtr<Top>`类型和`SmartPtr<Middle>`
The
type is different. Plus the explicit qualifier in explicit smartptr<middle> , smartptr<top> pt1=smartptr<middle > (new middle); This code compilation does not pass.
and the compiler does not think smartptr<top> type and smartptr<middle> type has an inheritance relationship.
in order to be able to achieve mutual transformation. Be able to join the main thrust of this section to solve the above problems.
For example, the following code:
Template<typaname t> class smartptr{public : Template<typename u> smartprt (const smartprt<u>& Other": heldprt (Other.get ()) {}; t* get () const { return Heldprt;} ...... private : t* heldprt; }; Smartptr<top> pt1=smartptr<middle> (new middle); Smartprt<top> pt2=smartprt<bottom> (new Bottom); Smartprt<const top> pct2=pt1;
We have added a member function template. Because TypeName T and TypeName U are two types, and there are no explicit keywords in the constructor, they are not blocked heldPrt(other.get())的隐式转换 .
Therefore, the above code can be compiled.
The author concludes by listing an excerpt from the TR1 specification for TR1::SHARED_PTR
For example, the following:
Template<classT>class shared_ptr{ Public:Template<classY>Explicit shared_ptr(y* p);Template<classY>shared_ptr(shared_ptr<Y>Const& R);Template<classY>Explicit shared_ptr(weak_ptr<y>Const& R);Template<classY>Explicit shared_ptr(auto_ptr<Y>Const& R);Template<classY>shared_ptr&operator=(shared_ptr<Y>Const& R);Template<classY>shared_ptr&operator=(auto_ptr<Y>Const& R); ...... };
We can see that the only generalization copy constructor above is not explicit, which means that the implicit conversion of shared_ptr is agreed, while the other smart pointer conversions are not agreed.
Another place to note here is the declaration of the generalization copy constructor (member template) in class. Does not prevent the compiler from generating their own copy constructor (Non-template), in other words. Assuming that the program only writes a generalization of the copy constructor, then the compiler will voluntarily generate a non-generalized version number, if you do not want this default version number, it must not be lazy. A copy constructor with two version numbers is written.
The code is as follows:
template<typaname T> class SmartPtr{ public: template<typename U> SmartPrt(const SmartPrt<U>& other) :heldPrt(other.get()){}; SmartPtr(){}//假设不写自己的非泛化构造函数,编译器会自己主动生成自己的默认非泛化构造函数。 getconst{return heldPrt;} …… private: T* heldPrt; };
At last:
The author summarizes for example the following:
1. Use member function templates (member function template) to generate a "Accept all compatible type" functions.
2. If you declare member templates for "Generalization copy construction" or "generalization assignment operation", you still need to declare the normal copy constructor and copy assignment operator.
Effective C + + clause 45