自己的智能指针的模板特化
Posted
技术标签:
【中文标题】自己的智能指针的模板特化【英文标题】:Template specialization for own smart pointer 【发布时间】:2017-10-07 21:00:46 【问题描述】:我有自己的智能指针类实现。
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
【问题讨论】:
你为什么想要这些? 只是为了好玩,但我坚持这个问题 对我来说一点也不好玩。更像是火车残骸。 【参考方案1】:如果你真的想获得一个 operator->()
递归提取 SmartPtr
以获得内部 no-SmartPtr
指针......我认为你应该避免专门化 SmartPtr
类,为 @987654325 @模板参数,但你必须“专门化”operator->()
我是说……
(1) 删除SmartPtr<SmartPtr<Pointee>>
特化
(2) 在SmartPtr
实现之前,开发一个type-traits 来检测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)通过示例实现不同版本的分派函数,在真情况下递归,在假情况下返回指针
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;
(但你确定这是个好主意吗?)
无论如何...不幸的是,此解决方案使用 getPtr()
和 operator->()
的 auto
返回类型,因此仅适用于 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) : aa0, bb0, cc0
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;
【讨论】:
【参考方案2】:在第 50 行你有:
SmartPtr<SmartPtr<Pointee>>::SmartPtr(SmartPtr<Pointee>* pt) : _pointee(pt)
应该是这样的
SmartPtr<SmartPtr<Pointee>>::SmartPtr(SmartPtr<Pointee>* pt) : _pointee(pt->get())
此外,您的专用 SmartPtr-to-SmartPtr 版本似乎缺少析构函数实现。
但最后不得不说
你在这里做的都是错的。这是糟糕的、令人困惑的代码,我强烈建议您不要使用它。
【讨论】:
以上是关于自己的智能指针的模板特化的主要内容,如果未能解决你的问题,请参考以下文章
C++模板类模板的全部特例化和局部特例化(偏特化-partial specialization)