1 /* ========================================================================
2 ** Extended Template and Library
3 ** Template Smart Pointer Implementation
4 ** $Id: _smart_ptr.h,v 1.1.1.1 2005/01/04 01:31:48 darco Exp $
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; }
181 //! Overloaded cast operator -- useful for implicit casts
183 operator smart_ptr<U>()
185 // This next line should provide a syntax check
186 // to make sure that this cast makes sense.
187 // If it doesn't, this should have a compiler error.
188 // Otherwise, it should get optimized right out
192 return *reinterpret_cast<smart_ptr<U>*>(this);
195 operator smart_ptr<const value_type>()const
196 { return smart_ptr<const value_type>(static_cast<const_pointer>(obj)); }
198 //! static_cast<> wrapper
199 template <class U> static
200 smart_ptr<T> cast_static(const smart_ptr<U> &x)
201 { if(!x)return NULL; return smart_ptr<T>(static_cast<T*>(x.get()),x.refcount); }
203 //! dynamic_cast<> wrapper
204 template <class U> static
205 smart_ptr<T> cast_dynamic(const smart_ptr<U> &x)
206 { if(!x)return 0; return smart_ptr<T>(dynamic_cast<T*>(x.get()),x.refcount); }
208 //! const_cast<> wrapper
209 template <class U> static
210 smart_ptr<T> cast_const(const smart_ptr<U> &x)
211 { if(!x)return 0; return smart_ptr<T>(const_cast<T*>(x.get()),x.refcount); }
213 pointer get()const { return obj; }
215 //! More explicit bool cast
216 operator bool()const { return obj!=0; }
218 bool operator!()const { return !obj; }
220 }; // END of template class smart_ptr
222 // ========================================================================
223 /*! \class loose_smart_ptr _smart_ptr.h ETL/smart_ptr
224 ** \brief Loose Object Smart Pointer
229 class loose_smart_ptr
233 typedef T value_type;
234 typedef T& reference;
235 typedef const T& const_reference;
237 typedef const T* const_pointer;
238 typedef int count_type;
239 typedef int size_type;
242 value_type *obj; //!< \internal Pointer to object
243 weak_reference_counter refcount; //!< \internal Pointer to object's reference counter
247 //! Default constructor - empty smart_ptr
248 loose_smart_ptr():obj(0),refcount(0) {}
250 //! Default copy constructor
251 loose_smart_ptr(const loose_smart_ptr<value_type> &x):obj(x.get()),refcount(x.refcount) { }
253 loose_smart_ptr(const smart_ptr<value_type> &x):obj(x.get()),refcount(x.refcount) { }
255 void reset() { obj=0,refcount=0; }
257 operator smart_ptr<value_type>()
259 return smart_ptr<value_type>(static_cast<pointer>(obj),refcount);
262 operator smart_ptr<const value_type>()
264 return smart_ptr<const value_type>(static_cast<const_pointer>(obj),refcount);
267 //! Returns number of instances
268 const count_type& count()const { return refcount; }
270 bool unique()const { return refcount.unique(); }
272 reference operator*()const { assert(obj); return *obj; }
274 pointer operator->()const { assert(obj); return obj; }
276 pointer get()const { return obj; }
278 bool operator!()const { return !obj; }
281 template <class T,class U> bool
282 operator==(const smart_ptr<T> &lhs,const smart_ptr<U> &rhs)
283 { return (lhs.get()==rhs.get()); }
284 template <class T,class U> bool
285 operator==(const loose_smart_ptr<T> &lhs,const loose_smart_ptr<U> &rhs)
286 { return (lhs.get()==rhs.get()); }
287 template <class T,class U> bool
288 operator==(const smart_ptr<T> &lhs,const loose_smart_ptr<U> &rhs)
289 { return (lhs.get()==rhs.get()); }
290 template <class T,class U> bool
291 operator==(const loose_smart_ptr<T> &lhs,const smart_ptr<U> &rhs)
292 { return (lhs.get()==rhs.get()); }
293 template <class T> bool
294 operator==(const smart_ptr<T> &lhs,const T *rhs)
295 { return (lhs.get()==rhs); }
296 template <class T> bool
297 operator==(const loose_smart_ptr<T> &lhs,const T *rhs)
298 { return (lhs.get()==rhs); }
299 template <class T> bool
300 operator==(const T *lhs,const smart_ptr<T> &rhs)
301 { return (lhs==rhs.get()); }
302 template <class T> bool
303 operator==(const T *lhs,const loose_smart_ptr<T> &rhs)
304 { return (lhs==rhs.get()); }
307 template <class T,class U> bool
308 operator!=(const smart_ptr<T> &lhs,const smart_ptr<U> &rhs)
309 { return (lhs.get()!=rhs.get()); }
310 template <class T,class U> bool
311 operator!=(const loose_smart_ptr<T> &lhs,const loose_smart_ptr<U> &rhs)
312 { return (lhs.get()!=rhs.get()); }
313 template <class T,class U> bool
314 operator!=(const smart_ptr<T> &lhs,const loose_smart_ptr<U> &rhs)
315 { return (lhs.get()!=rhs.get()); }
316 template <class T,class U> bool
317 operator!=(const loose_smart_ptr<T> &lhs,const smart_ptr<U> &rhs)
318 { return (lhs.get()!=rhs.get()); }
319 template <class T> bool
320 operator!=(const smart_ptr<T> &lhs,const T *rhs)
321 { return (lhs.get()!=rhs); }
322 template <class T> bool
323 operator!=(const loose_smart_ptr<T> &lhs,const T *rhs)
324 { return (lhs.get()!=rhs); }
325 template <class T> bool
326 operator!=(const T *lhs,const smart_ptr<T> &rhs)
327 { return (lhs!=rhs.get()); }
328 template <class T> bool
329 operator!=(const T *lhs,const loose_smart_ptr<T> &rhs)
330 { return (lhs!=rhs.get()); }
333 template <class T,class U> bool
334 operator<(const smart_ptr<T> &lhs,const smart_ptr<U> &rhs)
335 { return (lhs.get()<rhs.get()); }
336 template <class T,class U> bool
337 operator<(const loose_smart_ptr<T> &lhs,const loose_smart_ptr<U> &rhs)
338 { return (lhs.get()<rhs.get()); }
339 template <class T,class U> bool
340 operator<(const smart_ptr<T> &lhs,const loose_smart_ptr<U> &rhs)
341 { return (lhs.get()<rhs.get()); }
342 template <class T,class U> bool
343 operator<(const loose_smart_ptr<T> &lhs,const smart_ptr<U> &rhs)
344 { return (lhs.get()<rhs.get()); }
345 template <class T> bool
346 operator<(const smart_ptr<T> &lhs,const T *rhs)
347 { return (lhs.get()<rhs); }
348 template <class T> bool
349 operator<(const loose_smart_ptr<T> &lhs,const T *rhs)
350 { return (lhs.get()<rhs); }
351 template <class T> bool
352 operator<(const T *lhs,const smart_ptr<T> &rhs)
353 { return (lhs<rhs.get()); }
354 template <class T> bool
355 operator<(const T *lhs,const loose_smart_ptr<T> &rhs)
356 { return (lhs<rhs.get()); }
360 /* === E N D =============================================================== */