- Main Page
- Related Pages
- Classes
- Files

# _smart_ptr.h

Go to the documentation of this file.

    00001 /* ========================================================================
    00002 ** Extended Template and Library
    00003 ** Template Smart Pointer Implementation
    00004 ** $Id$
    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