自己的智能指针的模板专业化
Template specialization for own smart pointer
我有自己的智能指针class实现。
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
这是我自己的class,用于测试。它有方法 hours()
显示在控制台中我在构造函数中设置的小时数。
我可以像这样在控制台中显示小时数:
cout << sp2->hours() << endl;
而不是:
cout << sp3->operator->()->operator->()->hours() << endl;
我能做到这一点是因为我有第一个 class 其中 opertor->()
我 return Pointee*
.
template<class Pointee>
class SmartPtr {...}
和
template<class Pointee>
class SmartPtr<SmartPtr<Pointee>> {...}
哪里在opertor->()
我returnPointee &
.
但是有些错误我无法修复。
Error C2440 initialization: can not be converted "SmartPtr<Time> *" in "Time *"
Error C2439 SmartPtr<SmartPtr<Time>>::_pointee: unable to initialize member
第 50 行你有:
SmartPtr<SmartPtr<Pointee>>::SmartPtr(SmartPtr<Pointee>* pt) : _pointee(pt) {
应该是
SmartPtr<SmartPtr<Pointee>>::SmartPtr(SmartPtr<Pointee>* pt) : _pointee(pt->get()) {
此外,您似乎缺少针对您的专用 SmartPtr-to-SmartPtr 版本的析构函数实现。
不过最后不得不说的是
你在这里做的完全错了。这是糟糕的、令人困惑的代码,我强烈建议您不要使用它。
如果你真的想获得一个 operator->()
递归提取 SmartPtr
以获得内部 no-SmartPtr
指针......我认为你应该避免专门化SmartPtr
class, 对于 SmartPtr
模板参数,但是你必须 "specialize" 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) 实现不同版本的分派函数,在真实情况下递归,在错误情况下实现 return 指针,例如
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
return 类型,因此仅适用于 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;
}
我有自己的智能指针class实现。
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
这是我自己的class,用于测试。它有方法 hours()
显示在控制台中我在构造函数中设置的小时数。
我可以像这样在控制台中显示小时数:
cout << sp2->hours() << endl;
而不是:
cout << sp3->operator->()->operator->()->hours() << endl;
我能做到这一点是因为我有第一个 class 其中 opertor->()
我 return Pointee*
.
template<class Pointee>
class SmartPtr {...}
和
template<class Pointee>
class SmartPtr<SmartPtr<Pointee>> {...}
哪里在opertor->()
我returnPointee &
.
但是有些错误我无法修复。
Error C2440 initialization: can not be converted "SmartPtr<Time> *" in "Time *"
Error C2439 SmartPtr<SmartPtr<Time>>::_pointee: unable to initialize member
第 50 行你有:
SmartPtr<SmartPtr<Pointee>>::SmartPtr(SmartPtr<Pointee>* pt) : _pointee(pt) {
应该是
SmartPtr<SmartPtr<Pointee>>::SmartPtr(SmartPtr<Pointee>* pt) : _pointee(pt->get()) {
此外,您似乎缺少针对您的专用 SmartPtr-to-SmartPtr 版本的析构函数实现。
不过最后不得不说的是
你在这里做的完全错了。这是糟糕的、令人困惑的代码,我强烈建议您不要使用它。
如果你真的想获得一个 operator->()
递归提取 SmartPtr
以获得内部 no-SmartPtr
指针......我认为你应该避免专门化SmartPtr
class, 对于 SmartPtr
模板参数,但是你必须 "specialize" 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) 实现不同版本的分派函数,在真实情况下递归,在错误情况下实现 return 指针,例如
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
return 类型,因此仅适用于 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;
}