diff options
author | Daniel Wilhelm <daniel@wili.li> | 2014-04-18 17:15:16 +0200 |
---|---|---|
committer | Daniel Wilhelm <daniel@wili.li> | 2014-04-18 17:15:16 +0200 |
commit | bd6336c629841c6db3a6ca53a936d629d34db53b (patch) | |
tree | 3721ef997864108df175ce677a8a7d4342a6f1d2 /shared/loki/SmartPtr.h | |
parent | 4.0 (diff) | |
download | FreeFileSync-bd6336c629841c6db3a6ca53a936d629d34db53b.tar.gz FreeFileSync-bd6336c629841c6db3a6ca53a936d629d34db53b.tar.bz2 FreeFileSync-bd6336c629841c6db3a6ca53a936d629d34db53b.zip |
4.1
Diffstat (limited to 'shared/loki/SmartPtr.h')
-rw-r--r-- | shared/loki/SmartPtr.h | 1778 |
1 files changed, 0 insertions, 1778 deletions
diff --git a/shared/loki/SmartPtr.h b/shared/loki/SmartPtr.h deleted file mode 100644 index 6f6f9996..00000000 --- a/shared/loki/SmartPtr.h +++ /dev/null @@ -1,1778 +0,0 @@ -//////////////////////////////////////////////////////////////////////////////// -// The Loki Library -// Copyright (c) 2001 by Andrei Alexandrescu -// This code accompanies the book: -// Alexandrescu, Andrei. "Modern C++ Design: Generic Programming and Design -// Patterns Applied". Copyright (c) 2001. Addison-Wesley. -// Permission to use, copy, modify, distribute and sell this software for any -// purpose is hereby granted without fee, provided that the above copyright -// notice appear in all copies and that both that copyright notice and this -// permission notice appear in supporting documentation. -// The author or Addison-Wesley Longman make no representations about the -// suitability of this software for any purpose. It is provided "as is" -// without express or implied warranty. -//////////////////////////////////////////////////////////////////////////////// -#ifndef LOKI_SMARTPTR_INC_ -#define LOKI_SMARTPTR_INC_ - -// $Id: SmartPtr.h 903 2008-11-10 05:55:12Z rich_sposato $ - - -/// \defgroup SmartPointerGroup Smart pointers -/// Policy based implementation of a smart pointer -/// \defgroup SmartPointerOwnershipGroup Ownership policies -/// \ingroup SmartPointerGroup -/// \defgroup SmartPointerStorageGroup Storage policies -/// \ingroup SmartPointerGroup -/// \defgroup SmartPointerConversionGroup Conversion policies -/// \ingroup SmartPointerGroup -/// \defgroup SmartPointerCheckingGroup Checking policies -/// \ingroup SmartPointerGroup - -#include "LokiExport.h" -#include "SmallObj.h" -#include "TypeManip.h" -#include "static_check.h" -#include "RefToValue.h" -#include "ConstPolicy.h" - -#include <functional> -#include <stdexcept> -#include <cassert> -#include <string> - -#if !defined(_MSC_VER) -# if defined(__sparc__) -# include <inttypes.h> -# else -# include <stdint.h> -# endif -#endif - -#if defined(_MSC_VER) || defined(__GNUC__) -// GCC>=4.1 must use -ffriend-injection due to a bug in GCC -#define LOKI_ENABLE_FRIEND_TEMPLATE_TEMPLATE_PARAMETER_WORKAROUND -#endif - - -namespace Loki -{ - -//////////////////////////////////////////////////////////////////////////////// -/// \class HeapStorage -/// -/// \ingroup SmartPointerStorageGroup -/// Implementation of the StoragePolicy used by SmartPtr. Uses explicit call -/// to T's destructor followed by call to free. -//////////////////////////////////////////////////////////////////////////////// - - -template <class T> -class HeapStorage -{ -public: - typedef T* StoredType; /// the type of the pointee_ object - typedef T* InitPointerType; /// type used to declare OwnershipPolicy type. - typedef T* PointerType; /// type returned by operator-> - typedef T& ReferenceType; /// type returned by operator* - - HeapStorage() : pointee_(Default()) - {} - - // The storage policy doesn't initialize the stored pointer - // which will be initialized by the OwnershipPolicy's Clone fn - HeapStorage(const HeapStorage&) : pointee_(0) - {} - - template <class U> - HeapStorage(const HeapStorage<U>&) : pointee_(0) - {} - - HeapStorage(const StoredType& p) : pointee_(p) {} - - PointerType operator->() const { return pointee_; } - - ReferenceType operator*() const { return *pointee_; } - - void Swap(HeapStorage& rhs) - { std::swap(pointee_, rhs.pointee_); } - - // Accessors - template <class F> - friend typename HeapStorage<F>::PointerType GetImpl(const HeapStorage<F>& sp); - - template <class F> - friend const typename HeapStorage<F>::StoredType& GetImplRef(const HeapStorage<F>& sp); - - template <class F> - friend typename HeapStorage<F>::StoredType& GetImplRef(HeapStorage<F>& sp); - -protected: - // Destroys the data stored - // (Destruction might be taken over by the OwnershipPolicy) - void Destroy() - { - if ( 0 != pointee_ ) - { - pointee_->~T(); - ::free( pointee_ ); - } - } - - // Default value to initialize the pointer - static StoredType Default() - { return 0; } - -private: - // Data - StoredType pointee_; -}; - -template <class T> -inline typename HeapStorage<T>::PointerType GetImpl(const HeapStorage<T>& sp) -{ return sp.pointee_; } - -template <class T> -inline const typename HeapStorage<T>::StoredType& GetImplRef(const HeapStorage<T>& sp) -{ return sp.pointee_; } - -template <class T> -inline typename HeapStorage<T>::StoredType& GetImplRef(HeapStorage<T>& sp) -{ return sp.pointee_; } - - -//////////////////////////////////////////////////////////////////////////////// -/// \class DefaultSPStorage -/// -/// \ingroup SmartPointerStorageGroup -/// Implementation of the StoragePolicy used by SmartPtr -//////////////////////////////////////////////////////////////////////////////// - - -template <class T> -class DefaultSPStorage -{ -public: - typedef T* StoredType; // the type of the pointee_ object - typedef T* InitPointerType; /// type used to declare OwnershipPolicy type. - typedef T* PointerType; // type returned by operator-> - typedef T& ReferenceType; // type returned by operator* - - DefaultSPStorage() : pointee_(Default()) - {} - - // The storage policy doesn't initialize the stored pointer - // which will be initialized by the OwnershipPolicy's Clone fn - DefaultSPStorage(const DefaultSPStorage&) : pointee_(0) - {} - - template <class U> - DefaultSPStorage(const DefaultSPStorage<U>&) : pointee_(0) - {} - - DefaultSPStorage(const StoredType& p) : pointee_(p) {} - - PointerType operator->() const { return pointee_; } - - ReferenceType operator*() const { return *pointee_; } - - void Swap(DefaultSPStorage& rhs) - { std::swap(pointee_, rhs.pointee_); } - - // Accessors - template <class F> - friend typename DefaultSPStorage<F>::PointerType GetImpl(const DefaultSPStorage<F>& sp); - - template <class F> - friend const typename DefaultSPStorage<F>::StoredType& GetImplRef(const DefaultSPStorage<F>& sp); - - template <class F> - friend typename DefaultSPStorage<F>::StoredType& GetImplRef(DefaultSPStorage<F>& sp); - -protected: - // Destroys the data stored - // (Destruction might be taken over by the OwnershipPolicy) - // - // If your compiler gives you a warning in this area while - // compiling the tests, it is on purpose, please ignore it. - void Destroy() - { - delete pointee_; - } - - // Default value to initialize the pointer - static StoredType Default() - { return 0; } - -private: - // Data - StoredType pointee_; -}; - -template <class T> -inline typename DefaultSPStorage<T>::PointerType GetImpl(const DefaultSPStorage<T>& sp) -{ return sp.pointee_; } - -template <class T> -inline const typename DefaultSPStorage<T>::StoredType& GetImplRef(const DefaultSPStorage<T>& sp) -{ return sp.pointee_; } - -template <class T> -inline typename DefaultSPStorage<T>::StoredType& GetImplRef(DefaultSPStorage<T>& sp) -{ return sp.pointee_; } - - -//////////////////////////////////////////////////////////////////////////////// -/// \class LockedStorage -/// -/// \ingroup SmartPointerStorageGroup -/// Implementation of the StoragePolicy used by SmartPtr. -/// -/// Each call to operator-> locks the object for the duration of a call to a -/// member function of T. -/// -/// \par How It Works -/// LockedStorage has a helper class called Locker, which acts as a smart -/// pointer with limited abilities. LockedStorage::operator-> returns an -/// unnamed temporary of type Locker<T> that exists for the duration of the -/// call to a member function of T. The unnamed temporary locks the object -/// when it is constructed by operator-> and unlocks the object when it is -/// destructed. -/// -/// \note This storage policy requires class T to have member functions Lock -/// and Unlock. If your class does not have Lock or Unlock functions, you may -/// either make a child class which does, or make a policy class similar to -/// LockedStorage which calls other functions to lock the object. -//////////////////////////////////////////////////////////////////////////////// - -template <class T> -class Locker -{ -public: - Locker( const T* p ) : pointee_( const_cast< T* >( p ) ) - { - if ( pointee_ != 0 ) - pointee_->Lock(); - } - - ~Locker( void ) - { - if ( pointee_ != 0 ) - pointee_->Unlock(); - } - - operator T* () - { - return pointee_; - } - - T* operator->() - { - return pointee_; - } - -private: - Locker( void ); - Locker& operator = ( const Locker& ); - T* pointee_; -}; - -template <class T> -class LockedStorage -{ -public: - - typedef T* StoredType; /// the type of the pointee_ object - typedef T* InitPointerType; /// type used to declare OwnershipPolicy type. - typedef Locker< T > PointerType; /// type returned by operator-> - typedef T& ReferenceType; /// type returned by operator* - - LockedStorage() : pointee_( Default() ) {} - - ~LockedStorage( void ) {} - - LockedStorage( const LockedStorage&) : pointee_( 0 ) {} - - LockedStorage( const StoredType& p ) : pointee_( p ) {} - - PointerType operator->() - { - return Locker< T >( pointee_ ); - } - - void Swap(LockedStorage& rhs) - { - std::swap( pointee_, rhs.pointee_ ); - } - - // Accessors - template <class F> - friend typename LockedStorage<F>::InitPointerType GetImpl(const LockedStorage<F>& sp); - - template <class F> - friend const typename LockedStorage<F>::StoredType& GetImplRef(const LockedStorage<F>& sp); - - template <class F> - friend typename LockedStorage<F>::StoredType& GetImplRef(LockedStorage<F>& sp); - -protected: - // Destroys the data stored - // (Destruction might be taken over by the OwnershipPolicy) - void Destroy() - { - delete pointee_; - } - - // Default value to initialize the pointer - static StoredType Default() - { return 0; } - -private: - /// Dereference operator is not implemented. - ReferenceType operator*(); - - // Data - StoredType pointee_; -}; - -template <class T> -inline typename LockedStorage<T>::InitPointerType GetImpl(const LockedStorage<T>& sp) -{ return sp.pointee_; } - -template <class T> -inline const typename LockedStorage<T>::StoredType& GetImplRef(const LockedStorage<T>& sp) -{ return sp.pointee_; } - -template <class T> -inline typename LockedStorage<T>::StoredType& GetImplRef(LockedStorage<T>& sp) -{ return sp.pointee_; } - - -//////////////////////////////////////////////////////////////////////////////// -/// \class ArrayStorage -/// -/// \ingroup SmartPointerStorageGroup -/// Implementation of the ArrayStorage used by SmartPtr -//////////////////////////////////////////////////////////////////////////////// - - -template <class T> -class ArrayStorage -{ -public: - typedef T* StoredType; // the type of the pointee_ object - typedef T* InitPointerType; /// type used to declare OwnershipPolicy type. - typedef T* PointerType; // type returned by operator-> - typedef T& ReferenceType; // type returned by operator* - - ArrayStorage() : pointee_(Default()) - {} - - // The storage policy doesn't initialize the stored pointer - // which will be initialized by the OwnershipPolicy's Clone fn - ArrayStorage(const ArrayStorage&) : pointee_(0) - {} - - template <class U> - ArrayStorage(const ArrayStorage<U>&) : pointee_(0) - {} - - ArrayStorage(const StoredType& p) : pointee_(p) {} - - PointerType operator->() const { return pointee_; } - - ReferenceType operator*() const { return *pointee_; } - - void Swap(ArrayStorage& rhs) - { std::swap(pointee_, rhs.pointee_); } - - // Accessors - template <class F> - friend typename ArrayStorage<F>::PointerType GetImpl(const ArrayStorage<F>& sp); - - template <class F> - friend const typename ArrayStorage<F>::StoredType& GetImplRef(const ArrayStorage<F>& sp); - - template <class F> - friend typename ArrayStorage<F>::StoredType& GetImplRef(ArrayStorage<F>& sp); - -protected: - // Destroys the data stored - // (Destruction might be taken over by the OwnershipPolicy) - void Destroy() - { delete [] pointee_; } - - // Default value to initialize the pointer - static StoredType Default() - { return 0; } - -private: - // Data - StoredType pointee_; -}; - -template <class T> -inline typename ArrayStorage<T>::PointerType GetImpl(const ArrayStorage<T>& sp) -{ return sp.pointee_; } - -template <class T> -inline const typename ArrayStorage<T>::StoredType& GetImplRef(const ArrayStorage<T>& sp) -{ return sp.pointee_; } - -template <class T> -inline typename ArrayStorage<T>::StoredType& GetImplRef(ArrayStorage<T>& sp) -{ return sp.pointee_; } - - -//////////////////////////////////////////////////////////////////////////////// -/// \class RefCounted -/// -/// \ingroup SmartPointerOwnershipGroup -/// Implementation of the OwnershipPolicy used by SmartPtr -/// Provides a classic external reference counting implementation -//////////////////////////////////////////////////////////////////////////////// - -template <class P> -class RefCounted -{ -public: - RefCounted() - : pCount_(static_cast<uintptr_t*>( - SmallObject<>::operator new(sizeof(uintptr_t)))) - { - assert(pCount_ != 0); - *pCount_ = 1; - } - - RefCounted(const RefCounted& rhs) - : pCount_(rhs.pCount_) - {} - - // MWCW lacks template friends, hence the following kludge - template <typename P1> - RefCounted(const RefCounted<P1>& rhs) - : pCount_(reinterpret_cast<const RefCounted&>(rhs).pCount_) - {} - - P Clone(const P& val) - { - ++*pCount_; - return val; - } - - bool Release(const P&) - { - if (!--*pCount_) - { - SmallObject<>::operator delete(pCount_, sizeof(uintptr_t)); - pCount_ = NULL; - return true; - } - return false; - } - - void Swap(RefCounted& rhs) - { std::swap(pCount_, rhs.pCount_); } - - enum { destructiveCopy = false }; - -private: - // Data - uintptr_t* pCount_; -}; - -//////////////////////////////////////////////////////////////////////////////// -/// \struct RefCountedMT -/// -/// \ingroup SmartPointerOwnershipGroup -/// Implementation of the OwnershipPolicy used by SmartPtr -/// Implements external reference counting for multithreaded programs -/// Policy Usage: RefCountedMTAdj<ThreadingModel>::RefCountedMT -/// -/// \par Warning -/// There could be a race condition, see bug "Race condition in RefCountedMTAdj::Release" -/// http://sourceforge.net/tracker/index.php?func=detail&aid=1408845&group_id=29557&atid=396644 -/// As stated in bug 1408845, the Release function is not thread safe if a -/// SmartPtr copy-constructor tries to copy the last pointer to an object in -/// one thread, while the destructor is acting on the last pointer in another -/// thread. The existence of a race between a copy-constructor and destructor -/// implies a design flaw at a higher level. That race condition must be -/// fixed at a higher design level, and no change to this class could fix it. -//////////////////////////////////////////////////////////////////////////////// - -template < template <class, class> class ThreadingModel, - class MX = LOKI_DEFAULT_MUTEX > -struct RefCountedMTAdj -{ - template <class P> - class RefCountedMT : public ThreadingModel< RefCountedMT<P>, MX > - { - typedef ThreadingModel< RefCountedMT<P>, MX > base_type; - typedef typename base_type::IntType CountType; - typedef volatile CountType* CountPtrType; - - public: - RefCountedMT() - { - pCount_ = static_cast<CountPtrType>( - SmallObject<LOKI_DEFAULT_THREADING_NO_OBJ_LEVEL>::operator new( - sizeof(*pCount_))); - assert(pCount_); - //*pCount_ = 1; - ThreadingModel<RefCountedMT, MX>::AtomicAssign(*pCount_, 1); - } - - RefCountedMT(const RefCountedMT& rhs) - : pCount_(rhs.pCount_) - {} - - //MWCW lacks template friends, hence the following kludge - template <typename P1> - RefCountedMT(const RefCountedMT<P1>& rhs) - : pCount_(reinterpret_cast<const RefCountedMT<P>&>(rhs).pCount_) - {} - - P Clone(const P& val) - { - ThreadingModel<RefCountedMT, MX>::AtomicIncrement(*pCount_); - return val; - } - - bool Release(const P&) - { - bool isZero = false; - ThreadingModel< RefCountedMT, MX >::AtomicDecrement( *pCount_, 0, isZero ); - if ( isZero ) - { - SmallObject<LOKI_DEFAULT_THREADING_NO_OBJ_LEVEL>::operator delete( - const_cast<CountType*>(pCount_), - sizeof(*pCount_)); - return true; - } - return false; - } - - void Swap(RefCountedMT& rhs) - { std::swap(pCount_, rhs.pCount_); } - - enum { destructiveCopy = false }; - - private: - // Data - CountPtrType pCount_; - }; -}; - -//////////////////////////////////////////////////////////////////////////////// -/// \class COMRefCounted -/// -/// \ingroup SmartPointerOwnershipGroup -/// Implementation of the OwnershipPolicy used by SmartPtr -/// Adapts COM intrusive reference counting to OwnershipPolicy-specific syntax -//////////////////////////////////////////////////////////////////////////////// - -template <class P> -class COMRefCounted -{ -public: - COMRefCounted() - {} - - template <class U> - COMRefCounted(const COMRefCounted<U>&) - {} - - static P Clone(const P& val) - { - if (val != 0) - val->AddRef(); - return val; - } - - static bool Release(const P& val) - { - if (val != 0) - val->Release(); - return false; - } - - enum { destructiveCopy = false }; - - static void Swap(COMRefCounted&) - {} -}; - -//////////////////////////////////////////////////////////////////////////////// -/// \struct DeepCopy -/// -/// \ingroup SmartPointerOwnershipGroup -/// Implementation of the OwnershipPolicy used by SmartPtr -/// Implements deep copy semantics, assumes existence of a Clone() member -/// function of the pointee type -//////////////////////////////////////////////////////////////////////////////// - -template <class P> -struct DeepCopy -{ - DeepCopy() - {} - - template <class P1> - DeepCopy(const DeepCopy<P1>&) - {} - - static P Clone(const P& val) - { return val->Clone(); } - - static bool Release(const P&) - { return true; } - - static void Swap(DeepCopy&) - {} - - enum { destructiveCopy = false }; -}; - -//////////////////////////////////////////////////////////////////////////////// -/// \class RefLinked -/// -/// \ingroup SmartPointerOwnershipGroup -/// Implementation of the OwnershipPolicy used by SmartPtr -/// Implements reference linking -//////////////////////////////////////////////////////////////////////////////// - -namespace Private -{ -class LOKI_EXPORT RefLinkedBase -{ -public: - RefLinkedBase() - { prev_ = next_ = this; } - - RefLinkedBase(const RefLinkedBase& rhs); - - bool Release(); - - void Swap(RefLinkedBase& rhs); - - bool Merge( RefLinkedBase& rhs ); - - enum { destructiveCopy = false }; - -private: - static unsigned int CountPrevCycle( const RefLinkedBase* pThis ); - static unsigned int CountNextCycle( const RefLinkedBase* pThis ); - bool HasPrevNode( const RefLinkedBase* p ) const; - bool HasNextNode( const RefLinkedBase* p ) const; - - mutable const RefLinkedBase* prev_; - mutable const RefLinkedBase* next_; -}; -} - -template <class P> -class RefLinked : public Private::RefLinkedBase -{ -public: - RefLinked() - {} - - template <class P1> - RefLinked(const RefLinked<P1>& rhs) - : Private::RefLinkedBase(rhs) - {} - - static P Clone(const P& val) - { return val; } - - bool Release(const P&) - { return Private::RefLinkedBase::Release(); } - - template < class P1 > - bool Merge( RefLinked< P1 > & rhs ) - { - return Private::RefLinkedBase::Merge( rhs ); - } -}; - -//////////////////////////////////////////////////////////////////////////////// -/// \class DestructiveCopy -/// -/// \ingroup SmartPointerOwnershipGroup -/// Implementation of the OwnershipPolicy used by SmartPtr -/// Implements destructive copy semantics (a la std::auto_ptr) -//////////////////////////////////////////////////////////////////////////////// - -template <class P> -class DestructiveCopy -{ -public: - DestructiveCopy() - {} - - template <class P1> - DestructiveCopy(const DestructiveCopy<P1>&) - {} - - template <class P1> - static P Clone(P1& val) - { - P result(val); - val = P1(); - return result; - } - - static bool Release(const P&) - { return true; } - - static void Swap(DestructiveCopy&) - {} - - enum { destructiveCopy = true }; -}; - -//////////////////////////////////////////////////////////////////////////////// -/// \class NoCopy -/// -/// \ingroup SmartPointerOwnershipGroup -/// 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&) - { - // Make it depended on template parameter - static const bool DependedFalse = sizeof(P*) == 0; - - LOKI_STATIC_CHECK(DependedFalse, This_Policy_Disallows_Value_Copying); - } - - static bool Release(const P&) - { return true; } - - static void Swap(NoCopy&) - {} - - enum { destructiveCopy = false }; -}; - -//////////////////////////////////////////////////////////////////////////////// -/// \struct AllowConversion -/// -/// \ingroup SmartPointerConversionGroup -/// Implementation of the ConversionPolicy used by SmartPtr -/// Allows implicit conversion from SmartPtr to the pointee type -//////////////////////////////////////////////////////////////////////////////// - -struct AllowConversion -{ - enum { allow = true }; - - void Swap(AllowConversion&) - {} -}; - -//////////////////////////////////////////////////////////////////////////////// -/// \struct DisallowConversion -/// -/// \ingroup SmartPointerConversionGroup -/// 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&) - {} -}; - -//////////////////////////////////////////////////////////////////////////////// -/// \struct NoCheck -/// -/// \ingroup SmartPointerCheckingGroup -/// 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 AssertCheck -/// -/// \ingroup SmartPointerCheckingGroup -/// 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&) - {} -}; - -//////////////////////////////////////////////////////////////////////////////// -/// \struct AssertCheckStrict -/// -/// \ingroup SmartPointerCheckingGroup -/// 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 NullPointerException -/// -/// \ingroup SmartPointerGroup -/// Used by some implementations of the CheckingPolicy used by SmartPtr -//////////////////////////////////////////////////////////////////////////////// - -struct NullPointerException : public std::runtime_error -{ - NullPointerException() : std::runtime_error(std::string("")) - { } - const char* what() const throw() - { return "Null Pointer Exception"; } -}; - -//////////////////////////////////////////////////////////////////////////////// -/// \struct RejectNullStatic -/// -/// \ingroup SmartPointerCheckingGroup -/// 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&) - { - // Make it depended on template parameter - static const bool DependedFalse = sizeof(P*) == 0; - - LOKI_STATIC_CHECK(DependedFalse, 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 RejectNull -/// -/// \ingroup SmartPointerCheckingGroup -/// 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) - {} - - static void OnDefault(P) - {} - - void OnDereference(P val) - { if (!val) throw NullPointerException(); } - - void OnDereference(P val) const - { if (!val) throw NullPointerException(); } - - void Swap(RejectNull&) - {} -}; - -//////////////////////////////////////////////////////////////////////////////// -/// \struct RejectNullStrict -/// -/// \ingroup SmartPointerCheckingGroup -/// 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 OnDereference(P val) const - { OnInit(val); } - - void Swap(RejectNullStrict&) - {} -}; - - -//////////////////////////////////////////////////////////////////////////////// -// class template SmartPtr (declaration) -// The reason for all the fuss above -//////////////////////////////////////////////////////////////////////////////// - -template -< -typename T, - template <class> class OwnershipPolicy = RefCounted, - class ConversionPolicy = DisallowConversion, - template <class> class CheckingPolicy = AssertCheck, - template <class> class StoragePolicy = DefaultSPStorage, - template<class> class ConstnessPolicy = LOKI_DEFAULT_CONSTNESS - > -class SmartPtr; - -//////////////////////////////////////////////////////////////////////////////// -// class template SmartPtrDef (definition) -// this class added to unify the usage of SmartPtr -// 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, - template<class> class ConstnessPolicy = LOKI_DEFAULT_CONSTNESS - > -struct SmartPtrDef -{ - typedef SmartPtr - < - T, - OwnershipPolicy, - ConversionPolicy, - CheckingPolicy, - StoragePolicy, - ConstnessPolicy - > - type; -}; - -//////////////////////////////////////////////////////////////////////////////// -/// \class SmartPtr -/// -/// \ingroup SmartPointerGroup -/// -/// \param OwnershipPolicy default = RefCounted, -/// \param ConversionPolicy default = DisallowConversion, -/// \param CheckingPolicy default = AssertCheck, -/// \param StoragePolicy default = DefaultSPStorage -/// \param ConstnessPolicy default = LOKI_DEFAULT_CONSTNESS -/// -/// \par IMPORTANT NOTE -/// Due to threading issues, the OwnershipPolicy has been changed as follows: -/// -/// - Release() returns a boolean saying if that was the last release -/// so the pointer can be deleted by the StoragePolicy -/// - IsUnique() was removed -//////////////////////////////////////////////////////////////////////////////// - -template -< -typename T, - template <class> class OwnershipPolicy, - class ConversionPolicy, - template <class> class CheckingPolicy, - template <class> class StoragePolicy, - template <class> class ConstnessPolicy - > -class SmartPtr - : public StoragePolicy<T> - , public OwnershipPolicy<typename StoragePolicy<T>::InitPointerType> - , public CheckingPolicy<typename StoragePolicy<T>::StoredType> - , public ConversionPolicy -{ - typedef StoragePolicy<T> SP; - typedef OwnershipPolicy<typename StoragePolicy<T>::InitPointerType> OP; - typedef CheckingPolicy<typename StoragePolicy<T>::StoredType> KP; - typedef ConversionPolicy CP; - -public: - typedef typename ConstnessPolicy<T>::Type* ConstPointerType; - typedef typename ConstnessPolicy<T>::Type& ConstReferenceType; - - 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: - struct NeverMatched {}; - -#ifdef LOKI_SMARTPTR_CONVERSION_CONSTRUCTOR_POLICY - typedef typename Select< CP::allow, const StoredType&, NeverMatched>::Result ImplicitArg; - typedef typename Select < !CP::allow, const StoredType&, NeverMatched >::Result ExplicitArg; -#else - typedef const StoredType& ImplicitArg; - typedef typename Select<false, const StoredType&, NeverMatched>::Result ExplicitArg; -#endif - -public: - - SmartPtr() - { - KP::OnDefault(GetImpl(*this)); - } - - explicit - SmartPtr(ExplicitArg p) : SP(p) - { - KP::OnInit(GetImpl(*this)); - } - - SmartPtr(ImplicitArg p) : SP(p) - { - KP::OnInit(GetImpl(*this)); - } - - SmartPtr(CopyArg& rhs) : SP(rhs), OP(rhs), KP(rhs), CP(rhs) - { - GetImplRef(*this) = OP::Clone(GetImplRef(rhs)); - } - - template - < - typename T1, - template <class> class OP1, - class CP1, - template <class> class KP1, - template <class> class SP1, - template <class> class CNP1 - > - SmartPtr(const SmartPtr<T1, OP1, CP1, KP1, SP1, CNP1 >& rhs) - : SP(rhs), OP(rhs), KP(rhs), CP(rhs) - { GetImplRef(*this) = OP::Clone(GetImplRef(rhs)); } - - template - < - typename T1, - template <class> class OP1, - class CP1, - template <class> class KP1, - template <class> class SP1, - template <class> class CNP1 - > - SmartPtr(SmartPtr<T1, OP1, CP1, KP1, SP1, CNP1 >& rhs) - : SP(rhs), OP(rhs), KP(rhs), CP(rhs) - { - GetImplRef(*this) = OP::Clone(GetImplRef(rhs)); - } - - SmartPtr(RefToValue<SmartPtr> rhs) - : SP(rhs), OP(rhs), KP(rhs), CP(rhs) - {} - - operator RefToValue<SmartPtr>() - { return RefToValue<SmartPtr>(*this); } - - SmartPtr& operator=(CopyArg& rhs) - { - SmartPtr temp(rhs); - temp.Swap(*this); - return *this; - } - - template - < - typename T1, - template <class> class OP1, - class CP1, - template <class> class KP1, - template <class> class SP1, - template <class> class CNP1 - > - SmartPtr& operator=(const SmartPtr<T1, OP1, CP1, KP1, SP1, CNP1 >& rhs) - { - SmartPtr temp(rhs); - temp.Swap(*this); - return *this; - } - - template - < - typename T1, - template <class> class OP1, - class CP1, - template <class> class KP1, - template <class> class SP1, - template <class> class CNP1 - > - SmartPtr& operator=(SmartPtr<T1, OP1, CP1, KP1, SP1, CNP1 >& rhs) - { - SmartPtr temp(rhs); - temp.Swap(*this); - return *this; - } - - void Swap(SmartPtr& rhs) - { - OP::Swap(rhs); - CP::Swap(rhs); - KP::Swap(rhs); - SP::Swap(rhs); - } - - ~SmartPtr() - { - if (OP::Release(GetImpl(*static_cast<SP*>(this)))) - { - SP::Destroy(); - } - } - -#ifdef LOKI_ENABLE_FRIEND_TEMPLATE_TEMPLATE_PARAMETER_WORKAROUND - - // old non standard in class definition of friends - friend inline void Release(SmartPtr& sp, typename SP::StoredType& p) - { - p = GetImplRef(sp); - GetImplRef(sp) = SP::Default(); - } - - friend inline void Reset(SmartPtr& sp, typename SP::StoredType p) - { SmartPtr(p).Swap(sp); } - -#else - - template - < - typename T1, - template <class> class OP1, - class CP1, - template <class> class KP1, - template <class> class SP1, - template <class> class CNP1 - > - friend void Release(SmartPtr<T1, OP1, CP1, KP1, SP1, CNP1>& sp, - typename SP1<T1>::StoredType& p); - - template - < - typename T1, - template <class> class OP1, - class CP1, - template <class> class KP1, - template <class> class SP1, - template <class> class CNP1 - > - friend void Reset(SmartPtr<T1, OP1, CP1, KP1, SP1, CNP1>& sp, - typename SP1<T1>::StoredType p); -#endif - - - template - < - typename T1, - template <class> class OP1, - class CP1, - template <class> class KP1, - template <class> class SP1, - template <class> class CNP1 - > - bool Merge( SmartPtr< T1, OP1, CP1, KP1, SP1, CNP1 > & rhs ) - { - if ( GetImpl( *this ) != GetImpl( rhs ) ) - { - return false; - } - return OP::template Merge( rhs ); - } - - PointerType operator->() - { - KP::OnDereference(GetImplRef(*this)); - return SP::operator->(); - } - - ConstPointerType operator->() const - { - KP::OnDereference(GetImplRef(*this)); - return SP::operator->(); - } - - ReferenceType operator*() - { - KP::OnDereference(GetImplRef(*this)); - return SP::operator*(); - } - - ConstReferenceType operator*() const - { - KP::OnDereference(GetImplRef(*this)); - return SP::operator*(); - } - - bool operator!() const // Enables "if (!sp) ..." - { return GetImpl(*this) == 0; } - - static inline T* GetPointer( const SmartPtr& sp ) - { return GetImpl( sp ); } - - // Ambiguity buster - template - < - typename T1, - template <class> class OP1, - class CP1, - template <class> class KP1, - template <class> class SP1, - template <class> class CNP1 - > - bool operator==(const SmartPtr<T1, OP1, CP1, KP1, SP1, CNP1 >& rhs) const - { return GetImpl(*this) == GetImpl(rhs); } - - // Ambiguity buster - template - < - typename T1, - template <class> class OP1, - class CP1, - template <class> class KP1, - template <class> class SP1, - template <class> class CNP1 - > - bool operator!=(const SmartPtr<T1, OP1, CP1, KP1, SP1, CNP1 >& rhs) const - { return !(*this == rhs); } - - // Ambiguity buster - template - < - typename T1, - template <class> class OP1, - class CP1, - template <class> class KP1, - template <class> class SP1, - template <class> class CNP1 - > - bool operator<(const SmartPtr<T1, OP1, CP1, KP1, SP1, CNP1 >& rhs) const - { return GetImpl(*this) < GetImpl(rhs); } - - // Ambiguity buster - template - < - typename T1, - template <class> class OP1, - class CP1, - template <class> class KP1, - template <class> class SP1, - template <class> class CNP1 - > - inline bool operator > ( const SmartPtr< T1, OP1, CP1, KP1, SP1, CNP1 > & rhs ) - { - return ( GetImpl( rhs ) < GetImpl( *this ) ); - } - - // Ambiguity buster - template - < - typename T1, - template <class> class OP1, - class CP1, - template <class> class KP1, - template <class> class SP1, - template <class> class CNP1 - > - inline bool operator <= ( const SmartPtr< T1, OP1, CP1, KP1, SP1, CNP1 > & rhs ) - { - return !( GetImpl( rhs ) < GetImpl( *this ) ); - } - - // Ambiguity buster - template - < - typename T1, - template <class> class OP1, - class CP1, - template <class> class KP1, - template <class> class SP1, - template <class> class CNP1 - > - inline bool operator >= ( const SmartPtr< T1, OP1, CP1, KP1, SP1, CNP1 > & rhs ) - { - return !( GetImpl( *this ) < GetImpl( rhs ) ); - } - -private: - // Helper for enabling 'if (sp)' - struct Tester - { - Tester(int) {} - void dummy() {} - }; - - typedef void (Tester::*unspecified_boolean_type_)(); - - typedef typename Select<CP::allow, Tester, unspecified_boolean_type_>::Result - unspecified_boolean_type; - -public: - // enable 'if (sp)' - operator unspecified_boolean_type() const - { - return !*this ? 0 : &Tester::dummy; - } - -private: - // Helper for disallowing automatic conversion - struct Insipid - { - Insipid(PointerType) {} - }; - - typedef typename Select<CP::allow, PointerType, Insipid>::Result - AutomaticConversionResult; - -public: - operator AutomaticConversionResult() const - { return GetImpl(*this); } -}; - - -//////////////////////////////////////////////////////////////////////////////// -// friends -//////////////////////////////////////////////////////////////////////////////// - -#ifndef LOKI_ENABLE_FRIEND_TEMPLATE_TEMPLATE_PARAMETER_WORKAROUND - -template -< -typename T, - template <class> class OP, - class CP, - template <class> class KP, - template <class> class SP, - template <class> class CNP - > -inline void Release(SmartPtr<T, OP, CP, KP, SP, CNP>& sp, - typename SP<T>::StoredType& p) -{ - p = GetImplRef(sp); - GetImplRef(sp) = SP<T>::Default(); -} - -template -< -typename T, - template <class> class OP, - class CP, - template <class> class KP, - template <class> class SP, - template <class> class CNP - > -inline void Reset(SmartPtr<T, OP, CP, KP, SP, CNP>& sp, - typename SP<T>::StoredType p) -{ SmartPtr<T, OP, CP, KP, SP, CNP>(p).Swap(sp); } - -#endif - -//////////////////////////////////////////////////////////////////////////////// -// free comparison operators for class template SmartPtr -//////////////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////////////// -/// operator== for lhs = SmartPtr, rhs = raw pointer -/// \ingroup SmartPointerGroup -//////////////////////////////////////////////////////////////////////////////// - -template -< -typename T, - template <class> class OP, - class CP, - template <class> class KP, - template <class> class SP, - template <class> class CNP1, - typename U - > -inline bool operator==(const SmartPtr<T, OP, CP, KP, SP, CNP1 >& lhs, - U* rhs) -{ return GetImpl(lhs) == rhs; } - -//////////////////////////////////////////////////////////////////////////////// -/// operator== for lhs = raw pointer, rhs = SmartPtr -/// \ingroup SmartPointerGroup -//////////////////////////////////////////////////////////////////////////////// - -template -< -typename T, - template <class> class OP, - class CP, - template <class> class KP, - template <class> class SP, - template <class> class CNP1, - typename U - > -inline bool operator==(U* lhs, - const SmartPtr<T, OP, CP, KP, SP, CNP1 >& rhs) -{ return rhs == lhs; } - -//////////////////////////////////////////////////////////////////////////////// -/// operator!= for lhs = SmartPtr, rhs = raw pointer -/// \ingroup SmartPointerGroup -//////////////////////////////////////////////////////////////////////////////// - -template -< -typename T, - template <class> class OP, - class CP, - template <class> class KP, - template <class> class SP, - template <class> class CNP, - typename U - > -inline bool operator!=(const SmartPtr<T, OP, CP, KP, SP, CNP >& lhs, - U* rhs) -{ return !(lhs == rhs); } - -//////////////////////////////////////////////////////////////////////////////// -/// operator!= for lhs = raw pointer, rhs = SmartPtr -/// \ingroup SmartPointerGroup -//////////////////////////////////////////////////////////////////////////////// - -template -< -typename T, - template <class> class OP, - class CP, - template <class> class KP, - template <class> class SP, - template <class> class CNP, - typename U - > -inline bool operator!=(U* lhs, - const SmartPtr<T, OP, CP, KP, SP, CNP >& rhs) -{ return rhs != lhs; } - -//////////////////////////////////////////////////////////////////////////////// -/// operator< for lhs = SmartPtr, rhs = raw pointer -/// \ingroup SmartPointerGroup -//////////////////////////////////////////////////////////////////////////////// - -template -< -typename T, - template <class> class OP, - class CP, - template <class> class KP, - template <class> class SP, - template <class> class CNP, - typename U - > -inline bool operator<(const SmartPtr<T, OP, CP, KP, SP, CNP >& lhs, - U* rhs) -{ - return ( GetImpl( lhs ) < rhs ); -} - -//////////////////////////////////////////////////////////////////////////////// -/// operator< for lhs = raw pointer, rhs = SmartPtr -/// \ingroup SmartPointerGroup -//////////////////////////////////////////////////////////////////////////////// - -template -< -typename T, - template <class> class OP, - class CP, - template <class> class KP, - template <class> class SP, - template <class> class CNP, - typename U - > -inline bool operator<(U* lhs, - const SmartPtr<T, OP, CP, KP, SP, CNP >& rhs) -{ - return ( GetImpl( rhs ) < lhs ); -} - -//////////////////////////////////////////////////////////////////////////////// -// operator> for lhs = SmartPtr, rhs = raw pointer -/// \ingroup SmartPointerGroup -//////////////////////////////////////////////////////////////////////////////// - -template -< -typename T, - template <class> class OP, - class CP, - template <class> class KP, - template <class> class SP, - template <class> class CNP, - typename U - > -inline bool operator>(const SmartPtr<T, OP, CP, KP, SP, CNP >& lhs, - U* rhs) -{ return rhs < lhs; } - -//////////////////////////////////////////////////////////////////////////////// -/// operator> for lhs = raw pointer, rhs = SmartPtr -/// \ingroup SmartPointerGroup -//////////////////////////////////////////////////////////////////////////////// - -template -< -typename T, - template <class> class OP, - class CP, - template <class> class KP, - template <class> class SP, - template <class> class CNP, - typename U - > -inline bool operator>(U* lhs, - const SmartPtr<T, OP, CP, KP, SP, CNP >& rhs) -{ return rhs < lhs; } - -//////////////////////////////////////////////////////////////////////////////// -/// operator<= for lhs = SmartPtr, rhs = raw pointer -/// \ingroup SmartPointerGroup -//////////////////////////////////////////////////////////////////////////////// - -template -< -typename T, - template <class> class OP, - class CP, - template <class> class KP, - template <class> class SP, - template <class> class CNP, - typename U - > -inline bool operator<=(const SmartPtr<T, OP, CP, KP, SP, CNP >& lhs, - U* rhs) -{ return !(rhs < lhs); } - -//////////////////////////////////////////////////////////////////////////////// -/// operator<= for lhs = raw pointer, rhs = SmartPtr -/// \ingroup SmartPointerGroup -//////////////////////////////////////////////////////////////////////////////// - -template -< -typename T, - template <class> class OP, - class CP, - template <class> class KP, - template <class> class SP, - template <class> class CNP, - typename U - > -inline bool operator<=(U* lhs, - const SmartPtr<T, OP, CP, KP, SP, CNP >& rhs) -{ return !(rhs < lhs); } - -//////////////////////////////////////////////////////////////////////////////// -/// operator>= for lhs = SmartPtr, rhs = raw pointer -/// \ingroup SmartPointerGroup -//////////////////////////////////////////////////////////////////////////////// - -template -< -typename T, - template <class> class OP, - class CP, - template <class> class KP, - template <class> class SP, - template <class> class CNP, - typename U - > -inline bool operator>=(const SmartPtr<T, OP, CP, KP, SP, CNP >& lhs, - U* rhs) -{ return !(lhs < rhs); } - -//////////////////////////////////////////////////////////////////////////////// -/// operator>= for lhs = raw pointer, rhs = SmartPtr -/// \ingroup SmartPointerGroup -//////////////////////////////////////////////////////////////////////////////// - -template -< -typename T, - template <class> class OP, - class CP, - template <class> class KP, - template <class> class SP, - template <class> class CNP, - typename U - > -inline bool operator>=(U* lhs, - const SmartPtr<T, OP, CP, KP, SP, CNP >& rhs) -{ return !(lhs < rhs); } - -} // namespace Loki - -//////////////////////////////////////////////////////////////////////////////// -/// specialization of std::less for SmartPtr -/// \ingroup SmartPointerGroup -//////////////////////////////////////////////////////////////////////////////// - -namespace std -{ -template -< -typename T, - template <class> class OP, - class CP, - template <class> class KP, - template <class> class SP, - template <class> class CNP - > -struct less< Loki::SmartPtr<T, OP, CP, KP, SP, CNP > > - : public binary_function < Loki::SmartPtr<T, OP, CP, KP, SP, CNP >, - Loki::SmartPtr<T, OP, CP, KP, SP, CNP >, bool > -{ - bool operator()(const Loki::SmartPtr<T, OP, CP, KP, SP, CNP >& lhs, - const Loki::SmartPtr<T, OP, CP, KP, SP, CNP >& rhs) const - { return less<T*>()(GetImpl(lhs), GetImpl(rhs)); } -}; -} - -#endif // end file guardian - |