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

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

最佳答案

如果您真的想获取递归地提取operator->()以获得内部no-SmartPtr指针的SmartPtr,我认为您应该避免针对SmartPtr模板参数专门化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)举例来说,实现分派(dispatch)函数的不同版本在真实情况下是递归的,在错误情况下返回指针
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()operator->()返回类型,因此仅在C++ 14上有效;如果您想要C++ 11(或C++ 98)解决方案,则要复杂一些。

以下是完整的工作示例
#include <iostream>
#include <type_traits>

template <typename>
class SmartPtr;

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

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

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; }


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

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

    auto const operator->() const
     { return getPtr(isSP<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<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;
}


struct Time
 {
   int a, b, c;

   Time (int a0, int b0, int c0) : a{a0}, b{b0}, c{c0}
    { }

   int hours () const
    { return a; }
 };


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

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

08-16 23:52