ETL  0.04.19
_smart_ptr.h
Go to the documentation of this file.
1 /* ========================================================================
2 ** Extended Template and Library
3 ** Template Smart Pointer Implementation
4 ** $Id$
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 
42 
43 template <class T>
45 {
46  void operator()(T* x)const { delete x; }
47 };
48 
49 template <class T>
51 {
52  void operator()(T* x)const { delete [] x; }
53 };
54 
55 // ========================================================================
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
80 
81 public:
82  // Private constructor for convenience
83  smart_ptr(value_type* obj,reference_counter refcount):obj(obj),refcount(refcount) { }
84 
86  smart_ptr():obj(0),refcount(false) {}
87 
89 
94  explicit smart_ptr(value_type* x):obj(x),refcount(x?true:false) { }
95 
97 
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 
106 
111 
112  explicit smart_ptr(const value_type &x):obj(new value_type(x)) { }
113 
116 
118  template <class U> const smart_ptr<value_type> &
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 
136  const smart_ptr<value_type> &
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 
155  void
157  {
158  if(obj)
159  {
161  refcount.detach();
162  obj=0;
163  }
164  }
165 
166  void spawn() { operator=(smart_ptr(new T)); }
167 
169  const count_type& count()const { return refcount; }
170 
172  bool unique()const { return refcount.unique(); }
173 
176 
177  reference operator*()const { assert(obj); return *obj; }
178 
179  pointer operator->()const { assert(obj); return obj; }
180 
181 
183  { return smart_ptr<const value_type>(static_cast<const_pointer>(obj)); }
184 
186  template <class U> static
188  { if(!x)return NULL; return smart_ptr<T>(static_cast<T*>(x.get()),x.refcount); }
189 
191  template <class U> static
193  { if(!x)return 0; return smart_ptr<T>(dynamic_cast<T*>(x.get()),x.refcount); }
194 
196  template <class U> static
198  { if(!x)return 0; return smart_ptr<T>(const_cast<T*>(x.get()),x.refcount); }
199 
200  pointer get()const { return obj; }
201 
203  operator bool()const { return obj!=0; }
204 
205  bool operator!()const { return !obj; }
206 
208  template <class U>
209  operator smart_ptr<U>()
210  {
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
215  // of the code.
216  //(U*)obj;
217 
218  return *reinterpret_cast<smart_ptr<U>*>(this);
219  }
220 
221 }; // END of template class smart_ptr
222 
223 // ========================================================================
229 template <class T>
231 {
232 public:
233 
234  typedef T value_type;
235  typedef T& reference;
236  typedef const T& const_reference;
237  typedef T* pointer;
238  typedef const T* const_pointer;
239  typedef int count_type;
240  typedef int size_type;
241 
242 private:
245 
246 public:
247 
250 
253 
255 
256  void reset() { obj=0,refcount=0; }
257 
259  {
260  return smart_ptr<value_type>(static_cast<pointer>(obj),refcount);
261  }
262 
264  {
266  }
267 
269  const count_type& count()const { return refcount; }
270 
271  bool unique()const { return refcount.unique(); }
272 
273  reference operator*()const { assert(obj); return *obj; }
274 
275  pointer operator->()const { assert(obj); return obj; }
276 
277  pointer get()const { return obj; }
278 
279  bool operator!()const { return !obj; }
280 };
281 
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
287  { return (lhs.get()==rhs.get()); }
288 template <class T,class U> bool
290  { return (lhs.get()==rhs.get()); }
291 template <class T,class U> bool
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()); }
306 
307 
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
313  { return (lhs.get()!=rhs.get()); }
314 template <class T,class U> bool
316  { return (lhs.get()!=rhs.get()); }
317 template <class T,class U> bool
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()); }
332 
333 
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()); }
358 
360 
361 /* === E N D =============================================================== */
362 
363 #endif