📄 smartptr.h
字号:
void Swap(AllowConversion&)
{}
};
////////////////////////////////////////////////////////////////////////////////
// class template DisallowConversion
// Implementation of the ConversionPolicy used by SmartPtr
// Does not allow implicit conversion from SmartPtr to the pointee type
// You can initialize a DisallowConversion with an AllowConversion
////////////////////////////////////////////////////////////////////////////////
struct DisallowConversion
{
DisallowConversion()
{}
DisallowConversion(const AllowConversion&)
{}
enum { allow = false };
void Swap(DisallowConversion&)
{}
};
////////////////////////////////////////////////////////////////////////////////
// class template NoCheck
// Implementation of the CheckingPolicy used by SmartPtr
// Well, it's clear what it does :o)
////////////////////////////////////////////////////////////////////////////////
template <class P>
struct NoCheck
{
NoCheck()
{}
template <class P1>
NoCheck(const NoCheck<P1>&)
{}
static void OnDefault(const P&)
{}
static void OnInit(const P&)
{}
static void OnDereference(const P&)
{}
static void Swap(NoCheck&)
{}
};
////////////////////////////////////////////////////////////////////////////////
// class template AssertCheck
// Implementation of the CheckingPolicy used by SmartPtr
// Checks the pointer before dereference
////////////////////////////////////////////////////////////////////////////////
template <class P>
struct AssertCheck
{
AssertCheck()
{}
template <class P1>
AssertCheck(const AssertCheck<P1>&)
{}
template <class P1>
AssertCheck(const NoCheck<P1>&)
{}
static void OnDefault(const P&)
{}
static void OnInit(const P&)
{}
static void OnDereference(P val)
{ assert(val); (void)val; }
static void Swap(AssertCheck&)
{}
};
////////////////////////////////////////////////////////////////////////////////
// class template AssertCheckStrict
// Implementation of the CheckingPolicy used by SmartPtr
// Checks the pointer against zero upon initialization and before dereference
// You can initialize an AssertCheckStrict with an AssertCheck
////////////////////////////////////////////////////////////////////////////////
template <class P>
struct AssertCheckStrict
{
AssertCheckStrict()
{}
template <class U>
AssertCheckStrict(const AssertCheckStrict<U>&)
{}
template <class U>
AssertCheckStrict(const AssertCheck<U>&)
{}
template <class P1>
AssertCheckStrict(const NoCheck<P1>&)
{}
static void OnDefault(P val)
{ assert(val); }
static void OnInit(P val)
{ assert(val); }
static void OnDereference(P val)
{ assert(val); }
static void Swap(AssertCheckStrict&)
{}
};
////////////////////////////////////////////////////////////////////////////////
// class NullPointerException
// Used by some implementations of the CheckingPolicy used by SmartPtr
////////////////////////////////////////////////////////////////////////////////
struct NullPointerException : public std::runtime_error
{
NullPointerException() : std::runtime_error("")
{ }
const char* what() const throw()
{ return "Null Pointer Exception"; }
};
////////////////////////////////////////////////////////////////////////////////
// class template RejectNullStatic
// Implementation of the CheckingPolicy used by SmartPtr
// Checks the pointer upon initialization and before dereference
////////////////////////////////////////////////////////////////////////////////
template <class P>
struct RejectNullStatic
{
RejectNullStatic()
{}
template <class P1>
RejectNullStatic(const RejectNullStatic<P1>&)
{}
template <class P1>
RejectNullStatic(const NoCheck<P1>&)
{}
template <class P1>
RejectNullStatic(const AssertCheck<P1>&)
{}
template <class P1>
RejectNullStatic(const AssertCheckStrict<P1>&)
{}
static void OnDefault(const P&)
{
STATIC_CHECK(false, This_Policy_Does_Not_Allow_Default_Initialization);
}
static void OnInit(const P& val)
{ if (!val) throw NullPointerException(); }
static void OnDereference(const P& val)
{ if (!val) throw NullPointerException(); }
static void Swap(RejectNullStatic&)
{}
};
////////////////////////////////////////////////////////////////////////////////
// class template RejectNull
// Implementation of the CheckingPolicy used by SmartPtr
// Checks the pointer before dereference
////////////////////////////////////////////////////////////////////////////////
template <class P>
struct RejectNull
{
RejectNull()
{}
template <class P1>
RejectNull(const RejectNull<P1>&)
{}
static void OnInit(P val)
{ if (!val) throw NullPointerException(); }
static void OnDefault(P val)
{ OnInit(val); }
void OnDereference(P val)
{ OnInit(val); }
void Swap(RejectNull&)
{}
};
////////////////////////////////////////////////////////////////////////////////
// class template RejectNullStrict
// Implementation of the CheckingPolicy used by SmartPtr
// Checks the pointer upon initialization and before dereference
////////////////////////////////////////////////////////////////////////////////
template <class P>
struct RejectNullStrict
{
RejectNullStrict()
{}
template <class P1>
RejectNullStrict(const RejectNullStrict<P1>&)
{}
template <class P1>
RejectNullStrict(const RejectNull<P1>&)
{}
static void OnInit(P val)
{ if (!val) throw NullPointerException(); }
void OnDereference(P val)
{ OnInit(val); }
void Swap(RejectNullStrict&)
{}
};
////////////////////////////////////////////////////////////////////////////////
// class template ByRef
// Transports a reference as a value
// Serves to implement the Colvin/Gibbons trick for SmartPtr
////////////////////////////////////////////////////////////////////////////////
template <class T>
class ByRef
{
public:
ByRef(T& v) : value_(v) {}
operator T&() { return value_; }
// gcc doesn't like this:
operator const T&() const { return value_; }
private:
ByRef(const ByRef &);
ByRef& operator=(const ByRef &);
T& value_;
};
////////////////////////////////////////////////////////////////////////////////
// class template WrapTemplate (definition)
// suggested workaround for vc7 limitation with template template arguments
////////////////////////////////////////////////////////////////////////////////
template<template<typename> class C>
struct WrapTemplate
{
template<typename T>
struct In
{
typedef C<T> type;
};
// VC7 BUG - cannot access protected typedef
template<typename T>
struct PointerType : private C<T>
{
typedef typename C<T>::PointerType type;
};
// VC7 BUG - cannot access protected typedef
template<typename T>
struct StoredType : private C<T>
{
typedef typename C<T>::StoredType type;
};
};
////////////////////////////////////////////////////////////////////////////////
// class template SmartPtr (declaration)
// The reason for all the fuss above
////////////////////////////////////////////////////////////////////////////////
template
<
typename T,
class OwnershipPolicy = WrapTemplate<RefCounted>,
class ConversionPolicy = DisallowConversion,
class CheckingPolicy = WrapTemplate<AssertCheck>,
class StoragePolicy = WrapTemplate<DefaultSPStorage>
>
class SmartPtr;
////////////////////////////////////////////////////////////////////////////////
// class template SmartPtrDef (definition)
// this class added to adjust the ported SmartPtr to the original one.
// instead of writing SmartPtr<T,OP,CP,KP,SP> write SmartPtrDef<T,OP,CP,KP,SP>::type
////////////////////////////////////////////////////////////////////////////////
template
<
typename T,
template <class> class OwnershipPolicy = RefCounted,
class ConversionPolicy = DisallowConversion,
template <class> class CheckingPolicy = AssertCheck,
template <class> class StoragePolicy = DefaultSPStorage
>
struct SmartPtrDef
{
typedef SmartPtr
<
T,
WrapTemplate<OwnershipPolicy>,
ConversionPolicy,
WrapTemplate<CheckingPolicy>,
WrapTemplate<StoragePolicy>
>
type;
};
////////////////////////////////////////////////////////////////////////////////
// class template SmartPtr (definition)
////////////////////////////////////////////////////////////////////////////////
template
<
typename T,
class OwnershipPolicy,
class ConversionPolicy,
class CheckingPolicy,
class StoragePolicy
>
class SmartPtr
: public StoragePolicy::In<T>::type
, public OwnershipPolicy::In<typename StoragePolicy::template PointerType<T>::type>::type
, public CheckingPolicy ::In<typename StoragePolicy::template StoredType<T>::type>::type
, public ConversionPolicy
{
typedef typename StoragePolicy::template In<T>::type SP;
typedef typename OwnershipPolicy::template In<typename SP::PointerType>::type OP;
typedef typename CheckingPolicy::template In<typename SP::StoredType>::type KP;
typedef ConversionPolicy CP;
// VC7 bug
enum { OP_destructiveCopy = OP::destructiveCopy };
enum { CP_allow = CP::allow };
public:
typedef typename SP::PointerType PointerType;
typedef typename SP::StoredType StoredType;
typedef typename SP::ReferenceType ReferenceType;
typedef typename Select
<
OP_destructiveCopy,
SmartPtr,
const SmartPtr
>
::Result CopyArg;
private:
void OnKPReject()
{
if (OP::Release(GetImpl(*static_cast<SP*>(this)), true))
{
// if KP::IsDestructive(GetImpl(*this))
// call SP::Destroy() ?
}
}
class SmartPtrGuard
{
public:
typedef void (SmartPtr::*action_t)();
SmartPtrGuard(SmartPtr &sptr, action_t action)
: sptr_(sptr), action_(action), guard_(true)
{}
void Dismiss() { guard_ = false; }
~SmartPtrGuard()
{ if (guard_) (sptr_.*action_)(); }
private:
SmartPtrGuard(const SmartPtrGuard &);
SmartPtrGuard& operator=(const SmartPtrGuard &);
private:
SmartPtr &sptr_;
action_t action_;
bool guard_;
};
public:
SmartPtr()
{
SmartPtrGuard KPGuard(*this, &SmartPtr::OnKPReject);
KP::OnDefault(GetImpl(*this));
KPGuard.Dismiss();
}
//
// This constructor has exception safety problem
// If OP constructor throw - p might be leaked
// One solution is to add method to OP named OnInit with the following usage:
// OP::OnInit(GetImpl(*this), implicit_cast<SP&>(*this));
// The OP default constructor will have no throw guaranty
// and the OP::OnInit will decide if destroy should be invoked upon exception
//
SmartPtr(const StoredType& p) : SP(p)
{
//
// The following try catch only solve part of the exception safety problem.
// The solution might be wrong because KP might reject illegal pointers (not destructible via destroy like null com pointer).
// The complete solution might involve more tight connections between KP, OP and SP.
//
SmartPtrGuard KPGuard(*this, &SmartPtr::OnKPReject);
KP::OnInit(GetImpl(*this));
KPGuard.Dismiss();
}
SmartPtr(CopyArg& rhs)
: SP(rhs), OP(rhs), KP(rhs), CP(rhs)
{ GetImplRef(*this) = OP::Clone(GetImplRef(rhs)); }
template
<
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -