Initial import of ETL
[synfig.git] / ETL / trunk / ETL / _smart_ptr.h
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 $
5 **
6 ** Copyright (c) 2002 Robert B. Quattlebaum Jr.
7 **
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.
12 **
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.
17 **
18 ** === N O T E S ===========================================================
19 **
20 ** This is an internal header file, included by other ETL headers.
21 ** You should not attempt to use it directly.
22 **
23 ** ========================================================================= */
24
25 /* === S T A R T =========================================================== */
26
27 #ifndef __ETL__SMART_PTR_H
28 #define __ETL__SMART_PTR_H
29
30 /* === H E A D E R S ======================================================= */
31
32 #include <cassert>
33 #include "_ref_count.h"
34
35 /* === M A C R O S ========================================================= */
36
37 /* === T Y P E D E F S ===================================================== */
38
39 /* === C L A S S E S & S T R U C T S ======================================= */
40
41 _ETL_BEGIN_NAMESPACE
42
43 template <class T>
44 struct generic_deleter
45 {
46         void operator()(T* x)const { delete x; }
47 };
48
49 template <class T>
50 struct array_deleter
51 {
52         void operator()(T* x)const { delete [] x; }
53 };
54
55 // ========================================================================
56 /*!     \class  smart_ptr       _smart_ptr.h    ETL/smart_ptr
57 **      \brief  Object Smart Pointer
58 **      \see loose_smart_ptr
59 **      \writeme
60 */
61 template <class T, class D=generic_deleter<T> >
62 class smart_ptr
63 {
64 public:
65
66         typedef T value_type;
67         typedef T& reference;
68         typedef const T& const_reference;
69         typedef T* pointer;
70         typedef const T* const_pointer;
71         typedef int count_type;
72         typedef int size_type;
73         typedef D destructor_type;
74
75 #ifdef DOXYGEN_SHOULD_SKIP_THIS         // #ifdef is not a typo
76 private:        
77 #endif
78         value_type *obj;                //!< \internal Pointer to object
79         reference_counter refcount;
80
81 public:
82         // Private constructor for convenience
83         smart_ptr(value_type* obj,reference_counter refcount):obj(obj),refcount(refcount) {  }
84
85         //! Default constructor - empty smart_ptr
86         smart_ptr():obj(0),refcount(false) {}
87
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) {  }
95
96         //! Template copy constructor
97         /*! This template constructor allows us to cast
98                 smart_ptrs much like we would pointers. */
99 #ifdef _WIN32
100         template <class U>
101         smart_ptr(const smart_ptr<U> &x):obj((pointer)&*x.obj),refcount(x.refcount())
102                 { }
103 #endif
104
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) {  }
111
112         explicit smart_ptr(const value_type &x):obj(new value_type(x)) { }
113
114         //! smart_ptr is released on deletion
115         ~smart_ptr() { if(refcount.unique()) destructor_type()(obj); }
116
117         //! Template Assignment operator
118         template <class U> const smart_ptr<value_type> &
119         operator=(const smart_ptr<U> &x)
120         {
121                 if(x.get()==obj)
122                         return *this;
123
124                 reset();
125
126                 if(x.obj)
127                 {
128                         obj=(pointer)x.get();
129                         refcount=x.refcount;
130                 }
131                 
132                 return *this;
133         }
134
135         //! Assignment operator
136         const smart_ptr<value_type> &
137         operator=(const smart_ptr<value_type> &x)
138         {
139                 if(x.get()==obj)
140                         return *this;
141         
142                 reset();
143
144                 if(x.obj)
145                 {
146                 
147                         obj=(pointer)x.get();
148                         refcount=x.refcount;
149                 }
150                 
151                 return *this;
152         }
153
154         //! smart_ptr reset procedure
155         void
156         reset()
157         {               
158                 if(obj)
159                 {                       
160                         if(refcount.unique()) destructor_type()(obj);
161                         refcount.detach();
162                         obj=0;
163                 }
164         }
165                 
166         void spawn() { operator=(smart_ptr(new T)); }
167
168         //! Returns number of instances
169         const count_type& count()const { return refcount; }
170
171         //! Returns true if there is only one instance of the object
172         bool unique()const { return refcount.unique(); }
173
174         //! Returns a constant handle to our object
175         smart_ptr<const value_type> constant() { return *this; }
176
177         reference operator*()const { assert(obj); return *obj; }
178
179         pointer operator->()const { assert(obj); return obj; }
180
181         //! Overloaded cast operator -- useful for implicit casts
182         template <class U>
183         operator smart_ptr<U>()
184         {
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
189                 // of the code.
190                 //(U*)obj;
191
192                 return *reinterpret_cast<smart_ptr<U>*>(this);
193         }
194
195         operator smart_ptr<const value_type>()const
196         { return smart_ptr<const value_type>(static_cast<const_pointer>(obj)); }
197
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); }
202
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); }
207
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); }
212
213         pointer get()const { return obj; }
214
215         //! More explicit bool cast
216         operator bool()const { return obj!=0; }
217
218         bool operator!()const { return !obj; }
219
220 }; // END of template class smart_ptr
221
222 // ========================================================================
223 /*!     \class  loose_smart_ptr _smart_ptr.h    ETL/smart_ptr
224 **      \brief  Loose Object Smart Pointer
225 **      \see smart_ptr
226 **      \writeme
227 */
228 template <class T>
229 class loose_smart_ptr
230 {
231 public:
232
233         typedef T value_type;
234         typedef T& reference;
235         typedef const T& const_reference;
236         typedef T* pointer;
237         typedef const T* const_pointer;
238         typedef int count_type;
239         typedef int size_type;
240
241 private:
242         value_type *obj;                //!< \internal Pointer to object
243         weak_reference_counter refcount;        //!< \internal Pointer to object's reference counter
244
245 public:
246
247         //! Default constructor - empty smart_ptr
248         loose_smart_ptr():obj(0),refcount(0) {}
249
250         //! Default copy constructor
251         loose_smart_ptr(const loose_smart_ptr<value_type> &x):obj(x.get()),refcount(x.refcount) { }
252
253         loose_smart_ptr(const smart_ptr<value_type> &x):obj(x.get()),refcount(x.refcount) { }
254
255         void reset() { obj=0,refcount=0; }
256
257         operator smart_ptr<value_type>()
258         {
259                 return smart_ptr<value_type>(static_cast<pointer>(obj),refcount);
260         }
261
262         operator smart_ptr<const value_type>()
263         {
264                 return smart_ptr<const value_type>(static_cast<const_pointer>(obj),refcount);
265         }
266
267         //! Returns number of instances
268         const count_type& count()const { return refcount; }
269
270         bool unique()const { return refcount.unique(); }
271         
272         reference operator*()const { assert(obj); return *obj; }
273
274         pointer operator->()const { assert(obj); return obj; }
275
276         pointer get()const { return obj; }
277
278         bool operator!()const { return !obj; }
279 };
280
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()); }
305
306
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()); }
331
332
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()); }
357
358 _ETL_END_NAMESPACE
359
360 /* === E N D =============================================================== */
361
362 #endif