00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00015 #ifndef LOKI_SMARTPTR_INC_
00016 #define LOKI_SMARTPTR_INC_
00017
00018
00019
00020
00031
00032 #include "LokiExport.h"
00033 #include "SmallObj.h"
00034 #include "TypeManip.h"
00035 #include "static_check.h"
00036 #include "RefToValue.h"
00037 #include "ConstPolicy.h"
00038
00039 #include <functional>
00040 #include <stdexcept>
00041 #include <cassert>
00042 #include <string>
00043
00044 #if !defined(_MSC_VER)
00045 #include <stdint.h>
00046 #endif
00047
00048 #if defined(_MSC_VER) || defined(__GNUC__)
00049
00050 #define LOKI_ENABLE_FRIEND_TEMPLATE_TEMPLATE_PARAMETER_WORKAROUND
00051 #endif
00052
00053
00054 namespace Loki
00055 {
00056
00064
00065
00066 template <class T>
00067 class HeapStorage
00068 {
00069 public:
00070 typedef T* StoredType;
00071 typedef T* InitPointerType;
00072 typedef T* PointerType;
00073 typedef T& ReferenceType;
00074
00075 HeapStorage() : pointee_(Default())
00076 {}
00077
00078
00079
00080 HeapStorage(const HeapStorage&) : pointee_(0)
00081 {}
00082
00083 template <class U>
00084 HeapStorage(const HeapStorage<U>&) : pointee_(0)
00085 {}
00086
00087 HeapStorage(const StoredType& p) : pointee_(p) {}
00088
00089 PointerType operator->() const { return pointee_; }
00090
00091 ReferenceType operator*() const { return *pointee_; }
00092
00093 void Swap(HeapStorage& rhs)
00094 { std::swap(pointee_, rhs.pointee_); }
00095
00096
00097 template <class F>
00098 friend typename HeapStorage<F>::PointerType GetImpl(const HeapStorage<F>& sp);
00099
00100 template <class F>
00101 friend const typename HeapStorage<F>::StoredType& GetImplRef(const HeapStorage<F>& sp);
00102
00103 template <class F>
00104 friend typename HeapStorage<F>::StoredType& GetImplRef(HeapStorage<F>& sp);
00105
00106 protected:
00107
00108
00109 void Destroy()
00110 {
00111 if ( 0 != pointee_ )
00112 {
00113 pointee_->~T();
00114 ::free( pointee_ );
00115 }
00116 }
00117
00118
00119 static StoredType Default()
00120 { return 0; }
00121
00122 private:
00123
00124 StoredType pointee_;
00125 };
00126
00127 template <class T>
00128 inline typename HeapStorage<T>::PointerType GetImpl(const HeapStorage<T>& sp)
00129 { return sp.pointee_; }
00130
00131 template <class T>
00132 inline const typename HeapStorage<T>::StoredType& GetImplRef(const HeapStorage<T>& sp)
00133 { return sp.pointee_; }
00134
00135 template <class T>
00136 inline typename HeapStorage<T>::StoredType& GetImplRef(HeapStorage<T>& sp)
00137 { return sp.pointee_; }
00138
00139
00146
00147
00148 template <class T>
00149 class DefaultSPStorage
00150 {
00151 public:
00152 typedef T* StoredType;
00153 typedef T* InitPointerType;
00154 typedef T* PointerType;
00155 typedef T& ReferenceType;
00156
00157 DefaultSPStorage() : pointee_(Default())
00158 {}
00159
00160
00161
00162 DefaultSPStorage(const DefaultSPStorage&) : pointee_(0)
00163 {}
00164
00165 template <class U>
00166 DefaultSPStorage(const DefaultSPStorage<U>&) : pointee_(0)
00167 {}
00168
00169 DefaultSPStorage(const StoredType& p) : pointee_(p) {}
00170
00171 PointerType operator->() const { return pointee_; }
00172
00173 ReferenceType operator*() const { return *pointee_; }
00174
00175 void Swap(DefaultSPStorage& rhs)
00176 { std::swap(pointee_, rhs.pointee_); }
00177
00178
00179 template <class F>
00180 friend typename DefaultSPStorage<F>::PointerType GetImpl(const DefaultSPStorage<F>& sp);
00181
00182 template <class F>
00183 friend const typename DefaultSPStorage<F>::StoredType& GetImplRef(const DefaultSPStorage<F>& sp);
00184
00185 template <class F>
00186 friend typename DefaultSPStorage<F>::StoredType& GetImplRef(DefaultSPStorage<F>& sp);
00187
00188 protected:
00189
00190
00191 void Destroy()
00192 {
00193 delete pointee_;
00194 }
00195
00196
00197 static StoredType Default()
00198 { return 0; }
00199
00200 private:
00201
00202 StoredType pointee_;
00203 };
00204
00205 template <class T>
00206 inline typename DefaultSPStorage<T>::PointerType GetImpl(const DefaultSPStorage<T>& sp)
00207 { return sp.pointee_; }
00208
00209 template <class T>
00210 inline const typename DefaultSPStorage<T>::StoredType& GetImplRef(const DefaultSPStorage<T>& sp)
00211 { return sp.pointee_; }
00212
00213 template <class T>
00214 inline typename DefaultSPStorage<T>::StoredType& GetImplRef(DefaultSPStorage<T>& sp)
00215 { return sp.pointee_; }
00216
00217
00240
00241 template <class T>
00242 class Locker
00243 {
00244 public:
00245 Locker( const T * p ) : pointee_( const_cast< T * >( p ) )
00246 {
00247 if ( pointee_ != 0 )
00248 pointee_->Lock();
00249 }
00250
00251 ~Locker( void )
00252 {
00253 if ( pointee_ != 0 )
00254 pointee_->Unlock();
00255 }
00256
00257 operator T * ()
00258 {
00259 return pointee_;
00260 }
00261
00262 T * operator->()
00263 {
00264 return pointee_;
00265 }
00266
00267 private:
00268 Locker( void );
00269 Locker & operator = ( const Locker & );
00270 T * pointee_;
00271 };
00272
00273 template <class T>
00274 class LockedStorage
00275 {
00276 public:
00277
00278 typedef T* StoredType;
00279 typedef T* InitPointerType;
00280 typedef Locker< T > PointerType;
00281 typedef T& ReferenceType;
00282
00283 LockedStorage() : pointee_( Default() ) {}
00284
00285 ~LockedStorage( void ) {}
00286
00287 LockedStorage( const LockedStorage&) : pointee_( 0 ) {}
00288
00289 LockedStorage( const StoredType & p ) : pointee_( p ) {}
00290
00291 PointerType operator->()
00292 {
00293 return Locker< T >( pointee_ );
00294 }
00295
00296 void Swap(LockedStorage& rhs)
00297 {
00298 std::swap( pointee_, rhs.pointee_ );
00299 }
00300
00301
00302 template <class F>
00303 friend typename LockedStorage<F>::InitPointerType GetImpl(const LockedStorage<F>& sp);
00304
00305 template <class F>
00306 friend const typename LockedStorage<F>::StoredType& GetImplRef(const LockedStorage<F>& sp);
00307
00308 template <class F>
00309 friend typename LockedStorage<F>::StoredType& GetImplRef(LockedStorage<F>& sp);
00310
00311 protected:
00312
00313
00314 void Destroy()
00315 {
00316 delete pointee_;
00317 }
00318
00319
00320 static StoredType Default()
00321 { return 0; }
00322
00323 private:
00325 ReferenceType operator*();
00326
00327
00328 StoredType pointee_;
00329 };
00330
00331 template <class T>
00332 inline typename LockedStorage<T>::InitPointerType GetImpl(const LockedStorage<T>& sp)
00333 { return sp.pointee_; }
00334
00335 template <class T>
00336 inline const typename LockedStorage<T>::StoredType& GetImplRef(const LockedStorage<T>& sp)
00337 { return sp.pointee_; }
00338
00339 template <class T>
00340 inline typename LockedStorage<T>::StoredType& GetImplRef(LockedStorage<T>& sp)
00341 { return sp.pointee_; }
00342
00343
00350
00351
00352 template <class T>
00353 class ArrayStorage
00354 {
00355 public:
00356 typedef T* StoredType;
00357 typedef T* InitPointerType;
00358 typedef T* PointerType;
00359 typedef T& ReferenceType;
00360
00361 ArrayStorage() : pointee_(Default())
00362 {}
00363
00364
00365
00366 ArrayStorage(const ArrayStorage&) : pointee_(0)
00367 {}
00368
00369 template <class U>
00370 ArrayStorage(const ArrayStorage<U>&) : pointee_(0)
00371 {}
00372
00373 ArrayStorage(const StoredType& p) : pointee_(p) {}
00374
00375 PointerType operator->() const { return pointee_; }
00376
00377 ReferenceType operator*() const { return *pointee_; }
00378
00379 void Swap(ArrayStorage& rhs)
00380 { std::swap(pointee_, rhs.pointee_); }
00381
00382
00383 template <class F>
00384 friend typename ArrayStorage<F>::PointerType GetImpl(const ArrayStorage<F>& sp);
00385
00386 template <class F>
00387 friend const typename ArrayStorage<F>::StoredType& GetImplRef(const ArrayStorage<F>& sp);
00388
00389 template <class F>
00390 friend typename ArrayStorage<F>::StoredType& GetImplRef(ArrayStorage<F>& sp);
00391
00392 protected:
00393
00394
00395 void Destroy()
00396 { delete [] pointee_; }
00397
00398
00399 static StoredType Default()
00400 { return 0; }
00401
00402 private:
00403
00404 StoredType pointee_;
00405 };
00406
00407 template <class T>
00408 inline typename ArrayStorage<T>::PointerType GetImpl(const ArrayStorage<T>& sp)
00409 { return sp.pointee_; }
00410
00411 template <class T>
00412 inline const typename ArrayStorage<T>::StoredType& GetImplRef(const ArrayStorage<T>& sp)
00413 { return sp.pointee_; }
00414
00415 template <class T>
00416 inline typename ArrayStorage<T>::StoredType& GetImplRef(ArrayStorage<T>& sp)
00417 { return sp.pointee_; }
00418
00419
00427
00428 template <class P>
00429 class RefCounted
00430 {
00431 public:
00432 RefCounted()
00433 : pCount_(static_cast<uintptr_t*>(
00434 SmallObject<>::operator new(sizeof(uintptr_t))))
00435 {
00436 assert(pCount_!=0);
00437 *pCount_ = 1;
00438 }
00439
00440 RefCounted(const RefCounted& rhs)
00441 : pCount_(rhs.pCount_)
00442 {}
00443
00444
00445 template <typename P1>
00446 RefCounted(const RefCounted<P1>& rhs)
00447 : pCount_(reinterpret_cast<const RefCounted&>(rhs).pCount_)
00448 {}
00449
00450 P Clone(const P& val)
00451 {
00452 ++*pCount_;
00453 return val;
00454 }
00455
00456 bool Release(const P&)
00457 {
00458 if (!--*pCount_)
00459 {
00460 SmallObject<>::operator delete(pCount_, sizeof(uintptr_t));
00461 pCount_ = NULL;
00462 return true;
00463 }
00464 return false;
00465 }
00466
00467 void Swap(RefCounted& rhs)
00468 { std::swap(pCount_, rhs.pCount_); }
00469
00470 enum { destructiveCopy = false };
00471
00472 private:
00473
00474 uintptr_t* pCount_;
00475 };
00476
00489
00490 template <template <class, class> class ThreadingModel,
00491 class MX = LOKI_DEFAULT_MUTEX >
00492 struct RefCountedMTAdj
00493 {
00494 template <class P>
00495 class RefCountedMT : public ThreadingModel< RefCountedMT<P>, MX >
00496 {
00497 typedef ThreadingModel< RefCountedMT<P>, MX > base_type;
00498 typedef typename base_type::IntType CountType;
00499 typedef volatile CountType *CountPtrType;
00500
00501 public:
00502 RefCountedMT()
00503 {
00504 pCount_ = static_cast<CountPtrType>(
00505 SmallObject<LOKI_DEFAULT_THREADING_NO_OBJ_LEVEL>::operator new(
00506 sizeof(*pCount_)));
00507 assert(pCount_);
00508
00509 ThreadingModel<RefCountedMT, MX>::AtomicAssign(*pCount_, 1);
00510 }
00511
00512 RefCountedMT(const RefCountedMT& rhs)
00513 : pCount_(rhs.pCount_)
00514 {}
00515
00516
00517 template <typename P1>
00518 RefCountedMT(const RefCountedMT<P1>& rhs)
00519 : pCount_(reinterpret_cast<const RefCountedMT<P>&>(rhs).pCount_)
00520 {}
00521
00522 P Clone(const P& val)
00523 {
00524 ThreadingModel<RefCountedMT, MX>::AtomicIncrement(*pCount_);
00525 return val;
00526 }
00527
00528 bool Release(const P&)
00529 {
00530 if (!ThreadingModel<RefCountedMT, MX>::AtomicDecrement(*pCount_))
00531 {
00532 SmallObject<LOKI_DEFAULT_THREADING_NO_OBJ_LEVEL>::operator delete(
00533 const_cast<CountType *>(pCount_),
00534 sizeof(*pCount_));
00535 return true;
00536 }
00537 return false;
00538 }
00539
00540 void Swap(RefCountedMT& rhs)
00541 { std::swap(pCount_, rhs.pCount_); }
00542
00543 enum { destructiveCopy = false };
00544
00545 private:
00546
00547 CountPtrType pCount_;
00548 };
00549 };
00550
00558
00559 template <class P>
00560 class COMRefCounted
00561 {
00562 public:
00563 COMRefCounted()
00564 {}
00565
00566 template <class U>
00567 COMRefCounted(const COMRefCounted<U>&)
00568 {}
00569
00570 static P Clone(const P& val)
00571 {
00572 if(val!=0)
00573 val->AddRef();
00574 return val;
00575 }
00576
00577 static bool Release(const P& val)
00578 {
00579 if(val!=0)
00580 val->Release();
00581 return false;
00582 }
00583
00584 enum { destructiveCopy = false };
00585
00586 static void Swap(COMRefCounted&)
00587 {}
00588 };
00589
00598
00599 template <class P>
00600 struct DeepCopy
00601 {
00602 DeepCopy()
00603 {}
00604
00605 template <class P1>
00606 DeepCopy(const DeepCopy<P1>&)
00607 {}
00608
00609 static P Clone(const P& val)
00610 { return val->Clone(); }
00611
00612 static bool Release(const P&)
00613 { return true; }
00614
00615 static void Swap(DeepCopy&)
00616 {}
00617
00618 enum { destructiveCopy = false };
00619 };
00620
00628
00629 namespace Private
00630 {
00631 class LOKI_EXPORT RefLinkedBase
00632 {
00633 public:
00634 RefLinkedBase()
00635 { prev_ = next_ = this; }
00636
00637 RefLinkedBase(const RefLinkedBase& rhs);
00638
00639 bool Release();
00640
00641 void Swap(RefLinkedBase& rhs);
00642
00643 bool Merge( RefLinkedBase & rhs );
00644
00645 enum { destructiveCopy = false };
00646
00647 private:
00648 static unsigned int CountPrevCycle( const RefLinkedBase * pThis );
00649 static unsigned int CountNextCycle( const RefLinkedBase * pThis );
00650 bool HasPrevNode( const RefLinkedBase * p ) const;
00651 bool HasNextNode( const RefLinkedBase * p ) const;
00652
00653 mutable const RefLinkedBase* prev_;
00654 mutable const RefLinkedBase* next_;
00655 };
00656 }
00657
00658 template <class P>
00659 class RefLinked : public Private::RefLinkedBase
00660 {
00661 public:
00662 RefLinked()
00663 {}
00664
00665 template <class P1>
00666 RefLinked(const RefLinked<P1>& rhs)
00667 : Private::RefLinkedBase(rhs)
00668 {}
00669
00670 static P Clone(const P& val)
00671 { return val; }
00672
00673 bool Release(const P&)
00674 { return Private::RefLinkedBase::Release(); }
00675
00676 template < class P1 >
00677 bool Merge( RefLinked< P1 > & rhs )
00678 {
00679 return Private::RefLinkedBase::Merge( rhs );
00680 }
00681 };
00682
00690
00691 template <class P>
00692 class DestructiveCopy
00693 {
00694 public:
00695 DestructiveCopy()
00696 {}
00697
00698 template <class P1>
00699 DestructiveCopy(const DestructiveCopy<P1>&)
00700 {}
00701
00702 template <class P1>
00703 static P Clone(P1& val)
00704 {
00705 P result(val);
00706 val = P1();
00707 return result;
00708 }
00709
00710 static bool Release(const P&)
00711 { return true; }
00712
00713 static void Swap(DestructiveCopy&)
00714 {}
00715
00716 enum { destructiveCopy = true };
00717 };
00718
00726
00727 template <class P>
00728 class NoCopy
00729 {
00730 public:
00731 NoCopy()
00732 {}
00733
00734 template <class P1>
00735 NoCopy(const NoCopy<P1>&)
00736 {}
00737
00738 static P Clone(const P&)
00739 {
00740
00741 static const bool DependedFalse = sizeof(P*) == 0;
00742
00743 LOKI_STATIC_CHECK(DependedFalse, This_Policy_Disallows_Value_Copying);
00744 }
00745
00746 static bool Release(const P&)
00747 { return true; }
00748
00749 static void Swap(NoCopy&)
00750 {}
00751
00752 enum { destructiveCopy = false };
00753 };
00754
00762
00763 struct AllowConversion
00764 {
00765 enum { allow = true };
00766
00767 void Swap(AllowConversion&)
00768 {}
00769 };
00770
00779
00780 struct DisallowConversion
00781 {
00782 DisallowConversion()
00783 {}
00784
00785 DisallowConversion(const AllowConversion&)
00786 {}
00787
00788 enum { allow = false };
00789
00790 void Swap(DisallowConversion&)
00791 {}
00792 };
00793
00801
00802 template <class P>
00803 struct NoCheck
00804 {
00805 NoCheck()
00806 {}
00807
00808 template <class P1>
00809 NoCheck(const NoCheck<P1>&)
00810 {}
00811
00812 static void OnDefault(const P&)
00813 {}
00814
00815 static void OnInit(const P&)
00816 {}
00817
00818 static void OnDereference(const P&)
00819 {}
00820
00821 static void Swap(NoCheck&)
00822 {}
00823 };
00824
00825
00833
00834 template <class P>
00835 struct AssertCheck
00836 {
00837 AssertCheck()
00838 {}
00839
00840 template <class P1>
00841 AssertCheck(const AssertCheck<P1>&)
00842 {}
00843
00844 template <class P1>
00845 AssertCheck(const NoCheck<P1>&)
00846 {}
00847
00848 static void OnDefault(const P&)
00849 {}
00850
00851 static void OnInit(const P&)
00852 {}
00853
00854 static void OnDereference(P val)
00855 { assert(val); (void)val; }
00856
00857 static void Swap(AssertCheck&)
00858 {}
00859 };
00860
00869
00870 template <class P>
00871 struct AssertCheckStrict
00872 {
00873 AssertCheckStrict()
00874 {}
00875
00876 template <class U>
00877 AssertCheckStrict(const AssertCheckStrict<U>&)
00878 {}
00879
00880 template <class U>
00881 AssertCheckStrict(const AssertCheck<U>&)
00882 {}
00883
00884 template <class P1>
00885 AssertCheckStrict(const NoCheck<P1>&)
00886 {}
00887
00888 static void OnDefault(P val)
00889 { assert(val); }
00890
00891 static void OnInit(P val)
00892 { assert(val); }
00893
00894 static void OnDereference(P val)
00895 { assert(val); }
00896
00897 static void Swap(AssertCheckStrict&)
00898 {}
00899 };
00900
00907
00908 struct NullPointerException : public std::runtime_error
00909 {
00910 NullPointerException() : std::runtime_error(std::string(""))
00911 { }
00912 const char* what() const throw()
00913 { return "Null Pointer Exception"; }
00914 };
00915
00923
00924 template <class P>
00925 struct RejectNullStatic
00926 {
00927 RejectNullStatic()
00928 {}
00929
00930 template <class P1>
00931 RejectNullStatic(const RejectNullStatic<P1>&)
00932 {}
00933
00934 template <class P1>
00935 RejectNullStatic(const NoCheck<P1>&)
00936 {}
00937
00938 template <class P1>
00939 RejectNullStatic(const AssertCheck<P1>&)
00940 {}
00941
00942 template <class P1>
00943 RejectNullStatic(const AssertCheckStrict<P1>&)
00944 {}
00945
00946 static void OnDefault(const P&)
00947 {
00948
00949 static const bool DependedFalse = sizeof(P*) == 0;
00950
00951 LOKI_STATIC_CHECK(DependedFalse, ERROR_This_Policy_Does_Not_Allow_Default_Initialization);
00952 }
00953
00954 static void OnInit(const P& val)
00955 { if (!val) throw NullPointerException(); }
00956
00957 static void OnDereference(const P& val)
00958 { if (!val) throw NullPointerException(); }
00959
00960 static void Swap(RejectNullStatic&)
00961 {}
00962 };
00963
00971
00972 template <class P>
00973 struct RejectNull
00974 {
00975 RejectNull()
00976 {}
00977
00978 template <class P1>
00979 RejectNull(const RejectNull<P1>&)
00980 {}
00981
00982 static void OnInit(P)
00983 {}
00984
00985 static void OnDefault(P)
00986 {}
00987
00988 void OnDereference(P val)
00989 { if (!val) throw NullPointerException(); }
00990
00991 void OnDereference(P val) const
00992 { if (!val) throw NullPointerException(); }
00993
00994 void Swap(RejectNull&)
00995 {}
00996 };
00997
01005
01006 template <class P>
01007 struct RejectNullStrict
01008 {
01009 RejectNullStrict()
01010 {}
01011
01012 template <class P1>
01013 RejectNullStrict(const RejectNullStrict<P1>&)
01014 {}
01015
01016 template <class P1>
01017 RejectNullStrict(const RejectNull<P1>&)
01018 {}
01019
01020 static void OnInit(P val)
01021 { if (!val) throw NullPointerException(); }
01022
01023 void OnDereference(P val)
01024 { OnInit(val); }
01025
01026 void OnDereference(P val) const
01027 { OnInit(val); }
01028
01029 void Swap(RejectNullStrict&)
01030 {}
01031 };
01032
01033
01035
01036
01038
01039 template
01040 <
01041 typename T,
01042 template <class> class OwnershipPolicy = RefCounted,
01043 class ConversionPolicy = DisallowConversion,
01044 template <class> class CheckingPolicy = AssertCheck,
01045 template <class> class StoragePolicy = DefaultSPStorage,
01046 template<class> class ConstnessPolicy = LOKI_DEFAULT_CONSTNESS
01047 >
01048 class SmartPtr;
01049
01051
01052
01053
01055
01056 template
01057 <
01058 typename T,
01059 template <class> class OwnershipPolicy = RefCounted,
01060 class ConversionPolicy = DisallowConversion,
01061 template <class> class CheckingPolicy = AssertCheck,
01062 template <class> class StoragePolicy = DefaultSPStorage,
01063 template<class> class ConstnessPolicy = LOKI_DEFAULT_CONSTNESS
01064 >
01065 struct SmartPtrDef
01066 {
01067 typedef SmartPtr
01068 <
01069 T,
01070 OwnershipPolicy,
01071 ConversionPolicy,
01072 CheckingPolicy,
01073 StoragePolicy,
01074 ConstnessPolicy
01075 >
01076 type;
01077 };
01078
01097
01098 template
01099 <
01100 typename T,
01101 template <class> class OwnershipPolicy,
01102 class ConversionPolicy,
01103 template <class> class CheckingPolicy,
01104 template <class> class StoragePolicy,
01105 template <class> class ConstnessPolicy
01106 >
01107 class SmartPtr
01108 : public StoragePolicy<T>
01109 , public OwnershipPolicy<typename StoragePolicy<T>::InitPointerType>
01110 , public CheckingPolicy<typename StoragePolicy<T>::StoredType>
01111 , public ConversionPolicy
01112 {
01113 typedef StoragePolicy<T> SP;
01114 typedef OwnershipPolicy<typename StoragePolicy<T>::InitPointerType> OP;
01115 typedef CheckingPolicy<typename StoragePolicy<T>::StoredType> KP;
01116 typedef ConversionPolicy CP;
01117
01118 public:
01119 typedef typename ConstnessPolicy<T>::Type* ConstPointerType;
01120 typedef typename ConstnessPolicy<T>::Type& ConstReferenceType;
01121
01122 typedef typename SP::PointerType PointerType;
01123 typedef typename SP::StoredType StoredType;
01124 typedef typename SP::ReferenceType ReferenceType;
01125
01126 typedef typename Select<OP::destructiveCopy,SmartPtr, const SmartPtr>::Result
01127 CopyArg;
01128
01129 private:
01130 struct NeverMatched {};
01131
01132 #ifdef LOKI_SMARTPTR_CONVERSION_CONSTRUCTOR_POLICY
01133 typedef typename Select< CP::allow, const StoredType&, NeverMatched>::Result ImplicitArg;
01134 typedef typename Select<!CP::allow, const StoredType&, NeverMatched>::Result ExplicitArg;
01135 #else
01136 typedef const StoredType& ImplicitArg;
01137 typedef typename Select<false, const StoredType&, NeverMatched>::Result ExplicitArg;
01138 #endif
01139
01140 public:
01141
01142 SmartPtr()
01143 {
01144 KP::OnDefault(GetImpl(*this));
01145 }
01146
01147 explicit
01148 SmartPtr(ExplicitArg p) : SP(p)
01149 {
01150 KP::OnInit(GetImpl(*this));
01151 }
01152
01153 SmartPtr(ImplicitArg p) : SP(p)
01154 {
01155 KP::OnInit(GetImpl(*this));
01156 }
01157
01158 SmartPtr(CopyArg& rhs) : SP(rhs), OP(rhs), KP(rhs), CP(rhs)
01159 {
01160 GetImplRef(*this) = OP::Clone(GetImplRef(rhs));
01161 }
01162
01163 template
01164 <
01165 typename T1,
01166 template <class> class OP1,
01167 class CP1,
01168 template <class> class KP1,
01169 template <class> class SP1,
01170 template <class> class CNP1
01171 >
01172 SmartPtr(const SmartPtr<T1, OP1, CP1, KP1, SP1, CNP1 >& rhs)
01173 : SP(rhs), OP(rhs), KP(rhs), CP(rhs)
01174 { GetImplRef(*this) = OP::Clone(GetImplRef(rhs)); }
01175
01176 template
01177 <
01178 typename T1,
01179 template <class> class OP1,
01180 class CP1,
01181 template <class> class KP1,
01182 template <class> class SP1,
01183 template <class> class CNP1
01184 >
01185 SmartPtr(SmartPtr<T1, OP1, CP1, KP1, SP1, CNP1 >& rhs)
01186 : SP(rhs), OP(rhs), KP(rhs), CP(rhs)
01187 {
01188 GetImplRef(*this) = OP::Clone(GetImplRef(rhs));
01189 }
01190
01191 SmartPtr(RefToValue<SmartPtr> rhs)
01192 : SP(rhs), OP(rhs), KP(rhs), CP(rhs)
01193 {}
01194
01195 operator RefToValue<SmartPtr>()
01196 { return RefToValue<SmartPtr>(*this); }
01197
01198 SmartPtr& operator=(CopyArg& rhs)
01199 {
01200 SmartPtr temp(rhs);
01201 temp.Swap(*this);
01202 return *this;
01203 }
01204
01205 template
01206 <
01207 typename T1,
01208 template <class> class OP1,
01209 class CP1,
01210 template <class> class KP1,
01211 template <class> class SP1,
01212 template <class> class CNP1
01213 >
01214 SmartPtr& operator=(const SmartPtr<T1, OP1, CP1, KP1, SP1, CNP1 >& rhs)
01215 {
01216 SmartPtr temp(rhs);
01217 temp.Swap(*this);
01218 return *this;
01219 }
01220
01221 template
01222 <
01223 typename T1,
01224 template <class> class OP1,
01225 class CP1,
01226 template <class> class KP1,
01227 template <class> class SP1,
01228 template <class> class CNP1
01229 >
01230 SmartPtr& operator=(SmartPtr<T1, OP1, CP1, KP1, SP1, CNP1 >& rhs)
01231 {
01232 SmartPtr temp(rhs);
01233 temp.Swap(*this);
01234 return *this;
01235 }
01236
01237 void Swap(SmartPtr& rhs)
01238 {
01239 OP::Swap(rhs);
01240 CP::Swap(rhs);
01241 KP::Swap(rhs);
01242 SP::Swap(rhs);
01243 }
01244
01245 ~SmartPtr()
01246 {
01247 if (OP::Release(GetImpl(*static_cast<SP*>(this))))
01248 {
01249 SP::Destroy();
01250 }
01251 }
01252
01253 #ifdef LOKI_ENABLE_FRIEND_TEMPLATE_TEMPLATE_PARAMETER_WORKAROUND
01254
01255
01256 friend inline void Release(SmartPtr& sp, typename SP::StoredType& p)
01257 {
01258 p = GetImplRef(sp);
01259 GetImplRef(sp) = SP::Default();
01260 }
01261
01262 friend inline void Reset(SmartPtr& sp, typename SP::StoredType p)
01263 { SmartPtr(p).Swap(sp); }
01264
01265 #else
01266
01267 template
01268 <
01269 typename T1,
01270 template <class> class OP1,
01271 class CP1,
01272 template <class> class KP1,
01273 template <class> class SP1,
01274 template <class> class CNP1
01275 >
01276 friend void Release(SmartPtr<T1, OP1, CP1, KP1, SP1, CNP1>& sp,
01277 typename SP1<T1>::StoredType& p);
01278
01279 template
01280 <
01281 typename T1,
01282 template <class> class OP1,
01283 class CP1,
01284 template <class> class KP1,
01285 template <class> class SP1,
01286 template <class> class CNP1
01287 >
01288 friend void Reset(SmartPtr<T1, OP1, CP1, KP1, SP1, CNP1>& sp,
01289 typename SP1<T1>::StoredType p);
01290 #endif
01291
01292
01293 template
01294 <
01295 typename T1,
01296 template <class> class OP1,
01297 class CP1,
01298 template <class> class KP1,
01299 template <class> class SP1,
01300 template <class> class CNP1
01301 >
01302 bool Merge( SmartPtr< T1, OP1, CP1, KP1, SP1, CNP1 > & rhs )
01303 {
01304 if ( GetImpl( *this ) != GetImpl( rhs ) )
01305 {
01306 return false;
01307 }
01308 return OP::template Merge( rhs );
01309 }
01310
01311 PointerType operator->()
01312 {
01313 KP::OnDereference(GetImplRef(*this));
01314 return SP::operator->();
01315 }
01316
01317 ConstPointerType operator->() const
01318 {
01319 KP::OnDereference(GetImplRef(*this));
01320 return SP::operator->();
01321 }
01322
01323 ReferenceType operator*()
01324 {
01325 KP::OnDereference(GetImplRef(*this));
01326 return SP::operator*();
01327 }
01328
01329 ConstReferenceType operator*() const
01330 {
01331 KP::OnDereference(GetImplRef(*this));
01332 return SP::operator*();
01333 }
01334
01335 bool operator!() const
01336 { return GetImpl(*this) == 0; }
01337
01338 static inline T * GetPointer( const SmartPtr & sp )
01339 { return GetImpl( sp ); }
01340
01341
01342 template
01343 <
01344 typename T1,
01345 template <class> class OP1,
01346 class CP1,
01347 template <class> class KP1,
01348 template <class> class SP1,
01349 template <class> class CNP1
01350 >
01351 bool operator==(const SmartPtr<T1, OP1, CP1, KP1, SP1, CNP1 >& rhs) const
01352 { return GetImpl(*this) == GetImpl(rhs); }
01353
01354
01355 template
01356 <
01357 typename T1,
01358 template <class> class OP1,
01359 class CP1,
01360 template <class> class KP1,
01361 template <class> class SP1,
01362 template <class> class CNP1
01363 >
01364 bool operator!=(const SmartPtr<T1, OP1, CP1, KP1, SP1, CNP1 >& rhs) const
01365 { return !(*this == rhs); }
01366
01367
01368 template
01369 <
01370 typename T1,
01371 template <class> class OP1,
01372 class CP1,
01373 template <class> class KP1,
01374 template <class> class SP1,
01375 template <class> class CNP1
01376 >
01377 bool operator<(const SmartPtr<T1, OP1, CP1, KP1, SP1, CNP1 >& rhs) const
01378 { return GetImpl(*this) < GetImpl(rhs); }
01379
01380
01381 template
01382 <
01383 typename T1,
01384 template <class> class OP1,
01385 class CP1,
01386 template <class> class KP1,
01387 template <class> class SP1,
01388 template <class> class CNP1
01389 >
01390 inline bool operator > ( const SmartPtr< T1, OP1, CP1, KP1, SP1, CNP1 > & rhs )
01391 {
01392 return ( GetImpl( rhs ) < GetImpl( *this ) );
01393 }
01394
01395
01396 template
01397 <
01398 typename T1,
01399 template <class> class OP1,
01400 class CP1,
01401 template <class> class KP1,
01402 template <class> class SP1,
01403 template <class> class CNP1
01404 >
01405 inline bool operator <= ( const SmartPtr< T1, OP1, CP1, KP1, SP1, CNP1 > & rhs )
01406 {
01407 return !( GetImpl( rhs ) < GetImpl( *this ) );
01408 }
01409
01410
01411 template
01412 <
01413 typename T1,
01414 template <class> class OP1,
01415 class CP1,
01416 template <class> class KP1,
01417 template <class> class SP1,
01418 template <class> class CNP1
01419 >
01420 inline bool operator >= ( const SmartPtr< T1, OP1, CP1, KP1, SP1, CNP1 > & rhs )
01421 {
01422 return !( GetImpl( *this ) < GetImpl( rhs ) );
01423 }
01424
01425 private:
01426
01427 struct Tester
01428 {
01429 Tester(int) {}
01430 void dummy() {}
01431 };
01432
01433 typedef void (Tester::*unspecified_boolean_type_)();
01434
01435 typedef typename Select<CP::allow, Tester, unspecified_boolean_type_>::Result
01436 unspecified_boolean_type;
01437
01438 public:
01439
01440 operator unspecified_boolean_type() const
01441 {
01442 return !*this ? 0 : &Tester::dummy;
01443 }
01444
01445 private:
01446
01447 struct Insipid
01448 {
01449 Insipid(PointerType) {}
01450 };
01451
01452 typedef typename Select<CP::allow, PointerType, Insipid>::Result
01453 AutomaticConversionResult;
01454
01455 public:
01456 operator AutomaticConversionResult() const
01457 { return GetImpl(*this); }
01458 };
01459
01460
01462
01464
01465 #ifndef LOKI_ENABLE_FRIEND_TEMPLATE_TEMPLATE_PARAMETER_WORKAROUND
01466
01467 template
01468 <
01469 typename T,
01470 template <class> class OP,
01471 class CP,
01472 template <class> class KP,
01473 template <class> class SP,
01474 template <class> class CNP
01475 >
01476 inline void Release(SmartPtr<T, OP, CP, KP, SP, CNP>& sp,
01477 typename SP<T>::StoredType& p)
01478 {
01479 p = GetImplRef(sp);
01480 GetImplRef(sp) = SP<T>::Default();
01481 }
01482
01483 template
01484 <
01485 typename T,
01486 template <class> class OP,
01487 class CP,
01488 template <class> class KP,
01489 template <class> class SP,
01490 template <class> class CNP
01491 >
01492 inline void Reset(SmartPtr<T, OP, CP, KP, SP, CNP>& sp,
01493 typename SP<T>::StoredType p)
01494 { SmartPtr<T, OP, CP, KP, SP, CNP>(p).Swap(sp); }
01495
01496 #endif
01497
01499
01501
01506
01507 template
01508 <
01509 typename T,
01510 template <class> class OP,
01511 class CP,
01512 template <class> class KP,
01513 template <class> class SP,
01514 template <class> class CNP1,
01515 typename U
01516 >
01517 inline bool operator==(const SmartPtr<T, OP, CP, KP, SP, CNP1 >& lhs,
01518 U* rhs)
01519 { return GetImpl(lhs) == rhs; }
01520
01525
01526 template
01527 <
01528 typename T,
01529 template <class> class OP,
01530 class CP,
01531 template <class> class KP,
01532 template <class> class SP,
01533 template <class> class CNP1,
01534 typename U
01535 >
01536 inline bool operator==(U* lhs,
01537 const SmartPtr<T, OP, CP, KP, SP, CNP1 >& rhs)
01538 { return rhs == lhs; }
01539
01544
01545 template
01546 <
01547 typename T,
01548 template <class> class OP,
01549 class CP,
01550 template <class> class KP,
01551 template <class> class SP,
01552 template <class> class CNP,
01553 typename U
01554 >
01555 inline bool operator!=(const SmartPtr<T, OP, CP, KP, SP, CNP >& lhs,
01556 U* rhs)
01557 { return !(lhs == rhs); }
01558
01563
01564 template
01565 <
01566 typename T,
01567 template <class> class OP,
01568 class CP,
01569 template <class> class KP,
01570 template <class> class SP,
01571 template <class> class CNP,
01572 typename U
01573 >
01574 inline bool operator!=(U* lhs,
01575 const SmartPtr<T, OP, CP, KP, SP, CNP >& rhs)
01576 { return rhs != lhs; }
01577
01582
01583 template
01584 <
01585 typename T,
01586 template <class> class OP,
01587 class CP,
01588 template <class> class KP,
01589 template <class> class SP,
01590 template <class> class CNP,
01591 typename U
01592 >
01593 inline bool operator<(const SmartPtr<T, OP, CP, KP, SP, CNP >& lhs,
01594 U* rhs)
01595 {
01596 return ( GetImpl( lhs ) < rhs );
01597 }
01598
01603
01604 template
01605 <
01606 typename T,
01607 template <class> class OP,
01608 class CP,
01609 template <class> class KP,
01610 template <class> class SP,
01611 template <class> class CNP,
01612 typename U
01613 >
01614 inline bool operator<(U* lhs,
01615 const SmartPtr<T, OP, CP, KP, SP, CNP >& rhs)
01616 {
01617 return ( GetImpl( rhs ) < lhs );
01618 }
01619
01621
01624
01625 template
01626 <
01627 typename T,
01628 template <class> class OP,
01629 class CP,
01630 template <class> class KP,
01631 template <class> class SP,
01632 template <class> class CNP,
01633 typename U
01634 >
01635 inline bool operator>(const SmartPtr<T, OP, CP, KP, SP, CNP >& lhs,
01636 U* rhs)
01637 { return rhs < lhs; }
01638
01643
01644 template
01645 <
01646 typename T,
01647 template <class> class OP,
01648 class CP,
01649 template <class> class KP,
01650 template <class> class SP,
01651 template <class> class CNP,
01652 typename U
01653 >
01654 inline bool operator>(U* lhs,
01655 const SmartPtr<T, OP, CP, KP, SP, CNP >& rhs)
01656 { return rhs < lhs; }
01657
01662
01663 template
01664 <
01665 typename T,
01666 template <class> class OP,
01667 class CP,
01668 template <class> class KP,
01669 template <class> class SP,
01670 template <class> class CNP,
01671 typename U
01672 >
01673 inline bool operator<=(const SmartPtr<T, OP, CP, KP, SP, CNP >& lhs,
01674 U* rhs)
01675 { return !(rhs < lhs); }
01676
01681
01682 template
01683 <
01684 typename T,
01685 template <class> class OP,
01686 class CP,
01687 template <class> class KP,
01688 template <class> class SP,
01689 template <class> class CNP,
01690 typename U
01691 >
01692 inline bool operator<=(U* lhs,
01693 const SmartPtr<T, OP, CP, KP, SP, CNP >& rhs)
01694 { return !(rhs < lhs); }
01695
01700
01701 template
01702 <
01703 typename T,
01704 template <class> class OP,
01705 class CP,
01706 template <class> class KP,
01707 template <class> class SP,
01708 template <class> class CNP,
01709 typename U
01710 >
01711 inline bool operator>=(const SmartPtr<T, OP, CP, KP, SP, CNP >& lhs,
01712 U* rhs)
01713 { return !(lhs < rhs); }
01714
01719
01720 template
01721 <
01722 typename T,
01723 template <class> class OP,
01724 class CP,
01725 template <class> class KP,
01726 template <class> class SP,
01727 template <class> class CNP,
01728 typename U
01729 >
01730 inline bool operator>=(U* lhs,
01731 const SmartPtr<T, OP, CP, KP, SP, CNP >& rhs)
01732 { return !(lhs < rhs); }
01733
01734 }
01735
01740
01741 namespace std
01742 {
01743 template
01744 <
01745 typename T,
01746 template <class> class OP,
01747 class CP,
01748 template <class> class KP,
01749 template <class> class SP,
01750 template <class> class CNP
01751 >
01752 struct less< Loki::SmartPtr<T, OP, CP, KP, SP, CNP > >
01753 : public binary_function<Loki::SmartPtr<T, OP, CP, KP, SP, CNP >,
01754 Loki::SmartPtr<T, OP, CP, KP, SP, CNP >, bool>
01755 {
01756 bool operator()(const Loki::SmartPtr<T, OP, CP, KP, SP, CNP >& lhs,
01757 const Loki::SmartPtr<T, OP, CP, KP, SP, CNP >& rhs) const
01758 { return less<T*>()(GetImpl(lhs), GetImpl(rhs)); }
01759 };
01760 }
01761
01762 #endif // end file guardian
01763