00001 
00002 
00003 
00004 
00005 
00006 
00007 
00008 
00009 
00010 
00011 
00012 
00013 
00014 
00015 
00016 
00017 
00018 
00019 
00020 
00021 
00022 
00023 
00024 
00025 
00026 
00027 
00028 
00029 
00030 
00031 
00032 
00033 
00034 
00035 
00036 
00037 
00038 
00039 
00040 
00041 
00042 
00043 
00044 
00045 
00046 
00047 
00048 
00049 
00050 
00051 
00052 
00053 
00054 
00055 #ifndef SMARTPTR_INC_
00056 #define SMARTPTR_INC_
00057 
00058 
00059 
00060 
00061 
00062 
00063 
00064 
00065 
00066 
00067 #include <base/SmallObj>
00068 #include <base/TypeManip>
00069 #include <base/NullType>
00070 #include <base/static_check>
00071 #include <functional>
00072 #include <stdexcept>
00073 
00074 namespace base
00075 {
00076 
00077 
00078 
00079 
00080 
00081 
00082     template <class T>
00083     class DefaultSPStorage
00084     {
00085     public:
00086         typedef T* StoredType;    
00087         typedef T* PointerType;   
00088         typedef T& ReferenceType; 
00089         
00090         DefaultSPStorage() : pointee_(Default()) 
00091         {}
00092 
00093         
00094         
00095         DefaultSPStorage(const DefaultSPStorage&)
00096         {}
00097 
00098         template <class U>
00099         DefaultSPStorage(const DefaultSPStorage<U>&) 
00100         {}
00101         
00102         DefaultSPStorage(const StoredType& p) : pointee_(p) {}
00103         
00104         PointerType operator->() const { return pointee_; }
00105         
00106         ReferenceType operator*() const { return *pointee_; }
00107         
00108         void Swap(DefaultSPStorage& rhs)
00109         { std::swap(pointee_, rhs.pointee_); }
00110     
00111         
00112         friend inline PointerType GetImpl(const DefaultSPStorage& sp)
00113         { return sp.pointee_; }
00114         
00115         friend inline const StoredType& GetImplRef(const DefaultSPStorage& sp)
00116         { return sp.pointee_; }
00117 
00118         friend inline StoredType& GetImplRef(DefaultSPStorage& sp)
00119         { return sp.pointee_; }
00120 
00121         
00122         static StoredType Default()
00123         { return 0; }
00124 
00125     protected:
00126         
00127         
00128         void Destroy()
00129         { delete pointee_; }
00130     
00131     private:
00132         
00133         StoredType pointee_;
00134     };
00135 
00136 
00137 
00138 
00139 
00140 
00141 
00142     template <class P>
00143     class RefCounted
00144     {
00145     public:
00146         RefCounted() 
00147         {
00148             pCount_ = static_cast<unsigned int*>(
00149                 SmallObject<>::operator new(sizeof(unsigned int)));
00150             assert(pCount_);
00151             *pCount_ = 1;
00152         }
00153         
00154         RefCounted(const RefCounted& rhs) 
00155         : pCount_(rhs.pCount_)
00156         {}
00157         
00158         
00159         template <typename P1>
00160         RefCounted(const RefCounted<P1>& rhs) 
00161         : pCount_(reinterpret_cast<const RefCounted&>(rhs).pCount_)
00162         {}
00163         
00164         P Clone(const P& val)
00165         {
00166             ++*pCount_;
00167             return val;
00168         }
00169         
00170         void OnInit(const P&)
00171         {}
00172 
00173         bool Release(const P&)
00174         {
00175             if (!--*pCount_)
00176             {
00177                 SmallObject<>::operator delete(pCount_, sizeof(unsigned int));
00178                 return true;
00179             }
00180             return false;
00181         }
00182         
00183         void Swap(RefCounted& rhs)
00184         { std::swap(pCount_, rhs.pCount_); }
00185     
00186         enum { destructiveCopy = false };
00187 
00188     private:
00189         
00190         unsigned int* pCount_;
00191     };
00192     
00193 
00194 
00195 
00196 
00197 
00198     template <class P,
00199         template <class> class ThreadingModel>
00200     class RefCountedMT : public ThreadingModel< RefCountedMT<P, ThreadingModel> >
00201     {
00202     public:
00203         RefCountedMT() 
00204         {
00205             pCount_ = static_cast<unsigned int*>(
00206                 SmallObject<ThreadingModel>::operator new(
00207                     sizeof(unsigned int)));
00208             assert(pCount_);
00209             *pCount_ = 1;
00210         }
00211         
00212         RefCountedMT(const RefCountedMT& rhs) 
00213         : pCount_(rhs.pCount_)
00214         {}
00215         
00216         
00217         template <typename P1>
00218         RefCountedMT(const RefCountedMT<P1, ThreadingModel>& rhs) 
00219         : pCount_(reinterpret_cast<const RefCounted<P>&>(rhs).pCount_)
00220         {}
00221         
00222         P Clone(const P& val)
00223         {
00224             ThreadingModel<RefCountedMT>::AtomicIncrement(*pCount_);
00225             return val;
00226         }
00227         
00228         void OnInit(const P&)
00229         {}
00230 
00231         bool Release(const P&)
00232         {
00233             if (!ThreadingModel<RefCountedMT>::AtomicDecrement(*pCount_))
00234             {
00235                 SmallObject<ThreadingModel>::operator delete(pCount_, 
00236                     sizeof(unsigned int));
00237                 return true;
00238             }
00239             return false;
00240         }
00241         
00242         void Swap(RefCountedMT& rhs)
00243         { std::swap(pCount_, rhs.pCount_); }
00244     
00245         enum { destructiveCopy = false };
00246 
00247     private:
00248         
00249         volatile unsigned int* pCount_;
00250     };
00251 
00252 
00253 
00254 
00255 
00256 
00257 
00258     template <class P>
00259     class COMRefCounted
00260     {
00261     public:
00262         COMRefCounted()
00263         {}
00264         
00265         template <class U>
00266         COMRefCounted(const COMRefCounted<U>&)
00267         {}
00268         
00269         static P Clone(const P& val)
00270         {
00271             val->AddRef();
00272             return val;
00273         }
00274         
00275         static void OnInit(const P&)
00276         {}
00277 
00278         static bool Release(const P& val)
00279         { val->Release(); return false; }
00280         
00281         enum { destructiveCopy = false };
00282         
00283         static void Swap(COMRefCounted&)
00284         {}
00285     };
00286 
00287 
00288 
00289 
00290 
00291 
00292 
00293     template <class P>
00294     class IntrRefCounted
00295     {
00296     public:
00297         IntrRefCounted()
00298         {}
00299         
00300         template <class U>
00301         IntrRefCounted(const IntrRefCounted<U>&)
00302         {}
00303         
00304         static P Clone(const P& val)
00305         {
00306           if (val!=0)
00307             val->reference();
00308           return val;
00309         }
00310         
00311         static void OnInit(const P& val)
00312         {
00313           if (val!=0)
00314             val->reference();
00315         }
00316 
00317         static bool Release(const P& val)
00318         { 
00319           if (val!=0) 
00320             return val->unreference(); 
00321           return false;
00322         }
00323         
00324         enum { destructiveCopy = false };
00325         
00326         static void Swap(IntrRefCounted&)
00327         {}
00328     };
00329 
00330 
00331 
00332 
00333 
00334 
00335 
00336     template <class P>
00337     class NonSmartShared
00338     {
00339     public:
00340         NonSmartShared()
00341         {}
00342         
00343         template <class U>
00344         NonSmartShared(const NonSmartShared<U>&)
00345         {}
00346         
00347         static P Clone(const P& val)
00348         {
00349           return val;
00350         }
00351         
00352         static void OnInit(const P& val)
00353         {}
00354 
00355         static bool Release(const P& val)
00356         { 
00357           return false;
00358         }
00359         
00360         enum { destructiveCopy = false };
00361         
00362         static void Swap(NonSmartShared&)
00363         {}
00364     };
00365 
00366 
00367 
00368 
00369 
00370 
00371 
00372 
00373     template <class P>
00374     struct DeepCopy
00375     {
00376         DeepCopy()
00377         {}
00378         
00379         template <class P1>
00380         DeepCopy(const DeepCopy<P1>&)
00381         {}
00382         
00383         static P Clone(const P& val)
00384         { return val->Clone(); }
00385         
00386         static void OnInit(const P&)
00387         {}
00388 
00389         static bool Release(const P& val)
00390         { return true; }
00391         
00392         static void Swap(DeepCopy&)
00393         {}
00394         
00395         enum { destructiveCopy = false };
00396     };
00397     
00398 
00399 
00400 
00401 
00402 
00403 
00404     namespace Private
00405     {
00406         class RefLinkedBase
00407         {
00408         public:
00409             RefLinkedBase() 
00410             { prev_ = next_ = this; }
00411             
00412             RefLinkedBase(const RefLinkedBase& rhs) 
00413             {
00414                 prev_ = &rhs;
00415                 next_ = rhs.next_;
00416                 prev_->next_ = this;
00417                 next_->prev_ = this;
00418             }
00419             
00420             bool Release()
00421             {
00422                 if (next_ == this)
00423                 {   
00424                     assert(prev_ == this);
00425                     return true;
00426                 }
00427                 prev_->next_ = next_;
00428                 next_->prev_ = prev_;
00429                 return false;
00430             }
00431             
00432             void Swap(RefLinkedBase& rhs)
00433             {
00434                 if (next_ == this)
00435                 {
00436                     assert(prev_ == this);
00437                     if (rhs.next_ == &rhs)
00438                     {
00439                         assert(rhs.prev_ == &rhs);
00440                         
00441                         return;
00442                     }
00443                     prev_ = rhs.prev_;
00444                     next_ = rhs.next_;
00445                     prev_->next_ = next_->prev_ = this;
00446                     rhs.next_ = rhs.prev_ = &rhs;
00447                     return;
00448                 }
00449                 if (rhs.next_ == &rhs)
00450                 {
00451                     rhs.Swap(*this);
00452                     return;
00453                 }
00454                 std::swap(prev_, rhs.prev_);
00455                 std::swap(next_, rhs.next_);
00456                 std::swap(prev_->next_, rhs.prev_->next_);
00457                 std::swap(next_->prev_, rhs.next_->prev_);
00458             }
00459                 
00460             enum { destructiveCopy = false };
00461 
00462         private:
00463             mutable const RefLinkedBase* prev_;
00464             mutable const RefLinkedBase* next_;
00465         };
00466     }
00467     
00468     template <class P>
00469     class RefLinked : public Private::RefLinkedBase
00470     {
00471     public:
00472         RefLinked()
00473         {}
00474         
00475         template <class P1>
00476         RefLinked(const RefLinked<P1>& rhs) 
00477         : Private::RefLinkedBase(rhs)
00478         {}
00479 
00480         static P Clone(const P& val)
00481         { return val; }
00482 
00483         static void OnInit(const P&)
00484         {}
00485 
00486         bool Release(const P&)
00487         { return Private::RefLinkedBase::Release(); }
00488     };
00489     
00490 
00491 
00492 
00493 
00494 
00495 
00496     template <class P>
00497     class DestructiveCopy
00498     {
00499     public:
00500         DestructiveCopy()
00501         {}
00502         
00503         template <class P1>
00504         DestructiveCopy(const DestructiveCopy<P1>&)
00505         {}
00506         
00507         template <class P1>
00508         static P Clone(P1& val)
00509         {
00510             P result(val);
00511             val = P1();
00512             return result;
00513         }
00514 
00515         static void OnInit(const P&)
00516         {}
00517 
00518         static bool Release(const P&)
00519         { return true; }
00520         
00521         static void Swap(DestructiveCopy&)
00522         {}
00523         
00524         enum { destructiveCopy = true };
00525     };
00526     
00527 
00528 
00529 
00530 
00531 
00532 
00533     template <class P>
00534     class NoCopy
00535     {
00536     public:
00537         NoCopy()
00538         {}
00539         
00540         template <class P1>
00541         NoCopy(const NoCopy<P1>&)
00542         {}
00543         
00544         static P Clone(const P&)
00545         {
00546             CT_ASSERT(false, This_Policy_Disallows_Value_Copying);
00547         }
00548 
00549         static void OnInit(const P&)
00550         {}
00551 
00552         static bool Release(const P&)
00553         { return true; }
00554         
00555         static void Swap(NoCopy&)
00556         {}
00557         
00558         enum { destructiveCopy = false };
00559     };
00560     
00561 
00562 
00563 
00564 
00565 
00566 
00567     struct AllowConversion
00568     {
00569         enum { allow = true };
00570 
00571         void Swap(AllowConversion&)
00572         {}
00573     };
00574 
00575 
00576 
00577 
00578 
00579 
00580 
00581 
00582     struct DisallowConversion
00583     {
00584         DisallowConversion()
00585         {}
00586         
00587         DisallowConversion(const AllowConversion&)
00588         {}
00589         
00590         enum { allow = false };
00591 
00592         void Swap(DisallowConversion&)
00593         {}
00594     };
00595 
00596 
00597 
00598 
00599 
00600 
00601 
00602     template <class P>
00603     struct NoCheck
00604     {
00605         NoCheck()
00606         {}
00607         
00608         template <class P1>
00609         NoCheck(const NoCheck<P1>&)
00610         {}
00611         
00612         static void OnDefault(const P&)
00613         {}
00614 
00615         static void OnInit(const P&)
00616         {}
00617 
00618         static void OnDereference(const P&)
00619         {}
00620 
00621         static void Swap(NoCheck&)
00622         {}
00623     };
00624 
00625 
00626 
00627 
00628 
00629 
00630 
00631 
00632     template <class P>
00633     struct AssertCheck
00634     {
00635         AssertCheck()
00636         {}
00637         
00638         template <class P1>
00639         AssertCheck(const AssertCheck<P1>&)
00640         {}
00641         
00642         template <class P1>
00643         AssertCheck(const NoCheck<P1>&)
00644         {}
00645         
00646         static void OnDefault(const P&)
00647         {}
00648 
00649         static void OnInit(const P&)
00650         {}
00651 
00652         static void OnDereference(P val)
00653         { assert(val); }
00654 
00655         static void Swap(AssertCheck&)
00656         {}
00657     };
00658 
00659 
00660 
00661 
00662 
00663 
00664 
00665 
00666     template <class P>
00667     struct AssertCheckStrict
00668     {
00669         AssertCheckStrict()
00670         {}
00671         
00672         template <class U>
00673         AssertCheckStrict(const AssertCheckStrict<U>&)
00674         {}
00675         
00676         template <class U>
00677         AssertCheckStrict(const AssertCheck<U>&)
00678         {}
00679         
00680         template <class P1>
00681         AssertCheckStrict(const NoCheck<P1>&)
00682         {}
00683         
00684         static void OnDefault(P val)
00685         { assert(val); }
00686         
00687         static void OnInit(P val)
00688         { assert(val); }
00689         
00690         static void OnDereference(P val)
00691         { assert(val); }
00692         
00693         static void Swap(AssertCheckStrict&)
00694         {}
00695     };
00696 
00697 
00698 
00699 
00700 
00701 
00702     struct NullPointerException : public std::runtime_error
00703     {
00704         NullPointerException() : std::runtime_error("")
00705         { }
00706         const char* what() const throw()  
00707         { return "Null Pointer Exception"; }
00708     };
00709         
00710 
00711 
00712 
00713 
00714 
00715 
00716     template <class P>
00717     struct RejectNullStatic
00718     {
00719         RejectNullStatic()
00720         {}
00721         
00722         template <class P1>
00723         RejectNullStatic(const RejectNullStatic<P1>&)
00724         {}
00725         
00726         template <class P1>
00727         RejectNullStatic(const NoCheck<P1>&)
00728         {}
00729         
00730         template <class P1>
00731         RejectNullStatic(const AssertCheck<P1>&)
00732         {}
00733         
00734         template <class P1>
00735         RejectNullStatic(const AssertCheckStrict<P1>&)
00736         {}
00737         
00738         static void OnDefault(const P&)
00739         {
00740             CompileTimeError<false>
00741                 ERROR_This_Policy_Does_Not_Allow_Default_Initialization;
00742         }
00743         
00744         static void OnInit(const P& val)
00745         { if (!val) throw NullPointerException(); }
00746         
00747         static void OnDereference(const P& val)
00748         { if (!val) throw NullPointerException(); }
00749         
00750         static void Swap(RejectNullStatic&)
00751         {}
00752     };
00753 
00754 
00755 
00756 
00757 
00758 
00759 
00760     template <class P>
00761     struct RejectNull
00762     {
00763         RejectNull()
00764         {}
00765         
00766         template <class P1>
00767         RejectNull(const RejectNull<P1>&)
00768         {}
00769         
00770         static void OnInit(P val)
00771         { if (!val) throw NullPointerException(); }
00772 
00773         static void OnDefault(P val)
00774         { OnInit(val); }
00775         
00776         void OnDereference(P val)
00777         { OnInit(val); }
00778         
00779         void Swap(RejectNull&)
00780         {}        
00781     };
00782 
00783 
00784 
00785 
00786 
00787 
00788 
00789     template <class P>
00790     struct RejectNullStrict
00791     {
00792         RejectNullStrict()
00793         {}
00794         
00795         template <class P1>
00796         RejectNullStrict(const RejectNullStrict<P1>&)
00797         {}
00798         
00799         template <class P1>
00800         RejectNullStrict(const RejectNull<P1>&)
00801         {}
00802         
00803         static void OnInit(P val)
00804         { if (!val) throw NullPointerException(); }
00805 
00806         void OnDereference(P val)
00807         { OnInit(val); }
00808         
00809         void Swap(RejectNullStrict&)
00810         {}        
00811     };
00812 
00813 
00814 
00815 
00816 
00817 
00818 
00819     template <class T>
00820     class ByRef
00821     {
00822     public:
00823         ByRef(T& v) : value_(v) {}
00824         operator T&() { return value_; }
00825         
00826         
00827     private:
00828         T& value_;
00829     };
00830 
00831 
00832 
00833 
00834 
00835 
00836     template
00837     <
00838         typename T,
00839         template <class> class OwnershipPolicy = IntrRefCounted,
00840         class ConversionPolicy = DisallowConversion,
00841         template <class> class CheckingPolicy = AssertCheck,
00842         template <class> class StoragePolicy = DefaultSPStorage
00843     >
00844     class ref;
00845 
00846 
00847 
00848 
00849 
00850     template
00851     <
00852         typename T,
00853         template <class> class OwnershipPolicy,
00854         class ConversionPolicy,
00855         template <class> class CheckingPolicy,
00856         template <class> class StoragePolicy
00857     >
00858     class ref
00859         : public StoragePolicy<T>
00860         , public OwnershipPolicy<typename StoragePolicy<T>::PointerType>
00861         , public CheckingPolicy<typename StoragePolicy<T>::StoredType>
00862         , public ConversionPolicy
00863     {
00864         typedef StoragePolicy<T> SP;
00865         typedef OwnershipPolicy<typename StoragePolicy<T>::PointerType> OP;
00866         typedef CheckingPolicy<typename StoragePolicy<T>::StoredType> KP;
00867         typedef ConversionPolicy CP;
00868         
00869     public:
00870         typedef typename SP::PointerType PointerType;
00871         typedef typename SP::StoredType StoredType;
00872         typedef typename SP::ReferenceType ReferenceType;
00873         
00874         typedef typename Select<OP::destructiveCopy, 
00875                 ref, const ref>::Result
00876             CopyArg;
00877 
00878     
00879         ref()
00880         { KP::OnDefault(GetImpl(*this)); }
00881         
00882         explicit ref(const StoredType& p) : SP(p)
00883         { KP::OnInit(GetImpl(*this)); OP::OnInit(GetImpl(*this)); }
00884         
00885         ref(CopyArg& rhs)
00886         : SP(rhs), OP(rhs), KP(rhs), CP(rhs)
00887         { GetImplRef(*this) = OP::Clone(GetImplRef(rhs)); }
00888 
00889         template
00890         <
00891             typename T1,
00892             template <class> class OP1,
00893             class CP1,
00894             template <class> class KP1,
00895             template <class> class SP1
00896         >
00897         ref(const ref<T1, OP1, CP1, KP1, SP1>& rhs)
00898         : SP(rhs), OP(rhs), KP(rhs), CP(rhs)
00899         { GetImplRef(*this) = OP::Clone(GetImplRef(rhs)); }
00900 
00901         template
00902         <
00903             typename T1,
00904             template <class> class OP1,
00905             class CP1,
00906             template <class> class KP1,
00907             template <class> class SP1
00908         >
00909         ref(ref<T1, OP1, CP1, KP1, SP1>& rhs)
00910         : SP(rhs), OP(rhs), KP(rhs), CP(rhs)
00911         { GetImplRef(*this) = OP::Clone(GetImplRef(rhs)); }
00912 
00913 
00914         ref(ByRef<ref> rhs)
00915         : SP(rhs), OP(rhs), KP(rhs), CP(rhs)
00916         {}
00917         
00918         operator ByRef<ref>()
00919         { return ByRef<ref>(*this); }
00920 
00921         ref& operator=(CopyArg& rhs)
00922         {
00923             ref temp(rhs);
00924             temp.Swap(*this);
00925             return *this;
00926         }
00927 
00928         template
00929         <
00930             typename T1,
00931             template <class> class OP1,
00932             class CP1,
00933             template <class> class KP1,
00934             template <class> class SP1
00935         >
00936         ref& operator=(const ref<T1, OP1, CP1, KP1, SP1>& rhs)
00937         {
00938             ref temp(rhs);
00939             temp.Swap(*this);
00940             return *this;
00941         }
00942         
00943         template
00944         <
00945             typename T1,
00946             template <class> class OP1,
00947             class CP1,
00948             template <class> class KP1,
00949             template <class> class SP1
00950         >
00951         ref& operator=(ref<T1, OP1, CP1, KP1, SP1>& rhs)
00952         {
00953             ref temp(rhs);
00954             temp.Swap(*this);
00955             return *this;
00956         }
00957         
00958         void Swap(ref& rhs)
00959         {
00960             OP::Swap(rhs);
00961             CP::Swap(rhs);
00962             KP::Swap(rhs);
00963             SP::Swap(rhs);
00964         }
00965         
00966         ~ref()
00967         {
00968             if (OP::Release(GetImpl(*static_cast<SP*>(this))))
00969             {
00970               SP::Destroy();
00971             }
00972         }
00973         
00974         friend inline void Release(ref& sp, typename SP::StoredType& p)
00975         {
00976             p = GetImplRef(sp);
00977             GetImplRef(sp) = SP::Default();
00978         }
00979         
00980         friend inline void Release(ref& sp)
00981         {
00982             GetImplRef(sp) = SP::Default();
00983         }
00984         
00985         friend inline void Reset(ref& sp, typename SP::StoredType p)
00986         { ref(p).Swap(sp); }
00987 
00988         PointerType operator->()
00989         {
00990             KP::OnDereference(GetImplRef(*this));
00991             return SP::operator->();
00992         }
00993 
00994         PointerType operator->() const
00995         {
00996             KP::OnDereference(GetImplRef(*this));
00997             return SP::operator->();
00998         }
00999 
01000         ReferenceType operator*()
01001         {
01002             KP::OnDereference(GetImplRef(*this));
01003             return SP::operator*();
01004         }
01005         
01006         ReferenceType operator*() const
01007         {
01008             KP::OnDereference(GetImplRef(*this));
01009             return SP::operator*();
01010         }
01011 
01012         
01013         bool operator!() const 
01014         { return GetImpl(*this) == 0; }
01015         
01016         inline friend bool operator==(const ref& lhs,
01017             const T* rhs)
01018         { return GetImpl(lhs) == rhs; }
01019         
01020         inline friend bool operator==(const T* lhs,
01021             const ref& rhs)
01022         { return rhs == lhs; }
01023         
01024         inline friend bool operator!=(const ref& lhs,
01025             const T* rhs)
01026         { return !(lhs == rhs); }
01027         
01028         inline friend bool operator!=(const T* lhs,
01029             const ref& rhs)
01030         { return rhs != lhs; }
01031 
01032         
01033         template
01034         <
01035             typename T1,
01036             template <class> class OP1,
01037             class CP1,
01038             template <class> class KP1,
01039             template <class> class SP1
01040         >
01041         bool operator==(const ref<T1, OP1, CP1, KP1, SP1>& rhs) const
01042         { return *this == GetImpl(rhs); }
01043 
01044         
01045         template
01046         <
01047             typename T1,
01048             template <class> class OP1,
01049             class CP1,
01050             template <class> class KP1,
01051             template <class> class SP1
01052         >
01053         bool operator!=(const ref<T1, OP1, CP1, KP1, SP1>& rhs) const
01054         { return !(*this == rhs); }
01055 
01056         
01057         template
01058         <
01059             typename T1,
01060             template <class> class OP1,
01061             class CP1,
01062             template <class> class KP1,
01063             template <class> class SP1
01064         >
01065         bool operator<(const ref<T1, OP1, CP1, KP1, SP1>& rhs) const
01066         { return *this < GetImpl(rhs); }
01067 
01068     private:
01069         
01070         struct Tester
01071         {
01072             Tester() {}
01073         private:
01074             void operator delete(void*);
01075         };
01076         
01077     public:
01078         
01079         operator Tester*() const
01080         {
01081             if (!*this) return 0;
01082             static Tester t;
01083             return &t;
01084         }
01085 
01086     private:
01087         
01088         struct Insipid
01089         {
01090             Insipid(PointerType) {}
01091         };
01092         
01093         typedef typename Select<CP::allow, PointerType, Insipid>::Result
01094             AutomaticConversionResult;
01095     
01096     public:        
01097         operator AutomaticConversionResult() const
01098         { return GetImpl(*this); }
01099     };
01100 
01101 
01102 
01103 
01104 
01105     template 
01106     <
01107       typename Sub,
01108       typename Super,
01109       template <class> class OwnershipPolicy,
01110       class ConversionPolicy,
01111       template <class> class CheckingPolicy,
01112       template <class> class StoragePolicy
01113     >
01114     inline base::ref<Sub, OwnershipPolicy, ConversionPolicy, CheckingPolicy, StoragePolicy>
01115     static_cast_ref(const base::ref<Super, OwnershipPolicy, ConversionPolicy, CheckingPolicy, StoragePolicy>& r)
01116     {
01117       base::ref <Sub, OwnershipPolicy, ConversionPolicy, CheckingPolicy, StoragePolicy> subref;
01118       typedef StoragePolicy<Sub> DSP;
01119       typedef OwnershipPolicy<typename StoragePolicy<Sub>::PointerType> OP;
01120       typename DSP::PointerType subp = static_cast<typename DSP::PointerType>(GetImpl(r));
01121       GetImplRef(subref) = (subp!=0)?subref.OP::Clone(subp):0;
01122       return subref;
01123     }
01124 
01125     template 
01126     <
01127       typename Sub,
01128       typename Super,
01129       template <class> class OwnershipPolicy,
01130       class ConversionPolicy,
01131       template <class> class CheckingPolicy,
01132       template <class> class StoragePolicy
01133     >
01134     inline base::ref<Sub, OwnershipPolicy, ConversionPolicy, CheckingPolicy, StoragePolicy>
01135     dynamic_cast_ref(const base::ref<Super, OwnershipPolicy, ConversionPolicy, CheckingPolicy, StoragePolicy>& r)
01136     {
01137       base::ref <Sub, OwnershipPolicy, ConversionPolicy, CheckingPolicy, StoragePolicy> subref;
01138       typedef StoragePolicy<Sub> DSP;
01139       typedef OwnershipPolicy<typename StoragePolicy<Sub>::PointerType> OP;
01140       typename DSP::PointerType subp = dynamic_cast<typename DSP::PointerType>(GetImpl(r));
01141       GetImplRef(subref) = (subp!=0)?subref.OP::Clone(subp):0;
01142       return subref;
01143     }
01144 
01145 
01146     template 
01147     <
01148       typename Sub,
01149       typename Super,
01150       template <class> class OwnershipPolicy,
01151       class ConversionPolicy,
01152       template <class> class CheckingPolicy,
01153       template <class> class StoragePolicy
01154     >
01155     inline base::ref<Sub, OwnershipPolicy, ConversionPolicy, CheckingPolicy, StoragePolicy>
01156     
01157     
01158     narrow_cast_ref(base::ref<Super, OwnershipPolicy, ConversionPolicy, CheckingPolicy, StoragePolicy> r)
01159     {
01160       return static_cast_ref<Sub,Super,OwnershipPolicy,ConversionPolicy,CheckingPolicy,StoragePolicy>(r);
01161     }
01162 
01163 #define narrow_ref narrow_cast_ref
01164 
01165 
01166 
01167 
01168 
01169 
01170 
01171 
01172 
01173 
01174     template
01175     <
01176         typename T,
01177         template <class> class OP,
01178         class CP,
01179         template <class> class KP,
01180         template <class> class SP,
01181         typename U
01182     >
01183     inline bool operator==(const ref<T, OP, CP, KP, SP>& lhs,
01184         const U* rhs)
01185     { return GetImpl(lhs) == rhs; }
01186     
01187 
01188 
01189 
01190 
01191     template
01192     <
01193         typename T,
01194         template <class> class OP,
01195         class CP,
01196         template <class> class KP,
01197         template <class> class SP,
01198         typename U
01199     >
01200     inline bool operator==(const U* lhs,
01201         const ref<T, OP, CP, KP, SP>& rhs)
01202     { return rhs == lhs; }
01203 
01204 
01205 
01206 
01207 
01208     template
01209     <
01210         typename T,
01211         template <class> class OP,
01212         class CP,
01213         template <class> class KP,
01214         template <class> class SP,
01215         typename U
01216     >
01217     inline bool operator!=(const ref<T, OP, CP, KP, SP>& lhs,
01218         const U* rhs)
01219     { return !(lhs == rhs); }
01220     
01221 
01222 
01223 
01224 
01225     template
01226     <
01227         typename T,
01228         template <class> class OP,
01229         class CP,
01230         template <class> class KP,
01231         template <class> class SP,
01232         typename U
01233     >
01234     inline bool operator!=(const U* lhs,
01235         const ref<T, OP, CP, KP, SP>& rhs)
01236     { return rhs != lhs; }
01237 
01238 
01239 
01240 
01241 
01242     template
01243     <
01244         typename T,
01245         template <class> class OP,
01246         class CP,
01247         template <class> class KP,
01248         template <class> class SP,
01249         typename U
01250     >
01251     inline bool operator<(const ref<T, OP, CP, KP, SP>& lhs,
01252         const U* rhs);
01253         
01254 
01255 
01256 
01257 
01258     template
01259     <
01260         typename T,
01261         template <class> class OP,
01262         class CP,
01263         template <class> class KP,
01264         template <class> class SP,
01265         typename U
01266     >
01267     inline bool operator<(const U* lhs,
01268         const ref<T, OP, CP, KP, SP>& rhs);
01269         
01270 
01271 
01272 
01273 
01274     template
01275     <
01276         typename T,
01277         template <class> class OP,
01278         class CP,
01279         template <class> class KP,
01280         template <class> class SP,
01281         typename U
01282     >
01283     inline bool operator>(const ref<T, OP, CP, KP, SP>& lhs,
01284         const U* rhs)
01285     { return rhs < lhs; }
01286         
01287 
01288 
01289 
01290 
01291     template
01292     <
01293         typename T,
01294         template <class> class OP,
01295         class CP,
01296         template <class> class KP,
01297         template <class> class SP,
01298         typename U
01299     >
01300     inline bool operator>(const U* lhs,
01301         const ref<T, OP, CP, KP, SP>& rhs)
01302     { return rhs < lhs; }
01303   
01304 
01305 
01306 
01307 
01308     template
01309     <
01310         typename T,
01311         template <class> class OP,
01312         class CP,
01313         template <class> class KP,
01314         template <class> class SP,
01315         typename U
01316     >
01317     inline bool operator<=(const ref<T, OP, CP, KP, SP>& lhs,
01318         const U* rhs)
01319     { return !(rhs < lhs); }
01320         
01321 
01322 
01323 
01324 
01325     template
01326     <
01327         typename T,
01328         template <class> class OP,
01329         class CP,
01330         template <class> class KP,
01331         template <class> class SP,
01332         typename U
01333     >
01334     inline bool operator<=(const U* lhs,
01335         const ref<T, OP, CP, KP, SP>& rhs)
01336     { return !(rhs < lhs); }
01337 
01338 
01339 
01340 
01341 
01342     template
01343     <
01344         typename T,
01345         template <class> class OP,
01346         class CP,
01347         template <class> class KP,
01348         template <class> class SP,
01349         typename U
01350     >
01351     inline bool operator>=(const ref<T, OP, CP, KP, SP>& lhs,
01352         const U* rhs)
01353     { return !(lhs < rhs); }
01354         
01355 
01356 
01357 
01358 
01359     template
01360     <
01361         typename T,
01362         template <class> class OP,
01363         class CP,
01364         template <class> class KP,
01365         template <class> class SP,
01366         typename U
01367     >
01368     inline bool operator>=(const U* lhs,
01369         const ref<T, OP, CP, KP, SP>& rhs)
01370     { return !(lhs < rhs); }
01371 
01372 } 
01373 
01374 
01375 
01376 
01377 
01378 namespace std
01379 {
01380     template
01381     <
01382         typename T,
01383         template <class> class OP,
01384         class CP,
01385         template <class> class KP,
01386         template <class> class SP
01387     >
01388     struct less< base::ref<T, OP, CP, KP, SP> >
01389         : public binary_function<base::ref<T, OP, CP, KP, SP>,
01390             base::ref<T, OP, CP, KP, SP>, bool>
01391     {
01392         bool operator()(const base::ref<T, OP, CP, KP, SP>& lhs,
01393             const base::ref<T, OP, CP, KP, SP>& rhs) const
01394         { return less<T*>()(GetImpl(lhs), GetImpl(rhs)); }
01395     };
01396 }
01397 
01398 
01399 
01400 
01401 
01402 
01403 #endif // SMARTPTR_INC_