SmartPtr.h

00001 
00002 // The Loki Library
00003 // Copyright (c) 2001 by Andrei Alexandrescu
00004 // This code accompanies the book:
00005 // Alexandrescu, Andrei. "Modern C++ Design: Generic Programming and Design 
00006 //     Patterns Applied". Copyright (c) 2001. Addison-Wesley.
00007 // Permission to use, copy, modify, distribute and sell this software for any 
00008 //     purpose is hereby granted without fee, provided that the above copyright 
00009 //     notice appear in all copies and that both that copyright notice and this 
00010 //     permission notice appear in supporting documentation.
00011 // The author or Addison-Wesley Longman make no representations about the 
00012 //     suitability of this software for any purpose. It is provided "as is" 
00013 //     without express or implied warranty.
00015 #ifndef LOKI_SMARTPTR_INC_
00016 #define LOKI_SMARTPTR_INC_
00017 
00018 // $Id: SmartPtr.h 791 2006-12-15 01:36:29Z rich_sposato $
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 // GCC>=4.1 must use -ffriend-injection due to a bug in GCC
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         // The storage policy doesn't initialize the stored pointer 
00079         //     which will be initialized by the OwnershipPolicy's Clone fn
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         // Accessors
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         // Destroys the data stored
00108         // (Destruction might be taken over by the OwnershipPolicy)
00109         void Destroy()
00110         {
00111             if ( 0 != pointee_ )
00112             {
00113                 pointee_->~T();
00114                 ::free( pointee_ );
00115             }
00116         }
00117 
00118         // Default value to initialize the pointer
00119         static StoredType Default()
00120         { return 0; }
00121     
00122     private:
00123         // Data
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;    // the type of the pointee_ object
00153         typedef T* InitPointerType; 
00154         typedef T* PointerType;   // type returned by operator->
00155         typedef T& ReferenceType; // type returned by operator*
00156 
00157         DefaultSPStorage() : pointee_(Default()) 
00158         {}
00159 
00160         // The storage policy doesn't initialize the stored pointer 
00161         //     which will be initialized by the OwnershipPolicy's Clone fn
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         // Accessors
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         // Destroys the data stored
00190         // (Destruction might be taken over by the OwnershipPolicy)
00191         void Destroy()
00192         {
00193             delete pointee_;
00194         }
00195 
00196         // Default value to initialize the pointer
00197         static StoredType Default()
00198         { return 0; }
00199     
00200     private:
00201         // Data
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         // Accessors
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         // Destroys the data stored
00313         // (Destruction might be taken over by the OwnershipPolicy)
00314         void Destroy()
00315         {
00316             delete pointee_;
00317         }
00318 
00319         // Default value to initialize the pointer
00320         static StoredType Default()
00321         { return 0; }
00322 
00323     private:
00325         ReferenceType operator*();
00326 
00327         // Data
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;    // the type of the pointee_ object
00357         typedef T* InitPointerType; 
00358         typedef T* PointerType;   // type returned by operator->
00359         typedef T& ReferenceType; // type returned by operator*
00360 
00361         ArrayStorage() : pointee_(Default()) 
00362         {}
00363 
00364         // The storage policy doesn't initialize the stored pointer 
00365         //     which will be initialized by the OwnershipPolicy's Clone fn
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         // Accessors
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         // Destroys the data stored
00394         // (Destruction might be taken over by the OwnershipPolicy)
00395         void Destroy()
00396         { delete [] pointee_; }
00397         
00398         // Default value to initialize the pointer
00399         static StoredType Default()
00400         { return 0; }
00401     
00402     private:
00403         // Data
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         // MWCW lacks template friends, hence the following kludge
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         // Data
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                 //*pCount_ = 1;
00509                 ThreadingModel<RefCountedMT, MX>::AtomicAssign(*pCount_, 1);
00510             }
00511 
00512             RefCountedMT(const RefCountedMT& rhs) 
00513             : pCount_(rhs.pCount_)
00514             {}
00515 
00516             //MWCW lacks template friends, hence the following kludge
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             // Data
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             // Make it depended on template parameter
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             // Make it depended on template parameter
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 // class template SmartPtr (declaration)
01036 // The reason for all the fuss above
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 // class template SmartPtrDef (definition)
01052 // this class added to unify the usage of SmartPtr 
01053 // instead of writing SmartPtr<T,OP,CP,KP,SP> write SmartPtrDef<T,OP,CP,KP,SP>::type
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         // old non standard in class definition of friends
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 // Enables "if (!sp) ..."
01336         { return GetImpl(*this) == 0; }
01337 
01338         static inline T * GetPointer( const SmartPtr & sp )
01339         { return GetImpl( sp ); }
01340 
01341         // Ambiguity buster
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         // Ambiguity buster
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         // Ambiguity buster
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         // Ambiguity buster
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         // Ambiguity buster
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         // Ambiguity buster
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         // Helper for enabling 'if (sp)'
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         // enable 'if (sp)'
01440         operator unspecified_boolean_type() const
01441         {
01442             return !*this ? 0 : &Tester::dummy;
01443         }
01444 
01445     private:
01446         // Helper for disallowing automatic conversion
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 // friends
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 // free comparison operators for class template SmartPtr
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 //  operator> for lhs = SmartPtr, rhs = raw pointer
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 } // namespace Loki
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 

Generated on Sun Feb 25 16:52:28 2007 for Loki by  doxygen 1.5.1-p1