📄 smartptr.h
字号:
static bool Release(const P&)
{ return true; }
static void Swap(DestructiveCopy&)
{}
enum { destructiveCopy = true };
};
struct DestructiveCopyWrapper
{
template <class T>
struct In
{
typedef DestructiveCopy<T> type;
};
};
////////////////////////////////////////////////////////////////////////////////
// class template NoCopy
// Implementation of the OwnershipPolicy used by SmartPtr
// Implements a policy that doesn't allow copying objects
////////////////////////////////////////////////////////////////////////////////
template <class P>
class NoCopy
{
public:
NoCopy()
{}
template <class P1>
NoCopy(const NoCopy<P1>&)
{}
static P Clone(const P&)
{
STATIC_CHECK(false, This_Policy_Disallows_Value_Copying);
}
static bool Release(const P&)
{ return true; }
static void Swap(NoCopy&)
{}
enum { destructiveCopy = false };
};
struct NoCopyWrapper
{
template <class T>
struct In
{
typedef NoCopy<T> type;
};
};
////////////////////////////////////////////////////////////////////////////////
// class template AllowConversion
// Implementation of the ConversionPolicy used by SmartPtr
// Allows implicit conversion from SmartPtr to the pointee type
////////////////////////////////////////////////////////////////////////////////
struct AllowConversion
{
enum { allow = true };
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&)
{}
};
struct NoCheckWrapper
{
template <class T>
struct In
{
typedef NoCheck<T> type;
};
};
////////////////////////////////////////////////////////////////////////////////
// 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); }
static void Swap(AssertCheck&)
{}
};
struct AssertCheckWrapper
{
template <class T>
struct In {typedef AssertCheck<T> type;};
};
////////////////////////////////////////////////////////////////////////////////
// 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&)
{}
};
struct AssertCheckStrictWrapper
{
template <class T>
struct In
{
typedef AssertCheckStrict<T> type;
};
};
////////////////////////////////////////////////////////////////////////////////
// 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&)
{
CompileTimeError<false>
ERROR_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&)
{}
};
struct RejectNullStaticWrapper
{
template <class T>
struct In
{
typedef RejectNullStatic<T> type;
};
};
////////////////////////////////////////////////////////////////////////////////
// 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&)
{}
};
struct RejectNullWrapper
{
template <class T>
struct In
{
typedef RejectNull<T> type;
};
};
////////////////////////////////////////////////////////////////////////////////
// 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&)
{}
};
struct RejectNullStrictWrapper
{
template <class T>
struct In
{
typedef RejectNullStrict<T> type;
};
};
////////////////////////////////////////////////////////////////////////////////
// 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:
T& value_;
};
////////////////////////////////////////////////////////////////////////////////
// class template SmartPtr (declaration)
// The reason for all the fuss above
////////////////////////////////////////////////////////////////////////////////
template
<
typename T,
class OwnershipPolicy = RefCountedWrapper,
class ConversionPolicy = DisallowConversion,
class CheckingPolicy = AssertCheckWrapper,
class StoragePolicy = DefaultSPStorageWrapper
>
class SmartPtr;
////////////////////////////////////////////////////////////////////////////////
// class template SmartPtr (definition)
////////////////////////////////////////////////////////////////////////////////
namespace Private
{
template <class T, class Ow, class Con, class Check, class Stor>
struct SmartPtrImpl
{
struct Dummy{};
typedef typename ApplyInnerType<Stor, T>::type TempType;
typedef VC_Base_Workaround<TempType, Dummy> sttype;
// VC 6.0 will emit an "Error C2516. : is not a legal base class"
// if one tries to use TempType as base class for SmartPtr.
// Don't know why the compiler is happy with this workaround
typedef sttype::LeftBase Storage;
typedef Storage::PointerType PointerType;
typedef Storage::StoredType StoredType;
typedef Storage::ReferenceType ReferenceType;
typedef typename ApplyInnerType<Ow, PointerType>::type Temp2Type;
typedef typename ApplyInnerType<Check, StoredType>::type Temp3Type;
typedef VC_Base_Workaround<Temp2Type, Dummy> owtype;
typedef owtype::LeftBase Owner;
typedef VC_Base_Workaround<Temp3Type, Dummy> chtype;
typedef chtype::LeftBase Checking;
typedef Con Conversion;
};
}
template
<
typename T,
class OwnershipPolicy,
class ConversionPolicy,
class CheckingPolicy,
class StoragePolicy
>
class SmartPtr
: public Private::SmartPtrImpl<T, OwnershipPolicy, ConversionPolicy, CheckingPolicy, StoragePolicy>::Storage
, public Private::SmartPtrImpl<T, OwnershipPolicy, ConversionPolicy,CheckingPolicy, StoragePolicy>::Owner
, public Private::SmartPtrImpl<T, OwnershipPolicy, ConversionPolicy,CheckingPolicy, StoragePolicy>::Checking
, public Private::SmartPtrImpl<T, OwnershipPolicy, ConversionPolicy,CheckingPolicy, StoragePolicy>::Conversion
{
public:
typedef typename Private::SmartPtrImpl
<
T, OwnershipPolicy, ConversionPolicy, CheckingPolicy, StoragePolicy
>::Storage SP;
typedef SP::PointerType PointerType;
typedef SP::StoredType StoredType;
typedef SP::ReferenceType ReferenceType;
typedef typename Private::SmartPtrImpl
<
T, OwnershipPolicy, ConversionPolicy, CheckingPolicy, StoragePolicy
>::Owner OP;
typedef typename Private::SmartPtrImpl
<
T, OwnershipPolicy, ConversionPolicy, CheckingPolicy, StoragePolicy
>::Checking KP;
typedef ConversionPolicy CP;
typedef typename Select
<
OP::destructiveCopy,
SmartPtr, const SmartPtr
>::Result CopyArg;
typedef typename Select
<
OP::destructiveCopy,
NullType, StoredType
>::Result WorkaroundType;
// i think the following two ctors have an exception-safety problem
// in the original version. If KP throws one can't release the resources
// which were possibly allocated by SP and/or OP.
// don't know if my solution works.
SmartPtr()
{
try
{
KP::OnDefault(GetImpl(*this));
}
catch(...)
{
if (OP::Release(GetImpl(*static_cast<SP*>(this))))
{
SP::Destroy();
}
throw;
}
}
SmartPtr(const StoredType& p) : SP(p)
{
try
{
KP::OnInit(GetImpl(*this));
}
catch(...)
{
if (OP::Release(GetImpl(*static_cast<SP*>(this))))
{
SP::Destroy();
}
throw;
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -