#include "stdafx.h"
#include <exception>
template<class T>
class NoCheck;
template<class T>
class EnforceNotNull
{
public:
//EnforceNotNull(const NoCheck<T>&){}//<<-----If this is uncommented it works
static void Check(T* p)
{
class NullPtrException : public std::exception
{
};
if (!p)
{
throw NullPtrException();
}
}
};
template<class T>
class NoCheck
{
public:
NoCheck(){}
NoCheck(const NoCheck&){}
NoCheck(const EnforceNotNull<T>&){}
operator EnforceNotNull<T>() {return EnforceNotNull<T>();}//<<-----This seams to not do its job
static void Check(T* p)
{/*Empty body*/}
};
template<class T, template<class> class CheckingPolicy>
class SmartPtr : public CheckingPolicy<T>
{
public:
SmartPtr(T* p)
{
Check(p);
}
template<class T1, template <class> class CheckingPolicy1>
SmartPtr(const SmartPtr<T1,CheckingPolicy1>& pattern):pointee_(pattern.pointee_),
CheckingPolicy<T>(pattern)
{
}
T* pointee_;
private:
};
int _tmain(int argc, _TCHAR* argv[])
{
SmartPtr<int,NoCheck> p1(nullptr);
SmartPtr<int,EnforceNotNull> p = p1;//I'm trying here to convert NoCheck to
// EnforceNotNull but it works for me only if I use ctor, if I use conversion optor
//(from
// NoCheck to EnforceNotNull) it doesn't work why?
return 0;
}
答案 0 :(得分:2)
我不明白为什么必须从检查策略继承SmartPtr。我也不明白为什么政策必须是模板本身。
为什么不简单:
#include <cstdlib>
#include <exception>
class EnforceNotNull
{
public:
template <class T>
static void Check(T* p)
{
class NullPtrException : public std::exception
{
};
if (!p)
{
throw NullPtrException();
}
}
};
class NoCheck
{
public:
template<class T>
static void Check(T* p)
{/*Empty body*/}
};
template<class T, class CheckingPolicy>
class SmartPtr
{
public:
SmartPtr(T* p)
{
CheckingPolicy::Check(p);
}
template<class T1, class CheckingPolicy1>
SmartPtr(const SmartPtr<T1,CheckingPolicy1>& pattern):pointee_(pattern.pointee_)
{
CheckingPolicy::Check(pointee_); //pattern's pointee_ may not pass our check
}
T* pointee_;
private:
};
int main()
{
SmartPtr<int,NoCheck> p1(NULL);
SmartPtr<int,EnforceNotNull> p = p1;
return 0;
}
答案 1 :(得分:1)
您的代码看起来有点过于复杂。例如,除非它关注某个状态,否则您不必继承策略,这不是您的情况。另外,拥有类需要使用访问说明符,因此使用结构可能会更好。
无论如何,智能指针无法复制,这是主要技巧。您只能转让所有权(可移动的概念)。所以你的拷贝构造函数有点不正确。如果这显然是你的意图,你可能仍然拥有它,但请确保你有一些参考计数器。
以下是您的代码,简化并正常工作:
#include <cstdio>
#include <cstddef>
#include <exception>
class NullPtrException : public std::exception
{
};
template <typename T>
struct EnforceNotNull
{
static void Check(T *p)
{
if (p == NULL)
{
throw NullPtrException();
}
}
};
template <typename T>
struct NoCheck
{
static void Check(T *)
{
}
};
template <typename T, template <typename> class CheckingPolicy>
class SmartPtr
{
T* pointee_;
public:
SmartPtr (T* p) :
pointee_ (p)
{
CheckingPolicy<T>::Check (pointee_);
}
template <typename T1, template <typename> class CheckingPolicy1>
SmartPtr (SmartPtr<T1, CheckingPolicy1> & pattern) :
pointee_ (pattern.get ())
{
CheckingPolicy<T>::Check (pointee_);
pattern.release ();
}
~SmartPtr ()
{
delete pointee_;
pointee_ = NULL;
}
T *get ()
{
return pointee_;
}
T *release ()
{
T *result = pointee_;
pointee_ = NULL;
return result;
}
};
int main()
{
try
{
printf ("Creating NULL pointer...\n");
SmartPtr<int, NoCheck> p1 (NULL);
printf ("Changing policy... \n");
SmartPtr<int, EnforceNotNull> p = p1;
printf ("This doesn't work :-(\n");
}
catch (const NullPtrException &)
{
printf ("GOTCHA!!!\n");
}
}
以下是使用MPL强制执行转换的方法:
#include <cstdio>
#include <cstddef>
#include <exception>
#include <boost/utility/enable_if.hpp>
#include <boost/type_traits/is_same.hpp>
#include <boost/mpl/or.hpp>
class NullPtrException : public std::exception {};
struct EnforceNotNull
{
template <typename T>
static void Check(T *p)
{
if (p == NULL)
throw NullPtrException();
}
};
struct NoCheck
{
template <typename T>
static void Check(T *) {}
};
template <typename T, typename CheckingPolicy>
class SmartPtr
{
T* p_;
public:
SmartPtr (T* p) :
p_ (p)
{
CheckingPolicy::Check (p_);
}
template <typename T1, typename PolicyT>
SmartPtr (SmartPtr<T1, PolicyT> & ptr,
// Enable moving from no checking pointer to any pointer
// or checking pointer to checking pointer.
// This makes it impossible to transfer checking to non-checking pointer.
typename boost::enable_if< boost::mpl::or_ <
boost::is_same<PolicyT, NoCheck>,
boost::is_same<PolicyT, CheckingPolicy> > >::type *dummy = NULL) :
p_ (ptr.get ())
{
CheckingPolicy::Check (p_);
ptr.release ();
}
~SmartPtr ()
{
delete p_;
p_ = NULL;
}
T *get () const
{
return p_;
}
T *release ()
{
T *result = p_;
p_ = NULL;
return result;
}
};
int main()
{
try
{
SmartPtr<int, NoCheck> p1 (NULL);
SmartPtr<int, EnforceNotNull> p2 = p1;
// SmartPtr<int, NoCheck> p3 = p2; // This will not compile.
}
catch (const NullPtrException &)
{
printf ("GOTCHA!!!\n");
}
}
答案 2 :(得分:1)
您的operator EnforceNotNull<T>()
函数不是const
,因此编译器不会将其包含在可能的转换函数集中。取消注释EnforceNotNull
复制ctor或将const
放在上面的函数上,您的代码应该可以正常工作。