Main Page | Namespace List | Class Hierarchy | Alphabetical List | Class List | File List | Namespace Members | Class Members | File Members | Related Pages

base/ref.full

Go to the documentation of this file.
00001 /****************************************************************************
00002   Copyright (C)2001 by Andrei Alexandrescu
00003 
00004   This file is a derivative of a file from the Loki Library written by
00005   Andrei Alexandrescu.  It was distributed by him under the terms
00006   listed below (titled Loki Original Distribution Terms).
00007   In accordance with the terms, this distribution contains the copyright
00008   notice here and the copyright notice and permission notice
00009   in supporting documentation.  The terms do *not* require
00010   redistribution under those same terms.  This code is distributed
00011   to you under the terms of the GNU General Public License (GPL) 
00012   below.  The GPL does not require you to maintain the terms of
00013   the Loki Original Distribution Terms, but you are encouraged to do so.
00014 
00015   This program/file is free software; you can redistribute it and/or modify
00016   it under the terms of the GNU General Public License as published by
00017   the Free Software Foundation; either version 2 of the License, or
00018   (at your option) any later version.
00019   
00020   This program is distributed in the hope that it will be useful,
00021   but WITHOUT ANY WARRANTY; without even the implied warranty of
00022   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00023   GNU General Public License for more details. (http://www.gnu.org)
00024   
00025   You should have received a copy of the GNU General Public License
00026   along with this program; if not, write to the Free Software
00027   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00028   
00029  ****************************************************************************
00030   Loki Original Distribution Terms:
00031 
00032   The Loki Library
00033   Copyright (c) 2001 by Andrei Alexandrescu
00034   This code accompanies the book:
00035   Alexandrescu, Andrei. "Modern C++ Design: Generic Programming and Design 
00036       Patterns Applied". Copyright (c) 2001. Addison-Wesley.
00037   Permission to use, copy, modify, distribute and sell this software for any 
00038       purpose is hereby granted without fee, provided that the above copyright 
00039       notice appear in all copies and that both that copyright notice and this 
00040       permission notice appear in supporting documentation.
00041   The author or Addison-Welsey Longman make no representations about the 
00042       suitability of this software for any purpose. It is provided "as is" 
00043       without express or implied warranty.
00044  ****************************************************************************
00045 
00046   $Id: ref.full 1029 2004-02-11 20:45:54Z jungd $
00047   $Revision: 1.1 $
00048   $Date: 2004-02-11 15:45:54 -0500 (Wed, 11 Feb 2004) $
00049   $Author: jungd $
00050  
00051 ****************************************************************************/
00052 
00053 // Last update: June 20, 2001
00054 
00055 #ifndef SMARTPTR_INC_
00056 #define SMARTPTR_INC_
00057 
00058 ////////////////////////////////////////////////////////////////////////////////
00059 // IMPORTANT NOTE
00060 // Due to threading issues, the OwnershipPolicy has been changed as follows:
00061 //     Release() returns a boolean saying if that was the last release
00062 //        so the pointer can be deleted by the StoragePolicy
00063 //     IsUnique() was removed
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 // class template DefaultSPStorage
00079 // Implementation of the StoragePolicy used by ref
00080 ////////////////////////////////////////////////////////////////////////////////
00081 
00082     template <class T>
00083     class DefaultSPStorage
00084     {
00085     public:
00086         typedef T* StoredType;    // the type of the pointee_ object
00087         typedef T* PointerType;   // type returned by operator->
00088         typedef T& ReferenceType; // type returned by operator*
00089         
00090         DefaultSPStorage() : pointee_(Default()) 
00091         {}
00092 
00093         // The storage policy doesn't initialize the stored pointer 
00094         //     which will be initialized by the OwnershipPolicy's Clone fn
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         // Accessors
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         // Default value to initialize the pointer
00122         static StoredType Default()
00123         { return 0; }
00124 
00125     protected:
00126         // Destroys the data stored
00127         // (Destruction might be taken over by the OwnershipPolicy)
00128         void Destroy()
00129         { delete pointee_; }
00130     
00131     private:
00132         // Data
00133         StoredType pointee_;
00134     };
00135 
00136 ////////////////////////////////////////////////////////////////////////////////
00137 // class template RefCounted
00138 // Implementation of the OwnershipPolicy used by ref
00139 // Provides a classic external reference counting implementation
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         // MWCW lacks template friends, hence the following kludge
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         // Data
00190         unsigned int* pCount_;
00191     };
00192     
00193 ////////////////////////////////////////////////////////////////////////////////
00194 // class template RefCountedMT
00195 // Implementation of the OwnershipPolicy used by ref
00196 // Implements external reference counting for multithreaded programs
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         // MWCW lacks template friends, hence the following kludge
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         // Data
00249         volatile unsigned int* pCount_;
00250     };
00251 
00252 ////////////////////////////////////////////////////////////////////////////////
00253 // class template COMRefCounted
00254 // Implementation of the OwnershipPolicy used by ref
00255 // Adapts COM intrusive reference counting to OwnershipPolicy-specific syntax
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 // class template IntrRefCounted
00289 // Implementation of the OwnershipPolicy used by ref
00290 // Intrusive reference counting through class Referenced
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 // class template NonSmartShared
00332 // Implementation of the OwnershipPolicy used by ref
00333 // Behaves like a regular 'non-smart' builtin pointer
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 // class template DeepCopy
00368 // Implementation of the OwnershipPolicy used by ref
00369 // Implements deep copy semantics, assumes existence of a Clone() member 
00370 //     function of the pointee type
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 // class template RefLinked
00400 // Implementation of the OwnershipPolicy used by ref
00401 // Implements reference linking
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                         // both lists are empty, nothing 2 do
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 // class template DestructiveCopy
00492 // Implementation of the OwnershipPolicy used by ref
00493 // Implements destructive copy semantics (a la std::auto_ptr)
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 // class template NoCopy
00529 // Implementation of the OwnershipPolicy used by ref
00530 // Implements a policy that doesn't allow copying objects
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 // class template AllowConversion
00563 // Implementation of the ConversionPolicy used by ref
00564 // Allows implicit conversion from ref to the pointee type
00565 ////////////////////////////////////////////////////////////////////////////////
00566 
00567     struct AllowConversion
00568     {
00569         enum { allow = true };
00570 
00571         void Swap(AllowConversion&)
00572         {}
00573     };
00574 
00575 ////////////////////////////////////////////////////////////////////////////////
00576 // class template DisallowConversion
00577 // Implementation of the ConversionPolicy used by ref
00578 // Does not allow implicit conversion from ref to the pointee type
00579 // You can initialize a DisallowConversion with an AllowConversion
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 // class template NoCheck
00598 // Implementation of the CheckingPolicy used by ref
00599 // Well, it's clear what it does :o)
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 // class template AssertCheck
00628 // Implementation of the CheckingPolicy used by ref
00629 // Checks the pointer before dereference
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 // class template AssertCheckStrict
00661 // Implementation of the CheckingPolicy used by ref
00662 // Checks the pointer against zero upon initialization and before dereference
00663 // You can initialize an AssertCheckStrict with an AssertCheck 
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 // class NullPointerException
00699 // Used by some implementations of the CheckingPolicy used by ref
00700 ////////////////////////////////////////////////////////////////////////////////
00701 
00702     struct NullPointerException : public std::runtime_error
00703     {
00704         NullPointerException() : std::runtime_error("")
00705         { }
00706         const char* what() const throw()  // added throw() DJ
00707         { return "Null Pointer Exception"; }
00708     };
00709         
00710 ////////////////////////////////////////////////////////////////////////////////
00711 // class template RejectNullStatic
00712 // Implementation of the CheckingPolicy used by ref
00713 // Checks the pointer upon initialization and before dereference
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 // class template RejectNull
00756 // Implementation of the CheckingPolicy used by ref
00757 // Checks the pointer before dereference
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 // class template RejectNullStrict
00785 // Implementation of the CheckingPolicy used by ref
00786 // Checks the pointer upon initialization and before dereference
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 // class template ByRef
00815 // Transports a reference as a value
00816 // Serves to implement the Colvin/Gibbons trick for ref
00817 ////////////////////////////////////////////////////////////////////////////////
00818 
00819     template <class T>
00820     class ByRef
00821     {
00822     public:
00823         ByRef(T& v) : value_(v) {}
00824         operator T&() { return value_; }
00825         // gcc doesn't like this:
00826         // operator const T&() const { return value_; }
00827     private:
00828         T& value_;
00829     };
00830 
00831 ////////////////////////////////////////////////////////////////////////////////
00832 // class template ref (declaration)
00833 // The reason for all the fuss above
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 // class template ref (definition)
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 // Enables "if (!sp) ..."
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         // Ambiguity buster
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         // Ambiguity buster
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         // Ambiguity buster
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         // Helper for enabling 'if (sp)'
01070         struct Tester
01071         {
01072             Tester() {}
01073         private:
01074             void operator delete(void*);
01075         };
01076         
01077     public:
01078         // enable 'if (sp)'
01079         operator Tester*() const
01080         {
01081             if (!*this) return 0;
01082             static Tester t;
01083             return &t;
01084         }
01085 
01086     private:
01087         // Helper for disallowing automatic conversion
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 // casting operations class template ref
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     // crashes gcc3.2
01157     //narrow_cast_ref(base::ref< typename Select< SUPERSUBCLASS_STRICT(Super,Sub),Super,NullType>::Result, OwnershipPolicy, ConversionPolicy, CheckingPolicy, StoragePolicy> r)
01158     narrow_cast_ref(base::ref<Super, OwnershipPolicy, ConversionPolicy, CheckingPolicy, StoragePolicy> r)
01159     {
01160       return dynamic_cast_ref<Sub,Super,OwnershipPolicy,ConversionPolicy,CheckingPolicy,StoragePolicy>(r);
01161     }
01162 
01163 #define narrow_ref narrow_cast_ref
01164 
01165 
01166 ////////////////////////////////////////////////////////////////////////////////
01167 // free comparison operators for class template ref
01168 ////////////////////////////////////////////////////////////////////////////////
01169 
01170 ////////////////////////////////////////////////////////////////////////////////
01171 // operator== for lhs = ref, rhs = raw pointer
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 // operator== for lhs = raw pointer, rhs = ref
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 // operator!= for lhs = ref, rhs = raw pointer
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 // operator!= for lhs = raw pointer, rhs = ref
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 // operator< for lhs = ref, rhs = raw pointer -- NOT DEFINED
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 // operator< for lhs = raw pointer, rhs = ref -- NOT DEFINED
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 // operator> for lhs = ref, rhs = raw pointer -- NOT DEFINED
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 // operator> for lhs = raw pointer, rhs = ref
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 // operator<= for lhs = ref, rhs = raw pointer
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 // operator<= for lhs = raw pointer, rhs = ref
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 // operator>= for lhs = ref, rhs = raw pointer
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 // operator>= for lhs = raw pointer, rhs = ref
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 } // namespace base
01373 
01374 ////////////////////////////////////////////////////////////////////////////////
01375 // specialization of std::less for ref
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 // Change log:
01400 // June 20, 2001: ported by Nick Thurn to gcc 2.95.3. Kudos, Nick!!!
01401 ////////////////////////////////////////////////////////////////////////////////
01402 
01403 #endif // SMARTPTR_INC_

Generated on Thu Jul 29 15:56:12 2004 for OpenSim by doxygen 1.3.6