smartpointer.h

00001 // author: Jean Gressmann
00002 // web: www.0x42.de
00003 // Ergänzungen von Benjamin Kaufmann:
00004 // * Test auf void und auf incomplete type
00005 // * this->-Qualifikation von dependent-names in SmartPointer
00006 
00007 #ifndef SMARTPOINTER_H
00008 #define SMARTPOINTER_H
00009 
00010 #if defined(_MSC_VER)
00011 #       define for if(0);else for
00012 #       pragma warning(disable:4786)
00013 #       pragma warning(disable:4521)
00014 #       pragma warning(disable:4522)
00015 #       pragma warning(disable:4355)
00016 #       pragma warning(disable:4291)
00017 #endif
00018 
00019 #include <algorithm>
00020 #include <cassert>
00021 #include <stdexcept>
00022 #include <cassert>
00023 
00024 template <bool> struct StaticAssert;
00025 template <> struct StaticAssert<true> {};
00026 template <class T> struct is_void {enum {result = 0};};
00027 template <> struct is_void<void> {enum {result = 1};};
00028 
00029 
00030 // These freeResource() functions are required to handle their
00031 // specific Null indifferently, say delete 0 is
00032 // to do nothing.
00033 template<class T>
00034 struct PointerTraits_
00035 {
00036         StaticAssert<!is_void<T>::result> Error_Smart_Pointer_Does_Not_Support_Void_Ptr;
00037         typedef T ValueType;
00038         typedef T& ReferenceType;
00039         typedef const T& ConstReferenceType;
00040         typedef T* PointerType;
00041         typedef const T* ConstPointerType;
00042         static const PointerType Null;
00043 
00044         static void freeResource(PointerType p)
00045         {
00046                 enum { no_incomplete_types_please = sizeof(*p) };
00047                 delete p;
00048         }
00049 };
00050 
00051 template<class T>
00052 const typename PointerTraits_<T>::PointerType PointerTraits_<T>::Null = 0;
00053 
00054 
00055 template<class T>
00056 struct ArrayPointerTraits_
00057 {
00058         typedef T ValueType;
00059         typedef T& ReferenceType;
00060         typedef const T& ConstReferenceType;
00061         typedef T* PointerType;
00062         typedef const T* ConstPointerType;
00063         static const PointerType Null;
00064 
00065         static void freeResource(PointerType p)
00066         {
00067                 delete [] p;
00068         }
00069 };
00070 
00071 template<class T>
00072 const typename ArrayPointerTraits_<T>::PointerType ArrayPointerTraits_<T>::Null = 0;
00073 
00074 template<class Traits>
00075 class SingleOwner_
00076 {
00077 public:
00078         typedef typename Traits::PointerType PT;
00079         typedef typename Traits::ConstPointerType CPT;
00080         static CPT null() { return Traits::Null; }
00081 private:
00082         PT managed_;
00083 
00084         SingleOwner_(const SingleOwner_&);
00085         SingleOwner_& operator=(const SingleOwner_&);
00086 public:
00087         ~SingleOwner_()
00088         {
00089                 Traits::freeResource(managed_);
00090         }
00091         explicit
00092         SingleOwner_()
00093                 :       managed_(Traits::Null)
00094         {}
00095         explicit
00096         SingleOwner_(PT p)
00097                 :       managed_(p)
00098         {}
00099 
00100         SingleOwner_(SingleOwner_& o)
00101                 :       managed_(Traits::Null)
00102         {
00103                 swap(o);
00104         }
00105 
00106         SingleOwner_& operator=(SingleOwner_& o)
00107         {
00108                 swap(o);
00109                 return *this;
00110         }
00111         SingleOwner_& operator=(PT p)
00112         {
00113                 SingleOwner_().swap(*this);
00114                 managed_ = p;
00115                 return *this;
00116         }
00117         bool unique() const { return true; }
00118         size_t count() const { return 1; }
00119         PT get() { return managed_; }
00120         CPT get() const { return managed_; }
00121         void swap(SingleOwner_& o) // nothrow guarantee
00122         {
00123                 std::swap(managed_, o.managed_);
00124         }
00125         void reset()
00126         {
00127                 SingleOwner_().swap(*this);
00128         }
00129         void release()
00130         {
00131                 managed_ = Traits::Null;
00132         }
00133 };
00134 
00135 template<class Traits>
00136 class ReferenceCountedOwner_
00137 {
00138 public:
00139         typedef typename Traits::PointerType PT;
00140         typedef typename Traits::ConstPointerType CPT;
00141         static CPT null() { return Traits::Null; }
00142 private:
00143         class RefCount_
00144         {
00145                 PT managed_;
00146                 size_t count_;
00147                 RefCount_();
00148                 RefCount_(const RefCount_&);
00149                 RefCount_& operator=(const RefCount_&);
00150         public:
00151                 explicit
00152                 RefCount_(PT p)
00153                         :       managed_(p)
00154                         ,       count_(1)
00155                 {}
00156                 void inc()
00157                 {
00158                         ++count_;
00159                 }
00160                 size_t count() const { return count_; }
00161                 bool unique() const { return count_ == 1; }
00162                 void dec()
00163                 {
00164                         --count_;
00165                         if(!count_)
00166                         {
00167                                 PT deleteme = managed_;
00168                                 delete this;
00169                                 Traits::freeResource(deleteme);
00170                         }
00171 
00172                 }
00173                 void weakDec()
00174                 {
00175                         --count_;
00176                         if(!count_)
00177                         {
00178                                 delete this;
00179                         }
00180                 }
00181                 PT get() { return managed_;     }
00182                 CPT get() const { return managed_; }
00183         };
00184         RefCount_* refCount_;
00185 
00186         void decIfValidRefCount()
00187         {
00188                 if(refCount_)
00189                 {
00190                         RefCount_* temp = 0;
00191                         std::swap(temp, refCount_);
00192                         temp->dec();
00193                 }
00194 
00195         }
00196         void incIfValidRefCount()  // nothrow guarantee
00197         {
00198                 if(refCount_)
00199                         refCount_->inc();
00200         }
00201         static RefCount_* createRefCount(PT p)
00202         {
00203                 return p == Traits::Null ? 0 : new RefCount_(p);
00204         }
00205 public:
00206         ~ReferenceCountedOwner_()
00207         {
00208                 decIfValidRefCount();
00209         }
00210         explicit
00211         ReferenceCountedOwner_()
00212                 :       refCount_(0)
00213         {}
00214         ReferenceCountedOwner_(PT p)
00215                 :       refCount_(createRefCount(p))
00216         {}
00217         ReferenceCountedOwner_(const ReferenceCountedOwner_& o)
00218                 :       refCount_(o.refCount_)
00219         {
00220                 incIfValidRefCount();
00221         }
00222         ReferenceCountedOwner_& operator=(const ReferenceCountedOwner_& o)
00223         {
00224                 ReferenceCountedOwner_().swap(*this);
00225 
00226                 refCount_ = o.refCount_;
00227                 incIfValidRefCount();
00228 
00229                 return *this;
00230         }
00231         ReferenceCountedOwner_& operator=(PT p)
00232         {
00233                 ReferenceCountedOwner_().swap(*this);
00234                 refCount_ = createRefCount(p);
00235 
00236                 return *this;
00237         }
00238         bool unique() const { return refCount_ ? refCount_->unique() : true; }  // nothrow guarantee
00239         size_t count() const { return refCount_ ? refCount_->count() : 1; }  // nothrow guarantee
00240         PT get() { return refCount_ ? refCount_->get() : Traits::Null; }
00241         CPT get() const { return refCount_ ? refCount_->get() : Traits::Null; }
00242         void swap(ReferenceCountedOwner_& o)  // nothrow guarantee
00243         {
00244                 std::swap(refCount_, o.refCount_);
00245         }
00246         void reset()
00247         {
00248                 ReferenceCountedOwner_().swap(*this);
00249         }
00250         void release()
00251         {
00252                 if(refCount_)
00253                         refCount_->weakDec();
00254                 refCount_ = 0;
00255         }
00256 };
00257 
00258 template
00259 <
00260         class T,
00261         class Traits = PointerTraits_<T>,
00262         class RefCountPolicy = SingleOwner_<Traits>
00263 >
00264 class SmartPointer : public RefCountPolicy
00265 {
00266 public:
00267         typedef typename Traits::ValueType VT;
00268         typedef typename Traits::PointerType PT;
00269         typedef typename Traits::ConstPointerType CPT;
00270         typedef typename Traits::ReferenceType RT;
00271         typedef typename Traits::ConstReferenceType CRT;
00272 
00273         explicit
00274         SmartPointer()
00275         {}
00276         explicit
00277         SmartPointer(PT p)
00278                 :       RefCountPolicy(p)
00279         {}
00280 
00281         SmartPointer(const SmartPointer& o)
00282                 :       RefCountPolicy(o)
00283         {}
00284         SmartPointer(SmartPointer& o)
00285                 :       RefCountPolicy(o)
00286         {}
00287         SmartPointer& operator=(SmartPointer& o)
00288         {
00289                 RefCountPolicy::operator=(o);
00290                 return *this;
00291         }
00292         SmartPointer& operator=(const SmartPointer& o)
00293         {
00294                 RefCountPolicy::operator=(o);
00295                 return *this;
00296         }
00297         SmartPointer& operator=(PT p)
00298         {
00299                 RefCountPolicy::operator=(p);
00300                 return *this;
00301         }
00302         bool operator==(const SmartPointer& o) const
00303         {
00304                 return this->get() == o.get();
00305         }
00306         bool operator!=(const SmartPointer& o) const
00307         {
00308                 return this->get() != o.get();
00309         }
00310 
00311         operator bool() const { return this->get() != Traits::Null; }
00312         PT operator->() { return this->get(); }
00313         CPT operator->() const { return this->get(); }
00314         RT operator*() { return *this->get(); }
00315         CRT operator*() const { return *this->get(); }
00316 };
00317 
00318 template<class T, class Traits = PointerTraits_<T> >
00319 class SharedPtr : public SmartPointer<T, Traits, ReferenceCountedOwner_<Traits> >
00320 {
00321         typedef SmartPointer<T, Traits, ReferenceCountedOwner_<Traits> > Base;
00322 public:
00323         typedef typename Base::PT PT;
00324         typedef typename Base::VT VT;
00325         explicit
00326         SharedPtr()
00327                 :       Base()
00328         {}
00329 
00330         SharedPtr(PT p)
00331                 :       Base(p)
00332         {}
00333         SharedPtr(const SharedPtr& o)
00334                 :       Base(o)
00335         {}
00336         SharedPtr& operator=(PT p) {
00337                 Base::operator=(p);
00338                 return *this;
00339         }
00340 };
00341 
00342 
00343 #endif

Generated on Fri Apr 27 13:12:36 2007 for Highlight Code Converter by  doxygen 1.5.2