template<class T>
class shared_ptr
{
public:
template<class Y> // 构造,来自任何兼容的
explicit shared_ptr(Y* p); //内置指针
template<class Y>
shared_ptr(shared_ptr<Y> const& r); //或shared_ptr、
template<class Y>
explicit shared_ptr(weak_ptr<Y> const& r); //或weak_ptr、
template<class Y>
explicit shared_ptr(auto_ptr<Y>& r); //或auto_ptr
template<class Y> //赋值,来自任何兼容的
shared_ptr& operator=(shared_ptr<Y> const& r); //shared_ptr
template<class Y>
shared_ptr& operator=(auto_ptr<Y>& r); //或auto_ptr
};
member function templates(成员函数模板)的效用不限于构造函数,它们常扮演的另一个角色是支持赋值操作。例如TR1的shared_ptr支持所有“来自兼容之内置指针”、tr1::shared_ptr、auto_ptr和tr1::weak_ptrs”的构造行为,以及所有来自上述各物(tr1::weak_ptrs除外)的赋值操作。下面是TR1规范中关于tr1::shared_ptr的一份摘录,其中强烈倾向声明template参数时采用关键字class而不采用typename(条款42曾说过,两者的意义在此语境下完全相同)。
上述所有构造函数都是explicit,惟有“泛化构造函数”除外。那意味从某个shared_ptr类型隐式转换至另一个shared_ptr类型是被允许的,但从某个内置指针或其他智能指针类型进行隐式转换则不被认可(如果是显式转换如cast强制转型动作倒是可以)。另一个趣味点是传递给tr1::shared_ptr构造函数和assignment操作符的auto_ptrs并未把声明为const,与之形成对比的则是tr1::shared_ptrs和tr1::weak_ptrs都以const传递。这是因为条款13说过,当你复制一个auto_ptrs,它们其实被改动了。
member fuction templates(成员函数模板)是个奇妙的东西,但它们并不改变语言基本规则。条款3说过,编译器可能为我们产生四个成员函数,其中两个是copy构造函数和copy assignment操作符。现在,tr1::shared_ptr声明了一个泛化copy构造函数,而显然一旦类型T和Y相同,泛化copy构造函数会被具现化为“正常的”copy构造函数。那么究竟编译器会暗自为tr1::shared_ptr生成一个copy构造函数呢?或当某个tr1::shared_ptr对象根据另一个同型的tr1::shard_ptr对象展开构造行为时,编译器会将“泛化copy构造函数模板”具体化呢?
一如我所说,member templates并不改变语言规则,而语言规则说,如果在程序需要一个copy构造函数(是个member template)并不会阻止编译器生成他们自己的copy构造函数(一个non-template),所以如果你想要控制copy构造的方方面面,你必须同时声明泛化copy构造函数和“正常的”copy构造函数。相同规则也适用于赋值(assignment)操作。下面是tr1::shared_ptr的一份定义摘要,例证上述所言:
template<class T>
class shared_ptr
{
public:
shared_ptr(shared_ptr const& r); //copy构造函数
template<class Y>
shared_ptr(shared_ptr<Y> const& r); //泛化copy构造函数
shared_ptr& operator=(shared_ptr const& r); //copy assignment
template<class Y>
shared_ptr& operator=(shared_ptr<Y> const& r); //泛化copy assignment
};
请记住
请使用member function templates(成员函数模板)生成“可接受所有兼容类型”的函数。
如果你声明member templates用于“泛化copy构造”或“泛化assignment操作”,你还是需要声明正常的copy构造函数和copy assignment操作符。