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 #ifndef __ETL__SMART_PTR_H
00028 #define __ETL__SMART_PTR_H
00029
00030
00031
00032 #include <cassert>
00033 #include "_ref_count.h"
00034
00035
00036
00037
00038
00039
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
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
00212
00213
00214
00215
00216
00217
00218 return *reinterpret_cast<smart_ptr<U>*>(this);
00219 }
00220
00221 };
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
00362
00363 #endif