为自己的智能指针专门化模板

Template specialization for own smart pointer

本文关键字:专门化 指针 自己的 智能      更新时间:2023-10-16

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

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->(),它递归地提取SmartPtr以获得内部的no-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) 实现调度函数的不同版本,在true情况下递归,在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;

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

不管怎样。。。不幸的是,该解决方案使用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) : 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;    
}

在第50行,您有:

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

可能是

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

此外,您似乎缺少专门的SmartPtr到SmartPtr版本的析构函数实现。

但最后,必须说

你在这里做的完全是错误的。这是一个糟糕的、令人困惑的代码,我强烈建议您不要使用它