1 /* ========================================================================
2 ** Extended Template and Library
3 ** Template Smart Pointer Implementation
6 ** Copyright (c) 2002 Robert B. Quattlebaum Jr.
8 ** This package is free software; you can redistribute it and/or
9 ** modify it under the terms of the GNU General Public License as
10 ** published by the Free Software Foundation; either version 2 of
11 ** the License, or (at your option) any later version.
13 ** This package is distributed in the hope that it will be useful,
14 ** but WITHOUT ANY WARRANTY; without even the implied warranty of
15 ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 ** General Public License for more details.
18 ** === N O T E S ===========================================================
20 ** This is an internal header file, included by other ETL headers.
21 ** You should not attempt to use it directly.
23 ** ========================================================================= */
25 /* === S T A R T =========================================================== */
27 #ifndef __ETL__SMART_PTR_H
28 #define __ETL__SMART_PTR_H
30 /* === H E A D E R S ======================================================= */
33 #include "_ref_count.h"
35 /* === M A C R O S ========================================================= */
37 /* === T Y P E D E F S ===================================================== */
39 /* === C L A S S E S & S T R U C T S ======================================= */
44 struct generic_deleter
46 void operator()(T* x)const { delete x; }
52 void operator()(T* x)const { delete [] x; }
55 // ========================================================================
56 /*! \class smart_ptr _smart_ptr.h ETL/smart_ptr
57 ** \brief Object Smart Pointer
58 ** \see loose_smart_ptr
61 template <class T, class D=generic_deleter<T> >
68 typedef const T& const_reference;
70 typedef const T* const_pointer;
71 typedef int count_type;
72 typedef int size_type;
73 typedef D destructor_type;
75 #ifdef DOXYGEN_SHOULD_SKIP_THIS // #ifdef is not a typo
78 value_type *obj; //!< \internal Pointer to object
79 reference_counter refcount;
82 // Private constructor for convenience
83 smart_ptr(value_type* obj,reference_counter refcount):obj(obj),refcount(refcount) { }
85 //! Default constructor - empty smart_ptr
86 smart_ptr():obj(0),refcount(false) {}
88 //! Constructor that constructs from a pointer to new object
89 /*! A new smart_ptr is created with a pointer
90 to a newly allocated object. We need
91 to be explicit with this so we don't
92 accidently have two smart_ptrs for one
93 object -- that would be bad. */
94 explicit smart_ptr(value_type* x):obj(x),refcount(x?true:false) { }
96 //! Template copy constructor
97 /*! This template constructor allows us to cast
98 smart_ptrs much like we would pointers. */
101 smart_ptr(const smart_ptr<U> &x):obj((pointer)&*x.obj),refcount(x.refcount())
105 //! Default copy constructor
106 /*! The template above is not good enough
107 for all compilers. We need to explicitly
108 define the copy constructor for this
109 class to work on those compilers. */
110 smart_ptr(const smart_ptr<value_type> &x):obj(x.obj),refcount(x.refcount) { }
112 explicit smart_ptr(const value_type &x):obj(new value_type(x)) { }
114 //! smart_ptr is released on deletion
115 ~smart_ptr() { if(refcount.unique()) destructor_type()(obj); }
117 //! Template Assignment operator
118 template <class U> const smart_ptr<value_type> &
119 operator=(const smart_ptr<U> &x)
128 obj=(pointer)x.get();
135 //! Assignment operator
136 const smart_ptr<value_type> &
137 operator=(const smart_ptr<value_type> &x)
147 obj=(pointer)x.get();
154 //! smart_ptr reset procedure
160 if(refcount.unique()) destructor_type()(obj);
166 void spawn() { operator=(smart_ptr(new T)); }
168 //! Returns number of instances
169 const count_type& count()const { return refcount; }
171 //! Returns true if there is only one instance of the object
172 bool unique()const { return refcount.unique(); }
174 //! Returns a constant handle to our object
175 smart_ptr<const value_type> constant() { return *this; }
177 reference operator*()const { assert(obj); return *obj; }
179 pointer operator->()const { assert(obj); return obj; }
182 operator smart_ptr<const value_type>()const
183 { return smart_ptr<const value_type>(static_cast<const_pointer>(obj)); }
185 //! static_cast<> wrapper
186 template <class U> static
187 smart_ptr<T> cast_static(const smart_ptr<U> &x)
188 { if(!x)return NULL; return smart_ptr<T>(static_cast<T*>(x.get()),x.refcount); }
190 //! dynamic_cast<> wrapper
191 template <class U> static
192 smart_ptr<T> cast_dynamic(const smart_ptr<U> &x)
193 { if(!x)return 0; return smart_ptr<T>(dynamic_cast<T*>(x.get()),x.refcount); }
195 //! const_cast<> wrapper
196 template <class U> static
197 smart_ptr<T> cast_const(const smart_ptr<U> &x)
198 { if(!x)return 0; return smart_ptr<T>(const_cast<T*>(x.get()),x.refcount); }
200 pointer get()const { return obj; }
202 //! More explicit bool cast
203 operator bool()const { return obj!=0; }
205 bool operator!()const { return !obj; }
207 //! Overloaded cast operator -- useful for implicit casts
209 operator smart_ptr<U>()
211 // This next line should provide a syntax check
212 // to make sure that this cast makes sense.
213 // If it doesn't, this should have a compiler error.
214 // Otherwise, it should get optimized right out
218 return *reinterpret_cast<smart_ptr<U>*>(this);
221 }; // END of template class smart_ptr
223 // ========================================================================
224 /*! \class loose_smart_ptr _smart_ptr.h ETL/smart_ptr
225 ** \brief Loose Object Smart Pointer
230 class loose_smart_ptr
234 typedef T value_type;
235 typedef T& reference;
236 typedef const T& const_reference;
238 typedef const T* const_pointer;
239 typedef int count_type;
240 typedef int size_type;
243 value_type *obj; //!< \internal Pointer to object
244 weak_reference_counter refcount; //!< \internal Pointer to object's reference counter
248 //! Default constructor - empty smart_ptr
249 loose_smart_ptr():obj(0),refcount(0) {}
251 //! Default copy constructor
252 loose_smart_ptr(const loose_smart_ptr<value_type> &x):obj(x.get()),refcount(x.refcount) { }
254 loose_smart_ptr(const smart_ptr<value_type> &x):obj(x.get()),refcount(x.refcount) { }
256 void reset() { obj=0,refcount=0; }
258 operator smart_ptr<value_type>()
260 return smart_ptr<value_type>(static_cast<pointer>(obj),refcount);
263 operator smart_ptr<const value_type>()
265 return smart_ptr<const value_type>(static_cast<const_pointer>(obj),refcount);
268 //! Returns number of instances
269 const count_type& count()const { return refcount; }
271 bool unique()const { return refcount.unique(); }
273 reference operator*()const { assert(obj); return *obj; }
275 pointer operator->()const { assert(obj); return obj; }
277 pointer get()const { return obj; }
279 bool operator!()const { return !obj; }
282 template <class T,class U> bool
283 operator==(const smart_ptr<T> &lhs,const smart_ptr<U> &rhs)
284 { return (lhs.get()==rhs.get()); }
285 template <class T,class U> bool
286 operator==(const loose_smart_ptr<T> &lhs,const loose_smart_ptr<U> &rhs)
287 { return (lhs.get()==rhs.get()); }
288 template <class T,class U> bool
289 operator==(const smart_ptr<T> &lhs,const loose_smart_ptr<U> &rhs)
290 { return (lhs.get()==rhs.get()); }
291 template <class T,class U> bool
292 operator==(const loose_smart_ptr<T> &lhs,const smart_ptr<U> &rhs)
293 { return (lhs.get()==rhs.get()); }
294 template <class T> bool
295 operator==(const smart_ptr<T> &lhs,const T *rhs)
296 { return (lhs.get()==rhs); }
297 template <class T> bool
298 operator==(const loose_smart_ptr<T> &lhs,const T *rhs)
299 { return (lhs.get()==rhs); }
300 template <class T> bool
301 operator==(const T *lhs,const smart_ptr<T> &rhs)
302 { return (lhs==rhs.get()); }
303 template <class T> bool
304 operator==(const T *lhs,const loose_smart_ptr<T> &rhs)
305 { return (lhs==rhs.get()); }
308 template <class T,class U> bool
309 operator!=(const smart_ptr<T> &lhs,const smart_ptr<U> &rhs)
310 { return (lhs.get()!=rhs.get()); }
311 template <class T,class U> bool
312 operator!=(const loose_smart_ptr<T> &lhs,const loose_smart_ptr<U> &rhs)
313 { return (lhs.get()!=rhs.get()); }
314 template <class T,class U> bool
315 operator!=(const smart_ptr<T> &lhs,const loose_smart_ptr<U> &rhs)
316 { return (lhs.get()!=rhs.get()); }
317 template <class T,class U> bool
318 operator!=(const loose_smart_ptr<T> &lhs,const smart_ptr<U> &rhs)
319 { return (lhs.get()!=rhs.get()); }
320 template <class T> bool
321 operator!=(const smart_ptr<T> &lhs,const T *rhs)
322 { return (lhs.get()!=rhs); }
323 template <class T> bool
324 operator!=(const loose_smart_ptr<T> &lhs,const T *rhs)
325 { return (lhs.get()!=rhs); }
326 template <class T> bool
327 operator!=(const T *lhs,const smart_ptr<T> &rhs)
328 { return (lhs!=rhs.get()); }
329 template <class T> bool
330 operator!=(const T *lhs,const loose_smart_ptr<T> &rhs)
331 { return (lhs!=rhs.get()); }
334 template <class T,class U> bool
335 operator<(const smart_ptr<T> &lhs,const smart_ptr<U> &rhs)
336 { return (lhs.get()<rhs.get()); }
337 template <class T,class U> bool
338 operator<(const loose_smart_ptr<T> &lhs,const loose_smart_ptr<U> &rhs)
339 { return (lhs.get()<rhs.get()); }
340 template <class T,class U> bool
341 operator<(const smart_ptr<T> &lhs,const loose_smart_ptr<U> &rhs)
342 { return (lhs.get()<rhs.get()); }
343 template <class T,class U> bool
344 operator<(const loose_smart_ptr<T> &lhs,const smart_ptr<U> &rhs)
345 { return (lhs.get()<rhs.get()); }
346 template <class T> bool
347 operator<(const smart_ptr<T> &lhs,const T *rhs)
348 { return (lhs.get()<rhs); }
349 template <class T> bool
350 operator<(const loose_smart_ptr<T> &lhs,const T *rhs)
351 { return (lhs.get()<rhs); }
352 template <class T> bool
353 operator<(const T *lhs,const smart_ptr<T> &rhs)
354 { return (lhs<rhs.get()); }
355 template <class T> bool
356 operator<(const T *lhs,const loose_smart_ptr<T> &rhs)
357 { return (lhs<rhs.get()); }
361 /* === E N D =============================================================== */