条款45:运用成员函数模板接收所有兼容类型

Use member function templates to accept "all compatible types".

class Top { ... };
class Middle: public Top { ... };

template<typename T>
class SmartPtr {
public:
    explicit SmartPtr(T* realPtr);
    ...
};

SmartPtr<Top> pt1 = SmartPtr<Middle>(new Middle);    // 无法通过编译

同一个 template 的不同具现体(instantiations)之间并不存在固有关系,所以编译器会视 SmartPtr<Middle>SmartPtr<Top> 为完全不同的两个类。

member function templates

通过 member function templates 可以实现 templates 之间的自动转型:

template<typename T>
class SmartPtr {
public:
    template<typename U>
    Smart(const SmartPtr<U>& other);
};

但在实际应用中,我们希望根据一个 SmartPtr<Bottom> 创建一个 SmartPtr<Top> ,却不希望通过SmartPtr<Top>创建一个 SmartPtr<Bottom> 。所以可以使用成员初值列(member initialization list)来初始化 SmartPtr<T> 之类型为 T* 的成员变量,从而增加一条限定条件,即“存在某个隐式转换可以将一个 U* 指针转为一个 T* 指针”时,编译才可通过:

template<typename T>
class SmartPtr {
public:
    template<typename U>
    SmartPtr(const SmartPtr<U>& other): heldPtr(other.get()) { ... }
    T* get() const { return heldPtr; }
private:
    T* heldPtr;
};

Last updated

Was this helpful?