_smart_ptr.h

Go to the documentation of this file.
00001 /* ========================================================================
00002 ** Extended Template and Library
00003 ** Template Smart Pointer Implementation
00004 ** $Id: _smart_ptr.h 334 2007-03-16 00:37:48Z dooglus $
00005 **
00006 ** Copyright (c) 2002 Robert B. Quattlebaum Jr.
00007 **
00008 ** This package is free software; you can redistribute it and/or
00009 ** modify it under the terms of the GNU General Public License as
00010 ** published by the Free Software Foundation; either version 2 of
00011 ** the License, or (at your option) any later version.
00012 **
00013 ** This package is distributed in the hope that it will be useful,
00014 ** but WITHOUT ANY WARRANTY; without even the implied warranty of
00015 ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00016 ** General Public License for more details.
00017 **
00018 ** === N O T E S ===========================================================
00019 **
00020 ** This is an internal header file, included by other ETL headers.
00021 ** You should not attempt to use it directly.
00022 **
00023 ** ========================================================================= */
00024 
00025 /* === S T A R T =========================================================== */
00026 
00027 #ifndef __ETL__SMART_PTR_H
00028 #define __ETL__SMART_PTR_H
00029 
00030 /* === H E A D E R S ======================================================= */
00031 
00032 #include <cassert>
00033 #include "_ref_count.h"
00034 
00035 /* === M A C R O S ========================================================= */
00036 
00037 /* === T Y P E D E F S ===================================================== */
00038 
00039 /* === C L A S S E S & S T R U C T S ======================================= */
00040 
00041 _ETL_BEGIN_NAMESPACE
00042 
00043 template <class T>
00044 struct generic_deleter
00045 {
00046     void operator()(T* x)const { delete x; }
00047 };
00048 
00049 template <class T>
00050 struct array_deleter
00051 {
00052     void operator()(T* x)const { delete [] x; }
00053 };
00054 
00055 // ========================================================================
00061 template <class T, class D=generic_deleter<T> >
00062 class smart_ptr
00063 {
00064 public:
00065 
00066     typedef T value_type;
00067     typedef T& reference;
00068     typedef const T& const_reference;
00069     typedef T* pointer;
00070     typedef const T* const_pointer;
00071     typedef int count_type;
00072     typedef int size_type;
00073     typedef D destructor_type;
00074 
00075 #ifdef DOXYGEN_SHOULD_SKIP_THIS     // #ifdef is not a typo
00076 private:
00077 #endif
00078     value_type *obj;        
00079     reference_counter refcount;
00080 
00081 public:
00082     // Private constructor for convenience
00083     smart_ptr(value_type* obj,reference_counter refcount):obj(obj),refcount(refcount) {  }
00084 
00086     smart_ptr():obj(0),refcount(false) {}
00087 
00089 
00094     explicit smart_ptr(value_type* x):obj(x),refcount(x?true:false) {  }
00095 
00097 
00099 #ifdef _WIN32
00100     template <class U>
00101     smart_ptr(const smart_ptr<U> &x):obj((pointer)&*x.obj),refcount(x.refcount())
00102         { }
00103 #endif
00104 
00106 
00110     smart_ptr(const smart_ptr<value_type> &x):obj(x.obj),refcount(x.refcount) {  }
00111 
00112     explicit smart_ptr(const value_type &x):obj(new value_type(x)) { }
00113 
00115     ~smart_ptr() { if(refcount.unique()) destructor_type()(obj); }
00116 
00118     template <class U> const smart_ptr<value_type> &
00119     operator=(const smart_ptr<U> &x)
00120     {
00121         if(x.get()==obj)
00122             return *this;
00123 
00124         reset();
00125 
00126         if(x.obj)
00127         {
00128             obj=(pointer)x.get();
00129             refcount=x.refcount;
00130         }
00131 
00132         return *this;
00133     }
00134 
00136     const smart_ptr<value_type> &
00137     operator=(const smart_ptr<value_type> &x)
00138     {
00139         if(x.get()==obj)
00140             return *this;
00141 
00142         reset();
00143 
00144         if(x.obj)
00145         {
00146 
00147             obj=(pointer)x.get();
00148             refcount=x.refcount;
00149         }
00150 
00151         return *this;
00152     }
00153 
00155     void
00156     reset()
00157     {
00158         if(obj)
00159         {
00160             if(refcount.unique()) destructor_type()(obj);
00161             refcount.detach();
00162             obj=0;
00163         }
00164     }
00165 
00166     void spawn() { operator=(smart_ptr(new T)); }
00167 
00169     const count_type& count()const { return refcount; }
00170 
00172     bool unique()const { return refcount.unique(); }
00173 
00175     smart_ptr<const value_type> constant() { return *this; }
00176 
00177     reference operator*()const { assert(obj); return *obj; }
00178 
00179     pointer operator->()const { assert(obj); return obj; }
00180 
00181 
00182     operator smart_ptr<const value_type>()const
00183     { return smart_ptr<const value_type>(static_cast<const_pointer>(obj)); }
00184 
00186     template <class U> static
00187     smart_ptr<T> cast_static(const smart_ptr<U> &x)
00188     { if(!x)return NULL; return smart_ptr<T>(static_cast<T*>(x.get()),x.refcount); }
00189 
00191     template <class U> static
00192     smart_ptr<T> cast_dynamic(const smart_ptr<U> &x)
00193     { if(!x)return 0; return smart_ptr<T>(dynamic_cast<T*>(x.get()),x.refcount); }
00194 
00196     template <class U> static
00197     smart_ptr<T> cast_const(const smart_ptr<U> &x)
00198     { if(!x)return 0; return smart_ptr<T>(const_cast<T*>(x.get()),x.refcount); }
00199 
00200     pointer get()const { return obj; }
00201 
00203     operator bool()const { return obj!=0; }
00204 
00205     bool operator!()const { return !obj; }
00206 
00208     template <class U>
00209     operator smart_ptr<U>()
00210     {
00211         // This next line should provide a syntax check
00212         // to make sure that this cast makes sense.
00213         // If it doesn't, this should have a compiler error.
00214         // Otherwise, it should get optimized right out
00215         // of the code.
00216         //(U*)obj;
00217 
00218         return *reinterpret_cast<smart_ptr<U>*>(this);
00219     }
00220 
00221 }; // END of template class smart_ptr
00222 
00223 // ========================================================================
00229 template <class T>
00230 class loose_smart_ptr
00231 {
00232 public:
00233 
00234     typedef T value_type;
00235     typedef T& reference;
00236     typedef const T& const_reference;
00237     typedef T* pointer;
00238     typedef const T* const_pointer;
00239     typedef int count_type;
00240     typedef int size_type;
00241 
00242 private:
00243     value_type *obj;        
00244     weak_reference_counter refcount;    
00245 
00246 public:
00247 
00249     loose_smart_ptr():obj(0),refcount(0) {}
00250 
00252     loose_smart_ptr(const loose_smart_ptr<value_type> &x):obj(x.get()),refcount(x.refcount) { }
00253 
00254     loose_smart_ptr(const smart_ptr<value_type> &x):obj(x.get()),refcount(x.refcount) { }
00255 
00256     void reset() { obj=0,refcount=0; }
00257 
00258     operator smart_ptr<value_type>()
00259     {
00260         return smart_ptr<value_type>(static_cast<pointer>(obj),refcount);
00261     }
00262 
00263     operator smart_ptr<const value_type>()
00264     {
00265         return smart_ptr<const value_type>(static_cast<const_pointer>(obj),refcount);
00266     }
00267 
00269     const count_type& count()const { return refcount; }
00270 
00271     bool unique()const { return refcount.unique(); }
00272 
00273     reference operator*()const { assert(obj); return *obj; }
00274 
00275     pointer operator->()const { assert(obj); return obj; }
00276 
00277     pointer get()const { return obj; }
00278 
00279     bool operator!()const { return !obj; }
00280 };
00281 
00282 template <class T,class U> bool
00283 operator==(const smart_ptr<T> &lhs,const smart_ptr<U> &rhs)
00284     { return (lhs.get()==rhs.get()); }
00285 template <class T,class U> bool
00286 operator==(const loose_smart_ptr<T> &lhs,const loose_smart_ptr<U> &rhs)
00287     { return (lhs.get()==rhs.get()); }
00288 template <class T,class U> bool
00289 operator==(const smart_ptr<T> &lhs,const loose_smart_ptr<U> &rhs)
00290     { return (lhs.get()==rhs.get()); }
00291 template <class T,class U> bool
00292 operator==(const loose_smart_ptr<T> &lhs,const smart_ptr<U> &rhs)
00293     { return (lhs.get()==rhs.get()); }
00294 template <class T> bool
00295 operator==(const smart_ptr<T> &lhs,const T *rhs)
00296     { return (lhs.get()==rhs); }
00297 template <class T> bool
00298 operator==(const loose_smart_ptr<T> &lhs,const T *rhs)
00299     { return (lhs.get()==rhs); }
00300 template <class T> bool
00301 operator==(const T *lhs,const smart_ptr<T> &rhs)
00302     { return (lhs==rhs.get()); }
00303 template <class T> bool
00304 operator==(const T *lhs,const loose_smart_ptr<T> &rhs)
00305     { return (lhs==rhs.get()); }
00306 
00307 
00308 template <class T,class U> bool
00309 operator!=(const smart_ptr<T> &lhs,const smart_ptr<U> &rhs)
00310     { return (lhs.get()!=rhs.get()); }
00311 template <class T,class U> bool
00312 operator!=(const loose_smart_ptr<T> &lhs,const loose_smart_ptr<U> &rhs)
00313     { return (lhs.get()!=rhs.get()); }
00314 template <class T,class U> bool
00315 operator!=(const smart_ptr<T> &lhs,const loose_smart_ptr<U> &rhs)
00316     { return (lhs.get()!=rhs.get()); }
00317 template <class T,class U> bool
00318 operator!=(const loose_smart_ptr<T> &lhs,const smart_ptr<U> &rhs)
00319     { return (lhs.get()!=rhs.get()); }
00320 template <class T> bool
00321 operator!=(const smart_ptr<T> &lhs,const T *rhs)
00322     { return (lhs.get()!=rhs); }
00323 template <class T> bool
00324 operator!=(const loose_smart_ptr<T> &lhs,const T *rhs)
00325     { return (lhs.get()!=rhs); }
00326 template <class T> bool
00327 operator!=(const T *lhs,const smart_ptr<T> &rhs)
00328     { return (lhs!=rhs.get()); }
00329 template <class T> bool
00330 operator!=(const T *lhs,const loose_smart_ptr<T> &rhs)
00331     { return (lhs!=rhs.get()); }
00332 
00333 
00334 template <class T,class U> bool
00335 operator<(const smart_ptr<T> &lhs,const smart_ptr<U> &rhs)
00336     { return (lhs.get()<rhs.get()); }
00337 template <class T,class U> bool
00338 operator<(const loose_smart_ptr<T> &lhs,const loose_smart_ptr<U> &rhs)
00339     { return (lhs.get()<rhs.get()); }
00340 template <class T,class U> bool
00341 operator<(const smart_ptr<T> &lhs,const loose_smart_ptr<U> &rhs)
00342     { return (lhs.get()<rhs.get()); }
00343 template <class T,class U> bool
00344 operator<(const loose_smart_ptr<T> &lhs,const smart_ptr<U> &rhs)
00345     { return (lhs.get()<rhs.get()); }
00346 template <class T> bool
00347 operator<(const smart_ptr<T> &lhs,const T *rhs)
00348     { return (lhs.get()<rhs); }
00349 template <class T> bool
00350 operator<(const loose_smart_ptr<T> &lhs,const T *rhs)
00351     { return (lhs.get()<rhs); }
00352 template <class T> bool
00353 operator<(const T *lhs,const smart_ptr<T> &rhs)
00354     { return (lhs<rhs.get()); }
00355 template <class T> bool
00356 operator<(const T *lhs,const loose_smart_ptr<T> &rhs)
00357     { return (lhs<rhs.get()); }
00358 
00359 _ETL_END_NAMESPACE
00360 
00361 /* === E N D =============================================================== */
00362 
00363 #endif

Generated on Sun Oct 28 01:59:33 2007 for ETL by  doxygen 1.5.3-20071008