Ваш код выглядит немного сложнее.Например, вам не нужно наследовать политику, если она не заботится о каком-либо состоянии, а это не ваш случай.Кроме того, наличие классов требует указания спецификаторов доступа, так что вам может быть лучше с структурами.
В любом случае, интеллектуальные указатели не могут быть скопированы, что является основным приемом.Вы можете только передать право собственности (движимое понятие).Так что ваш конструктор копирования немного некорректен.У вас все еще может быть это, если это явно ваше намерение, но убедитесь, что у вас есть какой-нибудь счетчик ссылок.
Вот ваш код, упрощенный и работающий:
#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");
}
}