自己的智能指针的模板专业化

时间:2017-10-07 21:00:47

标签: c++ pointers smart-pointers template-specialization

我有自己的智能指针类实现。

template<class Pointee>
class SmartPtr {
private:
    Pointee* _pointee;
    SmartPtr(SmartPtr &);
public:
    explicit SmartPtr(Pointee * pt = 0);
    ~SmartPtr();
    SmartPtr& operator=(SmartPtr&);
    operator Pointee*() const { return _pointee; }
    bool operator!() const { return _pointee != 0; }
    bool defined() const { return _pointee != 0; }
    Pointee* operator->() const { return _pointee; }
    Pointee& operator*() const { return *_pointee; }
    Pointee* get() const { return _pointee; }
    Pointee* release();
    void reset(Pointee * pt = 0);
};

template<class Pointee>
class SmartPtr<SmartPtr<Pointee>> {
private:
    Pointee* _pointee;
    SmartPtr(SmartPtr &);
public:
    explicit SmartPtr(SmartPtr<Pointee> * pt = 0);
    ~SmartPtr();
    SmartPtr& operator=(SmartPtr&);
    operator Pointee*() const { return *_pointee; }
    bool operator!() const { return _pointee != 0; }
    bool defined() const { return _pointee != 0; }
    Pointee& operator->() const { return _pointee; }
    Pointee& operator*() const { return *_pointee; }
    Pointee* get() const { return _pointee; }
    Pointee* release();
    void reset(Pointee * pt = 0);
};

template<class Pointee>
SmartPtr<Pointee>::SmartPtr(SmartPtr &spt) :_pointee(spt.release()) {
    return;
}

template<class Pointee>
SmartPtr<Pointee>::SmartPtr(Pointee * pt) : _pointee(pt) {
    return;
}

template<class Pointee>
SmartPtr<SmartPtr<Pointee>>::SmartPtr(SmartPtr<Pointee>* pt) : _pointee(pt) {
    return;
}

template<class Pointee>
SmartPtr<Pointee>::~SmartPtr() {
    delete _pointee;
}

template<class Pointee>
SmartPtr<Pointee>& SmartPtr<Pointee>::operator=(SmartPtr &source)
{
    if (&source != this)
        reset(source.release());
    return *this;
}

template<class Pointee>
Pointee * SmartPtr<Pointee>::release() {
    Pointee* oldSmartPtr = _pointee;
    _pointee = 0;
    return oldSmartPtr;
}

template<class Pointee>
void SmartPtr<Pointee>::reset(Pointee * pt) {
    if (_pointee != pt)
    {
        delete _pointee;
        _pointee = pt;
    }
    return;
}

这个想法我能做到这一点:

SmartPtr<SmartPtr<SmartPtr<Time>>> sp3(new SmartPtr<SmartPtr<Time>>(new SmartPtr<Time>(new Time(0, 0, 1))));

Time 它是我自己的测试类。它有方法hours(),它在我在构造函数中设置的控制台计数中显示。

我可以在控制台中显示这样的小时数:

cout << sp2->hours() << endl;

而不是:

cout << sp3->operator->()->operator->()->hours() << endl;

我可以这样做是因为我在opertor->()的第一堂课时我返回Pointee*

template<class Pointee>
    class SmartPtr {...}

并且

template<class Pointee>
class SmartPtr<SmartPtr<Pointee>> {...}

opertor->() {}返回Pointee &

但我可以解决一些错误。

Error C2440 initialization: can not be converted "SmartPtr<Time> *" in "Time *" 
Error C2439 SmartPtr<SmartPtr<Time>>::_pointee: unable to initialize member

2 个答案:

答案 0 :(得分:0)

在第50行,你有:

SmartPtr<SmartPtr<Pointee>>::SmartPtr(SmartPtr<Pointee>* pt) : _pointee(pt) {

应该是

SmartPtr<SmartPtr<Pointee>>::SmartPtr(SmartPtr<Pointee>* pt) : _pointee(pt->get()) {

此外,您似乎错过了专门的SmartPtr-to-SmartPtr版本的析构函数实现。

但最后,必须说

你在这里所做的一切都是错的。这是糟糕的,令人困惑的代码,我强烈建议你不要使用它。

答案 1 :(得分:0)

如果你真的想要获得operator->()递归提取SmartPtr以获得内部no - SmartPtr指针......我认为你应该避免专门化SmartPtr 1}}类,用于SmartPtr模板参数,但您必须“专门化”operator->()

我的意思是......

(1)删除SmartPtr<SmartPtr<Pointee>>专业化

(2)在SmartPtr实施之前,开发一个类型特征来检测Pointee是否为SmartPtr,例如

template <typename>
class SmartPtr;

template <typename>
struct isSP : public std::false_type
 { };

template <typename P>
struct isSP<SmartPtr<P>> : public std::true_type
 { };

(3)要求将operator->()真正执行到您通过标记调度选择的另一个函数,例如

auto const operator->() const
 { return getPtr(isSP<Pointee>{}); }

(4)实现不同版本的dispatched函数在真实情况下是递归的,并以false形式返回指针,例如

auto const getPtr (std::true_type const &) const 
 { return _pointee->operator->(); }

auto const getPtr (std::false_type const &) const 
 { return _pointee; }

现在(在main()中)你可以写'

std::cout << sp3->hours() << std::endl;

(但你确定这是一个好主意吗?)

无论如何......遗憾的是,此解决方案使用autogetPtr()的{​​{1}}返回类型,因此仅适用于C ++ 14;如果你想要一个C ++ 11(或C ++ 98)解决方案,它会有点复杂。

以下是一个完整的工作示例

operator->()