1 ////////////////////////////////////////////////////////////////////////////////
3 // Copyright (c) 2001 by Andrei Alexandrescu
4 // This code accompanies the book:
5 // Alexandrescu, Andrei. "Modern C++ Design: Generic Programming and Design
6 // Patterns Applied". Copyright (c) 2001. Addison-Wesley.
7 // Permission to use, copy, modify, distribute and sell this software for any
8 // purpose is hereby granted without fee, provided that the above copyright
9 // notice appear in all copies and that both that copyright notice and this
10 // permission notice appear in supporting documentation.
11 // The author or Addison-Wesley Longman make no representations about the
12 // suitability of this software for any purpose. It is provided "as is"
13 // without express or implied warranty.
14 ////////////////////////////////////////////////////////////////////////////////
15 #ifndef LOKI_SMARTPTR_INC_
16 #define LOKI_SMARTPTR_INC_
18 // $Id: SmartPtr.h 903 2008-11-10 05:55:12Z rich_sposato $
21 /// \defgroup SmartPointerGroup Smart pointers
22 /// Policy based implementation of a smart pointer
23 /// \defgroup SmartPointerOwnershipGroup Ownership policies
24 /// \ingroup SmartPointerGroup
25 /// \defgroup SmartPointerStorageGroup Storage policies
26 /// \ingroup SmartPointerGroup
27 /// \defgroup SmartPointerConversionGroup Conversion policies
28 /// \ingroup SmartPointerGroup
29 /// \defgroup SmartPointerCheckingGroup Checking policies
30 /// \ingroup SmartPointerGroup
32 #include "LokiExport.h"
34 #include "TypeManip.h"
35 #include "static_check.h"
36 #include "RefToValue.h"
37 #include "ConstPolicy.h"
44 #if !defined(_MSC_VER)
45 # if defined(__sparc__)
46 # include <inttypes.h>
52 #if defined(_MSC_VER) || defined(__GNUC__)
53 // GCC>=4.1 must use -ffriend-injection due to a bug in GCC
54 #define LOKI_ENABLE_FRIEND_TEMPLATE_TEMPLATE_PARAMETER_WORKAROUND
61 ////////////////////////////////////////////////////////////////////////////////
62 /// \class HeapStorage
64 /// \ingroup SmartPointerStorageGroup
65 /// Implementation of the StoragePolicy used by SmartPtr. Uses explicit call
66 /// to T's destructor followed by call to free.
67 ////////////////////////////////////////////////////////////////////////////////
74 typedef T *StoredType; /// the type of the pointee_ object
75 typedef T *InitPointerType; /// type used to declare OwnershipPolicy type.
76 typedef T *PointerType; /// type returned by operator->
77 typedef T &ReferenceType; /// type returned by operator*
79 HeapStorage() : pointee_(Default())
82 // The storage policy doesn't initialize the stored pointer
83 // which will be initialized by the OwnershipPolicy's Clone fn
84 HeapStorage(const HeapStorage &) : pointee_(0)
88 HeapStorage(const HeapStorage<U>&) : pointee_(0)
91 HeapStorage(const StoredType &p) : pointee_(p) {}
93 PointerType operator->() const
98 ReferenceType operator*() const
103 void Swap(HeapStorage &rhs)
105 std::swap(pointee_, rhs.pointee_);
110 friend typename HeapStorage<F>::PointerType GetImpl(const HeapStorage<F>& sp);
113 friend const typename HeapStorage<F>::StoredType &GetImplRef(const HeapStorage<F>& sp);
116 friend typename HeapStorage<F>::StoredType &GetImplRef(HeapStorage<F>& sp);
119 // Destroys the data stored
120 // (Destruction might be taken over by the OwnershipPolicy)
130 // Default value to initialize the pointer
131 static StoredType Default()
142 inline typename HeapStorage<T>::PointerType GetImpl(const HeapStorage<T>& sp)
148 inline const typename HeapStorage<T>::StoredType &GetImplRef(const HeapStorage<T>& sp)
154 inline typename HeapStorage<T>::StoredType &GetImplRef(HeapStorage<T>& sp)
160 ////////////////////////////////////////////////////////////////////////////////
161 /// \class DefaultSPStorage
163 /// \ingroup SmartPointerStorageGroup
164 /// Implementation of the StoragePolicy used by SmartPtr
165 ////////////////////////////////////////////////////////////////////////////////
169 class DefaultSPStorage
172 typedef T *StoredType; // the type of the pointee_ object
173 typedef T *InitPointerType; /// type used to declare OwnershipPolicy type.
174 typedef T *PointerType; // type returned by operator->
175 typedef T &ReferenceType; // type returned by operator*
177 DefaultSPStorage() : pointee_(Default())
180 // The storage policy doesn't initialize the stored pointer
181 // which will be initialized by the OwnershipPolicy's Clone fn
182 DefaultSPStorage(const DefaultSPStorage &) : pointee_(0)
186 DefaultSPStorage(const DefaultSPStorage<U>&) : pointee_(0)
189 DefaultSPStorage(const StoredType &p) : pointee_(p) {}
191 PointerType operator->() const
196 ReferenceType operator*() const
201 void Swap(DefaultSPStorage &rhs)
203 std::swap(pointee_, rhs.pointee_);
208 friend typename DefaultSPStorage<F>::PointerType GetImpl(const DefaultSPStorage<F>& sp);
211 friend const typename DefaultSPStorage<F>::StoredType &GetImplRef(const DefaultSPStorage<F>& sp);
214 friend typename DefaultSPStorage<F>::StoredType &GetImplRef(DefaultSPStorage<F>& sp);
217 // Destroys the data stored
218 // (Destruction might be taken over by the OwnershipPolicy)
220 // If your compiler gives you a warning in this area while
221 // compiling the tests, it is on purpose, please ignore it.
227 // Default value to initialize the pointer
228 static StoredType Default()
239 inline typename DefaultSPStorage<T>::PointerType GetImpl(const DefaultSPStorage<T>& sp)
245 inline const typename DefaultSPStorage<T>::StoredType &GetImplRef(const DefaultSPStorage<T>& sp)
251 inline typename DefaultSPStorage<T>::StoredType &GetImplRef(DefaultSPStorage<T>& sp)
257 ////////////////////////////////////////////////////////////////////////////////
258 /// \class LockedStorage
260 /// \ingroup SmartPointerStorageGroup
261 /// Implementation of the StoragePolicy used by SmartPtr.
263 /// Each call to operator-> locks the object for the duration of a call to a
264 /// member function of T.
266 /// \par How It Works
267 /// LockedStorage has a helper class called Locker, which acts as a smart
268 /// pointer with limited abilities. LockedStorage::operator-> returns an
269 /// unnamed temporary of type Locker<T> that exists for the duration of the
270 /// call to a member function of T. The unnamed temporary locks the object
271 /// when it is constructed by operator-> and unlocks the object when it is
274 /// \note This storage policy requires class T to have member functions Lock
275 /// and Unlock. If your class does not have Lock or Unlock functions, you may
276 /// either make a child class which does, or make a policy class similar to
277 /// LockedStorage which calls other functions to lock the object.
278 ////////////////////////////////////////////////////////////////////////////////
284 Locker( const T *p ) : pointee_( const_cast< T * >( p ) )
308 Locker &operator = ( const Locker & );
317 typedef T *StoredType; /// the type of the pointee_ object
318 typedef T *InitPointerType; /// type used to declare OwnershipPolicy type.
319 typedef Locker< T > PointerType; /// type returned by operator->
320 typedef T &ReferenceType; /// type returned by operator*
322 LockedStorage() : pointee_( Default() ) {}
324 ~LockedStorage( void ) {}
326 LockedStorage( const LockedStorage &) : pointee_( 0 ) {}
328 LockedStorage( const StoredType &p ) : pointee_( p ) {}
330 PointerType operator->()
332 return Locker< T >( pointee_ );
335 void Swap(LockedStorage &rhs)
337 std::swap( pointee_, rhs.pointee_ );
342 friend typename LockedStorage<F>::InitPointerType GetImpl(const LockedStorage<F>& sp);
345 friend const typename LockedStorage<F>::StoredType &GetImplRef(const LockedStorage<F>& sp);
348 friend typename LockedStorage<F>::StoredType &GetImplRef(LockedStorage<F>& sp);
351 // Destroys the data stored
352 // (Destruction might be taken over by the OwnershipPolicy)
358 // Default value to initialize the pointer
359 static StoredType Default()
365 /// Dereference operator is not implemented.
366 ReferenceType operator*();
373 inline typename LockedStorage<T>::InitPointerType GetImpl(const LockedStorage<T>& sp)
379 inline const typename LockedStorage<T>::StoredType &GetImplRef(const LockedStorage<T>& sp)
385 inline typename LockedStorage<T>::StoredType &GetImplRef(LockedStorage<T>& sp)
391 ////////////////////////////////////////////////////////////////////////////////
392 /// \class ArrayStorage
394 /// \ingroup SmartPointerStorageGroup
395 /// Implementation of the ArrayStorage used by SmartPtr
396 ////////////////////////////////////////////////////////////////////////////////
403 typedef T *StoredType; // the type of the pointee_ object
404 typedef T *InitPointerType; /// type used to declare OwnershipPolicy type.
405 typedef T *PointerType; // type returned by operator->
406 typedef T &ReferenceType; // type returned by operator*
408 ArrayStorage() : pointee_(Default())
411 // The storage policy doesn't initialize the stored pointer
412 // which will be initialized by the OwnershipPolicy's Clone fn
413 ArrayStorage(const ArrayStorage &) : pointee_(0)
417 ArrayStorage(const ArrayStorage<U>&) : pointee_(0)
420 ArrayStorage(const StoredType &p) : pointee_(p) {}
422 PointerType operator->() const
427 ReferenceType operator*() const
432 void Swap(ArrayStorage &rhs)
434 std::swap(pointee_, rhs.pointee_);
439 friend typename ArrayStorage<F>::PointerType GetImpl(const ArrayStorage<F>& sp);
442 friend const typename ArrayStorage<F>::StoredType &GetImplRef(const ArrayStorage<F>& sp);
445 friend typename ArrayStorage<F>::StoredType &GetImplRef(ArrayStorage<F>& sp);
448 // Destroys the data stored
449 // (Destruction might be taken over by the OwnershipPolicy)
455 // Default value to initialize the pointer
456 static StoredType Default()
467 inline typename ArrayStorage<T>::PointerType GetImpl(const ArrayStorage<T>& sp)
473 inline const typename ArrayStorage<T>::StoredType &GetImplRef(const ArrayStorage<T>& sp)
479 inline typename ArrayStorage<T>::StoredType &GetImplRef(ArrayStorage<T>& sp)
485 ////////////////////////////////////////////////////////////////////////////////
486 /// \class RefCounted
488 /// \ingroup SmartPointerOwnershipGroup
489 /// Implementation of the OwnershipPolicy used by SmartPtr
490 /// Provides a classic external reference counting implementation
491 ////////////////////////////////////////////////////////////////////////////////
498 : pCount_(static_cast<uintptr_t *>(
499 SmallObject<>::operator new(sizeof(uintptr_t))))
505 RefCounted(const RefCounted &rhs)
506 : pCount_(rhs.pCount_)
509 // MWCW lacks template friends, hence the following kludge
510 template <typename P1>
511 RefCounted(const RefCounted<P1>& rhs)
512 : pCount_(reinterpret_cast<const RefCounted &>(rhs).pCount_)
515 P Clone(const P &val)
521 bool Release(const P &)
525 SmallObject<>::operator delete(pCount_, sizeof(uintptr_t));
532 void Swap(RefCounted &rhs)
534 std::swap(pCount_, rhs.pCount_);
537 enum { destructiveCopy = false };
544 ////////////////////////////////////////////////////////////////////////////////
545 /// \struct RefCountedMT
547 /// \ingroup SmartPointerOwnershipGroup
548 /// Implementation of the OwnershipPolicy used by SmartPtr
549 /// Implements external reference counting for multithreaded programs
550 /// Policy Usage: RefCountedMTAdj<ThreadingModel>::RefCountedMT
553 /// There could be a race condition, see bug "Race condition in RefCountedMTAdj::Release"
554 /// http://sourceforge.net/tracker/index.php?func=detail&aid=1408845&group_id=29557&atid=396644
555 /// As stated in bug 1408845, the Release function is not thread safe if a
556 /// SmartPtr copy-constructor tries to copy the last pointer to an object in
557 /// one thread, while the destructor is acting on the last pointer in another
558 /// thread. The existence of a race between a copy-constructor and destructor
559 /// implies a design flaw at a higher level. That race condition must be
560 /// fixed at a higher design level, and no change to this class could fix it.
561 ////////////////////////////////////////////////////////////////////////////////
563 template <template <class, class> class ThreadingModel,
564 class MX = LOKI_DEFAULT_MUTEX >
565 struct RefCountedMTAdj
568 class RefCountedMT : public ThreadingModel< RefCountedMT<P>, MX >
570 typedef ThreadingModel< RefCountedMT<P>, MX > base_type;
571 typedef typename base_type::IntType CountType;
572 typedef volatile CountType *CountPtrType;
577 pCount_ = static_cast<CountPtrType>(
578 SmallObject<LOKI_DEFAULT_THREADING_NO_OBJ_LEVEL>::operator new(
582 ThreadingModel<RefCountedMT, MX>::AtomicAssign(*pCount_, 1);
585 RefCountedMT(const RefCountedMT &rhs)
586 : pCount_(rhs.pCount_)
589 //MWCW lacks template friends, hence the following kludge
590 template <typename P1>
591 RefCountedMT(const RefCountedMT<P1>& rhs)
592 : pCount_(reinterpret_cast<const RefCountedMT<P>&>(rhs).pCount_)
595 P Clone(const P &val)
597 ThreadingModel<RefCountedMT, MX>::AtomicIncrement(*pCount_);
601 bool Release(const P &)
604 ThreadingModel< RefCountedMT, MX >::AtomicDecrement( *pCount_, 0, isZero );
607 SmallObject<LOKI_DEFAULT_THREADING_NO_OBJ_LEVEL>::operator delete(
608 const_cast<CountType *>(pCount_),
615 void Swap(RefCountedMT &rhs)
617 std::swap(pCount_, rhs.pCount_);
620 enum { destructiveCopy = false };
624 CountPtrType pCount_;
628 ////////////////////////////////////////////////////////////////////////////////
629 /// \class COMRefCounted
631 /// \ingroup SmartPointerOwnershipGroup
632 /// Implementation of the OwnershipPolicy used by SmartPtr
633 /// Adapts COM intrusive reference counting to OwnershipPolicy-specific syntax
634 ////////////////////////////////////////////////////////////////////////////////
644 COMRefCounted(const COMRefCounted<U>&)
647 static P Clone(const P &val)
654 static bool Release(const P &val)
661 enum { destructiveCopy = false };
663 static void Swap(COMRefCounted &)
667 ////////////////////////////////////////////////////////////////////////////////
670 /// \ingroup SmartPointerOwnershipGroup
671 /// Implementation of the OwnershipPolicy used by SmartPtr
672 /// Implements deep copy semantics, assumes existence of a Clone() member
673 /// function of the pointee type
674 ////////////////////////////////////////////////////////////////////////////////
683 DeepCopy(const DeepCopy<P1>&)
686 static P Clone(const P &val)
691 static bool Release(const P &)
696 static void Swap(DeepCopy &)
699 enum { destructiveCopy = false };
702 ////////////////////////////////////////////////////////////////////////////////
705 /// \ingroup SmartPointerOwnershipGroup
706 /// Implementation of the OwnershipPolicy used by SmartPtr
707 /// Implements reference linking
708 ////////////////////////////////////////////////////////////////////////////////
712 class LOKI_EXPORT RefLinkedBase
717 prev_ = next_ = this;
720 RefLinkedBase(const RefLinkedBase &rhs);
724 void Swap(RefLinkedBase &rhs);
726 bool Merge( RefLinkedBase &rhs );
728 enum { destructiveCopy = false };
731 static unsigned int CountPrevCycle( const RefLinkedBase *pThis );
732 static unsigned int CountNextCycle( const RefLinkedBase *pThis );
733 bool HasPrevNode( const RefLinkedBase *p ) const;
734 bool HasNextNode( const RefLinkedBase *p ) const;
736 mutable const RefLinkedBase *prev_;
737 mutable const RefLinkedBase *next_;
742 class RefLinked : public Private::RefLinkedBase
749 RefLinked(const RefLinked<P1>& rhs)
750 : Private::RefLinkedBase(rhs)
753 static P Clone(const P &val)
758 bool Release(const P &)
760 return Private::RefLinkedBase::Release();
763 template < class P1 >
764 bool Merge( RefLinked< P1 > & rhs )
766 return Private::RefLinkedBase::Merge( rhs );
770 ////////////////////////////////////////////////////////////////////////////////
771 /// \class DestructiveCopy
773 /// \ingroup SmartPointerOwnershipGroup
774 /// Implementation of the OwnershipPolicy used by SmartPtr
775 /// Implements destructive copy semantics (a la std::auto_ptr)
776 ////////////////////////////////////////////////////////////////////////////////
779 class DestructiveCopy
786 DestructiveCopy(const DestructiveCopy<P1>&)
790 static P Clone(P1 &val)
797 static bool Release(const P &)
802 static void Swap(DestructiveCopy &)
805 enum { destructiveCopy = true };
808 ////////////////////////////////////////////////////////////////////////////////
811 /// \ingroup SmartPointerOwnershipGroup
812 /// Implementation of the OwnershipPolicy used by SmartPtr
813 /// Implements a policy that doesn't allow copying objects
814 ////////////////////////////////////////////////////////////////////////////////
824 NoCopy(const NoCopy<P1>&)
827 static P Clone(const P &)
829 // Make it depended on template parameter
830 static const bool DependedFalse = sizeof(P *) == 0;
832 LOKI_STATIC_CHECK(DependedFalse, This_Policy_Disallows_Value_Copying);
835 static bool Release(const P &)
840 static void Swap(NoCopy &)
843 enum { destructiveCopy = false };
846 ////////////////////////////////////////////////////////////////////////////////
847 /// \struct AllowConversion
849 /// \ingroup SmartPointerConversionGroup
850 /// Implementation of the ConversionPolicy used by SmartPtr
851 /// Allows implicit conversion from SmartPtr to the pointee type
852 ////////////////////////////////////////////////////////////////////////////////
854 struct AllowConversion
856 enum { allow = true };
858 void Swap(AllowConversion &)
862 ////////////////////////////////////////////////////////////////////////////////
863 /// \struct DisallowConversion
865 /// \ingroup SmartPointerConversionGroup
866 /// Implementation of the ConversionPolicy used by SmartPtr
867 /// Does not allow implicit conversion from SmartPtr to the pointee type
868 /// You can initialize a DisallowConversion with an AllowConversion
869 ////////////////////////////////////////////////////////////////////////////////
871 struct DisallowConversion
876 DisallowConversion(const AllowConversion &)
879 enum { allow = false };
881 void Swap(DisallowConversion &)
885 ////////////////////////////////////////////////////////////////////////////////
888 /// \ingroup SmartPointerCheckingGroup
889 /// Implementation of the CheckingPolicy used by SmartPtr
890 /// Well, it's clear what it does :o)
891 ////////////////////////////////////////////////////////////////////////////////
900 NoCheck(const NoCheck<P1>&)
903 static void OnDefault(const P &)
906 static void OnInit(const P &)
909 static void OnDereference(const P &)
912 static void Swap(NoCheck &)
917 ////////////////////////////////////////////////////////////////////////////////
918 /// \struct AssertCheck
920 /// \ingroup SmartPointerCheckingGroup
921 /// Implementation of the CheckingPolicy used by SmartPtr
922 /// Checks the pointer before dereference
923 ////////////////////////////////////////////////////////////////////////////////
932 AssertCheck(const AssertCheck<P1>&)
936 AssertCheck(const NoCheck<P1>&)
939 static void OnDefault(const P &)
942 static void OnInit(const P &)
945 static void OnDereference(P val)
951 static void Swap(AssertCheck &)
955 ////////////////////////////////////////////////////////////////////////////////
956 /// \struct AssertCheckStrict
958 /// \ingroup SmartPointerCheckingGroup
959 /// Implementation of the CheckingPolicy used by SmartPtr
960 /// Checks the pointer against zero upon initialization and before dereference
961 /// You can initialize an AssertCheckStrict with an AssertCheck
962 ////////////////////////////////////////////////////////////////////////////////
965 struct AssertCheckStrict
971 AssertCheckStrict(const AssertCheckStrict<U>&)
975 AssertCheckStrict(const AssertCheck<U>&)
979 AssertCheckStrict(const NoCheck<P1>&)
982 static void OnDefault(P val)
987 static void OnInit(P val)
992 static void OnDereference(P val)
997 static void Swap(AssertCheckStrict &)
1001 ////////////////////////////////////////////////////////////////////////////////
1002 /// \struct NullPointerException
1004 /// \ingroup SmartPointerGroup
1005 /// Used by some implementations of the CheckingPolicy used by SmartPtr
1006 ////////////////////////////////////////////////////////////////////////////////
1008 struct NullPointerException : public std::runtime_error
1010 NullPointerException() : std::runtime_error(std::string(""))
1012 const char *what() const throw()
1014 return "Null Pointer Exception";
1018 ////////////////////////////////////////////////////////////////////////////////
1019 /// \struct RejectNullStatic
1021 /// \ingroup SmartPointerCheckingGroup
1022 /// Implementation of the CheckingPolicy used by SmartPtr
1023 /// Checks the pointer upon initialization and before dereference
1024 ////////////////////////////////////////////////////////////////////////////////
1027 struct RejectNullStatic
1033 RejectNullStatic(const RejectNullStatic<P1>&)
1037 RejectNullStatic(const NoCheck<P1>&)
1041 RejectNullStatic(const AssertCheck<P1>&)
1045 RejectNullStatic(const AssertCheckStrict<P1>&)
1048 static void OnDefault(const P &)
1050 // Make it depended on template parameter
1051 static const bool DependedFalse = sizeof(P *) == 0;
1053 LOKI_STATIC_CHECK(DependedFalse, ERROR_This_Policy_Does_Not_Allow_Default_Initialization);
1056 static void OnInit(const P &val)
1058 if (!val) throw NullPointerException();
1061 static void OnDereference(const P &val)
1063 if (!val) throw NullPointerException();
1066 static void Swap(RejectNullStatic &)
1070 ////////////////////////////////////////////////////////////////////////////////
1071 /// \struct RejectNull
1073 /// \ingroup SmartPointerCheckingGroup
1074 /// Implementation of the CheckingPolicy used by SmartPtr
1075 /// Checks the pointer before dereference
1076 ////////////////////////////////////////////////////////////////////////////////
1085 RejectNull(const RejectNull<P1>&)
1088 static void OnInit(P)
1091 static void OnDefault(P)
1094 void OnDereference(P val)
1096 if (!val) throw NullPointerException();
1099 void OnDereference(P val) const
1101 if (!val) throw NullPointerException();
1104 void Swap(RejectNull &)
1108 ////////////////////////////////////////////////////////////////////////////////
1109 /// \struct RejectNullStrict
1111 /// \ingroup SmartPointerCheckingGroup
1112 /// Implementation of the CheckingPolicy used by SmartPtr
1113 /// Checks the pointer upon initialization and before dereference
1114 ////////////////////////////////////////////////////////////////////////////////
1117 struct RejectNullStrict
1123 RejectNullStrict(const RejectNullStrict<P1>&)
1127 RejectNullStrict(const RejectNull<P1>&)
1130 static void OnInit(P val)
1132 if (!val) throw NullPointerException();
1135 void OnDereference(P val)
1140 void OnDereference(P val) const
1145 void Swap(RejectNullStrict &)
1150 ////////////////////////////////////////////////////////////////////////////////
1151 // class template SmartPtr (declaration)
1152 // The reason for all the fuss above
1153 ////////////////////////////////////////////////////////////////////////////////
1158 template <class> class OwnershipPolicy = RefCounted,
1159 class ConversionPolicy = DisallowConversion,
1160 template <class> class CheckingPolicy = AssertCheck,
1161 template <class> class StoragePolicy = DefaultSPStorage,
1162 template<class> class ConstnessPolicy = LOKI_DEFAULT_CONSTNESS
1166 ////////////////////////////////////////////////////////////////////////////////
1167 // class template SmartPtrDef (definition)
1168 // this class added to unify the usage of SmartPtr
1169 // instead of writing SmartPtr<T,OP,CP,KP,SP> write SmartPtrDef<T,OP,CP,KP,SP>::type
1170 ////////////////////////////////////////////////////////////////////////////////
1175 template <class> class OwnershipPolicy = RefCounted,
1176 class ConversionPolicy = DisallowConversion,
1177 template <class> class CheckingPolicy = AssertCheck,
1178 template <class> class StoragePolicy = DefaultSPStorage,
1179 template<class> class ConstnessPolicy = LOKI_DEFAULT_CONSTNESS
1195 ////////////////////////////////////////////////////////////////////////////////
1198 /// \ingroup SmartPointerGroup
1200 /// \param OwnershipPolicy default = RefCounted,
1201 /// \param ConversionPolicy default = DisallowConversion,
1202 /// \param CheckingPolicy default = AssertCheck,
1203 /// \param StoragePolicy default = DefaultSPStorage
1204 /// \param ConstnessPolicy default = LOKI_DEFAULT_CONSTNESS
1206 /// \par IMPORTANT NOTE
1207 /// Due to threading issues, the OwnershipPolicy has been changed as follows:
1209 /// - Release() returns a boolean saying if that was the last release
1210 /// so the pointer can be deleted by the StoragePolicy
1211 /// - IsUnique() was removed
1212 ////////////////////////////////////////////////////////////////////////////////
1217 template <class> class OwnershipPolicy,
1218 class ConversionPolicy,
1219 template <class> class CheckingPolicy,
1220 template <class> class StoragePolicy,
1221 template <class> class ConstnessPolicy
1224 : public StoragePolicy<T>
1225 , public OwnershipPolicy<typename StoragePolicy<T>::InitPointerType>
1226 , public CheckingPolicy<typename StoragePolicy<T>::StoredType>
1227 , public ConversionPolicy
1229 typedef StoragePolicy<T> SP;
1230 typedef OwnershipPolicy<typename StoragePolicy<T>::InitPointerType> OP;
1231 typedef CheckingPolicy<typename StoragePolicy<T>::StoredType> KP;
1232 typedef ConversionPolicy CP;
1235 typedef typename ConstnessPolicy<T>::Type *ConstPointerType;
1236 typedef typename ConstnessPolicy<T>::Type &ConstReferenceType;
1238 typedef typename SP::PointerType PointerType;
1239 typedef typename SP::StoredType StoredType;
1240 typedef typename SP::ReferenceType ReferenceType;
1242 typedef typename Select<OP::destructiveCopy,SmartPtr, const SmartPtr>::Result
1246 struct NeverMatched {};
1248 #ifdef LOKI_SMARTPTR_CONVERSION_CONSTRUCTOR_POLICY
1249 typedef typename Select< CP::allow, const StoredType &, NeverMatched>::Result ImplicitArg;
1250 typedef typename Select<!CP::allow, const StoredType &, NeverMatched>::Result ExplicitArg;
1252 typedef const StoredType &ImplicitArg;
1253 typedef typename Select<false, const StoredType &, NeverMatched>::Result ExplicitArg;
1260 KP::OnDefault(GetImpl(*this));
1264 SmartPtr(ExplicitArg p) : SP(p)
1266 KP::OnInit(GetImpl(*this));
1269 SmartPtr(ImplicitArg p) : SP(p)
1271 KP::OnInit(GetImpl(*this));
1274 SmartPtr(CopyArg &rhs) : SP(rhs), OP(rhs), KP(rhs), CP(rhs)
1276 GetImplRef(*this) = OP::Clone(GetImplRef(rhs));
1282 template <class> class OP1,
1284 template <class> class KP1,
1285 template <class> class SP1,
1286 template <class> class CNP1
1288 SmartPtr(const SmartPtr<T1, OP1, CP1, KP1, SP1, CNP1 >& rhs)
1289 : SP(rhs), OP(rhs), KP(rhs), CP(rhs)
1291 GetImplRef(*this) = OP::Clone(GetImplRef(rhs));
1297 template <class> class OP1,
1299 template <class> class KP1,
1300 template <class> class SP1,
1301 template <class> class CNP1
1303 SmartPtr(SmartPtr<T1, OP1, CP1, KP1, SP1, CNP1 >& rhs)
1304 : SP(rhs), OP(rhs), KP(rhs), CP(rhs)
1306 GetImplRef(*this) = OP::Clone(GetImplRef(rhs));
1309 SmartPtr(RefToValue<SmartPtr> rhs)
1310 : SP(rhs), OP(rhs), KP(rhs), CP(rhs)
1313 operator RefToValue<SmartPtr>()
1315 return RefToValue<SmartPtr>(*this);
1318 SmartPtr &operator=(CopyArg &rhs)
1328 template <class> class OP1,
1330 template <class> class KP1,
1331 template <class> class SP1,
1332 template <class> class CNP1
1334 SmartPtr &operator=(const SmartPtr<T1, OP1, CP1, KP1, SP1, CNP1 >& rhs)
1344 template <class> class OP1,
1346 template <class> class KP1,
1347 template <class> class SP1,
1348 template <class> class CNP1
1350 SmartPtr &operator=(SmartPtr<T1, OP1, CP1, KP1, SP1, CNP1 >& rhs)
1357 void Swap(SmartPtr &rhs)
1367 if (OP::Release(GetImpl(*static_cast<SP *>(this))))
1373 #ifdef LOKI_ENABLE_FRIEND_TEMPLATE_TEMPLATE_PARAMETER_WORKAROUND
1375 // old non standard in class definition of friends
1376 friend inline void Release(SmartPtr &sp, typename SP::StoredType &p)
1379 GetImplRef(sp) = SP::Default();
1382 friend inline void Reset(SmartPtr &sp, typename SP::StoredType p)
1384 SmartPtr(p).Swap(sp);
1392 template <class> class OP1,
1394 template <class> class KP1,
1395 template <class> class SP1,
1396 template <class> class CNP1
1398 friend void Release(SmartPtr<T1, OP1, CP1, KP1, SP1, CNP1>& sp,
1399 typename SP1<T1>::StoredType &p);
1404 template <class> class OP1,
1406 template <class> class KP1,
1407 template <class> class SP1,
1408 template <class> class CNP1
1410 friend void Reset(SmartPtr<T1, OP1, CP1, KP1, SP1, CNP1>& sp,
1411 typename SP1<T1>::StoredType p);
1418 template <class> class OP1,
1420 template <class> class KP1,
1421 template <class> class SP1,
1422 template <class> class CNP1
1424 bool Merge( SmartPtr< T1, OP1, CP1, KP1, SP1, CNP1 > & rhs )
1426 if ( GetImpl( *this ) != GetImpl( rhs ) )
1430 return OP::template Merge( rhs );
1433 PointerType operator->()
1435 KP::OnDereference(GetImplRef(*this));
1436 return SP::operator->();
1439 ConstPointerType operator->() const
1441 KP::OnDereference(GetImplRef(*this));
1442 return SP::operator->();
1445 ReferenceType operator*()
1447 KP::OnDereference(GetImplRef(*this));
1448 return SP::operator*();
1451 ConstReferenceType operator*() const
1453 KP::OnDereference(GetImplRef(*this));
1454 return SP::operator*();
1457 bool operator!() const // Enables "if (!sp) ..."
1459 return GetImpl(*this) == 0;
1462 static inline T *GetPointer( const SmartPtr &sp )
1464 return GetImpl( sp );
1471 template <class> class OP1,
1473 template <class> class KP1,
1474 template <class> class SP1,
1475 template <class> class CNP1
1477 bool operator==(const SmartPtr<T1, OP1, CP1, KP1, SP1, CNP1 >& rhs) const
1479 return GetImpl(*this) == GetImpl(rhs);
1486 template <class> class OP1,
1488 template <class> class KP1,
1489 template <class> class SP1,
1490 template <class> class CNP1
1492 bool operator!=(const SmartPtr<T1, OP1, CP1, KP1, SP1, CNP1 >& rhs) const
1494 return !(*this == rhs);
1501 template <class> class OP1,
1503 template <class> class KP1,
1504 template <class> class SP1,
1505 template <class> class CNP1
1507 bool operator<(const SmartPtr<T1, OP1, CP1, KP1, SP1, CNP1 >& rhs) const
1509 return GetImpl(*this) < GetImpl(rhs);
1516 template <class> class OP1,
1518 template <class> class KP1,
1519 template <class> class SP1,
1520 template <class> class CNP1
1522 inline bool operator > ( const SmartPtr< T1, OP1, CP1, KP1, SP1, CNP1 > & rhs )
1524 return ( GetImpl( rhs ) < GetImpl( *this ) );
1531 template <class> class OP1,
1533 template <class> class KP1,
1534 template <class> class SP1,
1535 template <class> class CNP1
1537 inline bool operator <= ( const SmartPtr< T1, OP1, CP1, KP1, SP1, CNP1 > & rhs )
1539 return !( GetImpl( rhs ) < GetImpl( *this ) );
1546 template <class> class OP1,
1548 template <class> class KP1,
1549 template <class> class SP1,
1550 template <class> class CNP1
1552 inline bool operator >= ( const SmartPtr< T1, OP1, CP1, KP1, SP1, CNP1 > & rhs )
1554 return !( GetImpl( *this ) < GetImpl( rhs ) );
1558 // Helper for enabling 'if (sp)'
1565 typedef void (Tester::*unspecified_boolean_type_)();
1567 typedef typename Select<CP::allow, Tester, unspecified_boolean_type_>::Result
1568 unspecified_boolean_type;
1572 operator unspecified_boolean_type() const
1574 return !*this ? 0 : &Tester::dummy;
1578 // Helper for disallowing automatic conversion
1581 Insipid(PointerType) {}
1584 typedef typename Select<CP::allow, PointerType, Insipid>::Result
1585 AutomaticConversionResult;
1588 operator AutomaticConversionResult() const
1590 return GetImpl(*this);
1595 ////////////////////////////////////////////////////////////////////////////////
1597 ////////////////////////////////////////////////////////////////////////////////
1599 #ifndef LOKI_ENABLE_FRIEND_TEMPLATE_TEMPLATE_PARAMETER_WORKAROUND
1604 template <class> class OP,
1606 template <class> class KP,
1607 template <class> class SP,
1608 template <class> class CNP
1610 inline void Release(SmartPtr<T, OP, CP, KP, SP, CNP>& sp,
1611 typename SP<T>::StoredType &p)
1614 GetImplRef(sp) = SP<T>::Default();
1620 template <class> class OP,
1622 template <class> class KP,
1623 template <class> class SP,
1624 template <class> class CNP
1626 inline void Reset(SmartPtr<T, OP, CP, KP, SP, CNP>& sp,
1627 typename SP<T>::StoredType p)
1629 SmartPtr<T, OP, CP, KP, SP, CNP>(p).Swap(sp);
1634 ////////////////////////////////////////////////////////////////////////////////
1635 // free comparison operators for class template SmartPtr
1636 ////////////////////////////////////////////////////////////////////////////////
1638 ////////////////////////////////////////////////////////////////////////////////
1639 /// operator== for lhs = SmartPtr, rhs = raw pointer
1640 /// \ingroup SmartPointerGroup
1641 ////////////////////////////////////////////////////////////////////////////////
1646 template <class> class OP,
1648 template <class> class KP,
1649 template <class> class SP,
1650 template <class> class CNP1,
1653 inline bool operator==(const SmartPtr<T, OP, CP, KP, SP, CNP1 >& lhs,
1656 return GetImpl(lhs) == rhs;
1659 ////////////////////////////////////////////////////////////////////////////////
1660 /// operator== for lhs = raw pointer, rhs = SmartPtr
1661 /// \ingroup SmartPointerGroup
1662 ////////////////////////////////////////////////////////////////////////////////
1667 template <class> class OP,
1669 template <class> class KP,
1670 template <class> class SP,
1671 template <class> class CNP1,
1674 inline bool operator==(U *lhs,
1675 const SmartPtr<T, OP, CP, KP, SP, CNP1 >& rhs)
1680 ////////////////////////////////////////////////////////////////////////////////
1681 /// operator!= for lhs = SmartPtr, rhs = raw pointer
1682 /// \ingroup SmartPointerGroup
1683 ////////////////////////////////////////////////////////////////////////////////
1688 template <class> class OP,
1690 template <class> class KP,
1691 template <class> class SP,
1692 template <class> class CNP,
1695 inline bool operator!=(const SmartPtr<T, OP, CP, KP, SP, CNP >& lhs,
1698 return !(lhs == rhs);
1701 ////////////////////////////////////////////////////////////////////////////////
1702 /// operator!= for lhs = raw pointer, rhs = SmartPtr
1703 /// \ingroup SmartPointerGroup
1704 ////////////////////////////////////////////////////////////////////////////////
1709 template <class> class OP,
1711 template <class> class KP,
1712 template <class> class SP,
1713 template <class> class CNP,
1716 inline bool operator!=(U *lhs,
1717 const SmartPtr<T, OP, CP, KP, SP, CNP >& rhs)
1722 ////////////////////////////////////////////////////////////////////////////////
1723 /// operator< for lhs = SmartPtr, rhs = raw pointer
1724 /// \ingroup SmartPointerGroup
1725 ////////////////////////////////////////////////////////////////////////////////
1730 template <class> class OP,
1732 template <class> class KP,
1733 template <class> class SP,
1734 template <class> class CNP,
1737 inline bool operator<(const SmartPtr<T, OP, CP, KP, SP, CNP >& lhs,
1740 return ( GetImpl( lhs ) < rhs );
1743 ////////////////////////////////////////////////////////////////////////////////
1744 /// operator< for lhs = raw pointer, rhs = SmartPtr
1745 /// \ingroup SmartPointerGroup
1746 ////////////////////////////////////////////////////////////////////////////////
1751 template <class> class OP,
1753 template <class> class KP,
1754 template <class> class SP,
1755 template <class> class CNP,
1758 inline bool operator<(U *lhs,
1759 const SmartPtr<T, OP, CP, KP, SP, CNP >& rhs)
1761 return ( GetImpl( rhs ) < lhs );
1764 ////////////////////////////////////////////////////////////////////////////////
1765 // operator> for lhs = SmartPtr, rhs = raw pointer
1766 /// \ingroup SmartPointerGroup
1767 ////////////////////////////////////////////////////////////////////////////////
1772 template <class> class OP,
1774 template <class> class KP,
1775 template <class> class SP,
1776 template <class> class CNP,
1779 inline bool operator>(const SmartPtr<T, OP, CP, KP, SP, CNP >& lhs,
1785 ////////////////////////////////////////////////////////////////////////////////
1786 /// operator> for lhs = raw pointer, rhs = SmartPtr
1787 /// \ingroup SmartPointerGroup
1788 ////////////////////////////////////////////////////////////////////////////////
1793 template <class> class OP,
1795 template <class> class KP,
1796 template <class> class SP,
1797 template <class> class CNP,
1800 inline bool operator>(U *lhs,
1801 const SmartPtr<T, OP, CP, KP, SP, CNP >& rhs)
1806 ////////////////////////////////////////////////////////////////////////////////
1807 /// operator<= for lhs = SmartPtr, rhs = raw pointer
1808 /// \ingroup SmartPointerGroup
1809 ////////////////////////////////////////////////////////////////////////////////
1814 template <class> class OP,
1816 template <class> class KP,
1817 template <class> class SP,
1818 template <class> class CNP,
1821 inline bool operator<=(const SmartPtr<T, OP, CP, KP, SP, CNP >& lhs,
1824 return !(rhs < lhs);
1827 ////////////////////////////////////////////////////////////////////////////////
1828 /// operator<= for lhs = raw pointer, rhs = SmartPtr
1829 /// \ingroup SmartPointerGroup
1830 ////////////////////////////////////////////////////////////////////////////////
1835 template <class> class OP,
1837 template <class> class KP,
1838 template <class> class SP,
1839 template <class> class CNP,
1842 inline bool operator<=(U *lhs,
1843 const SmartPtr<T, OP, CP, KP, SP, CNP >& rhs)
1845 return !(rhs < lhs);
1848 ////////////////////////////////////////////////////////////////////////////////
1849 /// operator>= for lhs = SmartPtr, rhs = raw pointer
1850 /// \ingroup SmartPointerGroup
1851 ////////////////////////////////////////////////////////////////////////////////
1856 template <class> class OP,
1858 template <class> class KP,
1859 template <class> class SP,
1860 template <class> class CNP,
1863 inline bool operator>=(const SmartPtr<T, OP, CP, KP, SP, CNP >& lhs,
1866 return !(lhs < rhs);
1869 ////////////////////////////////////////////////////////////////////////////////
1870 /// operator>= for lhs = raw pointer, rhs = SmartPtr
1871 /// \ingroup SmartPointerGroup
1872 ////////////////////////////////////////////////////////////////////////////////
1877 template <class> class OP,
1879 template <class> class KP,
1880 template <class> class SP,
1881 template <class> class CNP,
1884 inline bool operator>=(U *lhs,
1885 const SmartPtr<T, OP, CP, KP, SP, CNP >& rhs)
1887 return !(lhs < rhs);
1892 ////////////////////////////////////////////////////////////////////////////////
1893 /// specialization of std::less for SmartPtr
1894 /// \ingroup SmartPointerGroup
1895 ////////////////////////////////////////////////////////////////////////////////
1902 template <class> class OP,
1904 template <class> class KP,
1905 template <class> class SP,
1906 template <class> class CNP
1908 struct less< Loki::SmartPtr<T, OP, CP, KP, SP, CNP > >
1909 : public binary_function<Loki::SmartPtr<T, OP, CP, KP, SP, CNP >,
1910 Loki::SmartPtr<T, OP, CP, KP, SP, CNP >, bool>
1912 bool operator()(const Loki::SmartPtr<T, OP, CP, KP, SP, CNP >& lhs,
1913 const Loki::SmartPtr<T, OP, CP, KP, SP, CNP >& rhs) const
1915 return less<T *>()(GetImpl(lhs), GetImpl(rhs));
1920 #endif // end file guardian