1//
2// AutoPtr.h
3//
4// Library: Foundation
5// Package: Core
6// Module: AutoPtr
7//
8// Definition of the AutoPtr template class.
9//
10// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH.
11// and Contributors.
12//
13// SPDX-License-Identifier: BSL-1.0
14//
15
16
17#ifndef Foundation_AutoPtr_INCLUDED
18#define Foundation_AutoPtr_INCLUDED
19
20
21#include "Poco/Foundation.h"
22#include "Poco/Exception.h"
23#include <algorithm>
24
25
26namespace Poco {
27
28
29template <class C>
30class AutoPtr
31 /// AutoPtr is a "smart" pointer for classes implementing
32 /// reference counting based garbage collection.
33 /// To be usable with the AutoPtr template, a class must
34 /// implement the following behaviour:
35 /// A class must maintain a reference count.
36 /// The constructors of the object initialize the reference
37 /// count to one.
38 /// The class must implement a public duplicate() method:
39 /// void duplicate();
40 /// that increments the reference count by one.
41 /// The class must implement a public release() method:
42 /// void release()
43 /// that decrements the reference count by one, and,
44 /// if the reference count reaches zero, deletes the
45 /// object.
46 ///
47 /// AutoPtr works in the following way:
48 /// If an AutoPtr is assigned an ordinary pointer to
49 /// an object (via the constructor or the assignment operator),
50 /// it takes ownership of the object and the object's reference
51 /// count remains unchanged.
52 /// If the AutoPtr is assigned another AutoPtr, the
53 /// object's reference count is incremented by one by
54 /// calling duplicate() on its object.
55 /// The destructor of AutoPtr calls release() on its
56 /// object.
57 /// AutoPtr supports dereferencing with both the ->
58 /// and the * operator. An attempt to dereference a null
59 /// AutoPtr results in a NullPointerException being thrown.
60 /// AutoPtr also implements all relational operators.
61 /// Note that AutoPtr allows casting of its encapsulated data types.
62{
63public:
64 AutoPtr(): _ptr(0)
65 {
66 }
67
68 AutoPtr(C* ptr): _ptr(ptr)
69 {
70 }
71
72 AutoPtr(C* ptr, bool shared): _ptr(ptr)
73 {
74 if (shared && _ptr) _ptr->duplicate();
75 }
76
77 AutoPtr(const AutoPtr& ptr): _ptr(ptr._ptr)
78 {
79 if (_ptr) _ptr->duplicate();
80 }
81
82 AutoPtr(AutoPtr&& ptr) : _ptr(std::move(ptr._ptr))
83 {
84 ptr._ptr = nullptr;
85 }
86
87 template <class Other>
88 AutoPtr(const AutoPtr<Other>& ptr): _ptr(const_cast<Other*>(ptr.get()))
89 {
90 if (_ptr) _ptr->duplicate();
91 }
92
93 ~AutoPtr()
94 {
95 if (_ptr) _ptr->release();
96 }
97
98 AutoPtr& assign(C* ptr)
99 {
100 if (_ptr != ptr)
101 {
102 if (_ptr) _ptr->release();
103 _ptr = ptr;
104 }
105 return *this;
106 }
107
108 AutoPtr& assign(C* ptr, bool shared)
109 {
110 if (_ptr != ptr)
111 {
112 if (_ptr) _ptr->release();
113 _ptr = ptr;
114 if (shared && _ptr) _ptr->duplicate();
115 }
116 return *this;
117 }
118
119 AutoPtr& assign(const AutoPtr& ptr)
120 {
121 if (&ptr != this)
122 {
123 if (_ptr) _ptr->release();
124 _ptr = ptr._ptr;
125 if (_ptr) _ptr->duplicate();
126 }
127 return *this;
128 }
129
130 template <class Other>
131 AutoPtr& assign(const AutoPtr<Other>& ptr)
132 {
133 if (ptr.get() != _ptr)
134 {
135 if (_ptr) _ptr->release();
136 _ptr = const_cast<Other*>(ptr.get());
137 if (_ptr) _ptr->duplicate();
138 }
139 return *this;
140 }
141
142 AutoPtr& operator = (C* ptr)
143 {
144 return assign(ptr);
145 }
146
147 AutoPtr& operator = (const AutoPtr& ptr)
148 {
149 return assign(ptr);
150 }
151
152 template <class Other>
153 AutoPtr& operator = (const AutoPtr<Other>& ptr)
154 {
155 return assign<Other>(ptr);
156 }
157
158 AutoPtr& operator = (AutoPtr&& ptr)
159 {
160 swap(ptr);
161 return *this;
162 }
163
164
165 void swap(AutoPtr& ptr)
166 {
167 std::swap(_ptr, ptr._ptr);
168 }
169
170 template <class Other>
171 AutoPtr<Other> cast() const
172 /// Casts the AutoPtr via a dynamic cast to the given type.
173 /// Returns an AutoPtr containing NULL if the cast fails.
174 /// Example: (assume class Sub: public Super)
175 /// AutoPtr<Super> super(new Sub());
176 /// AutoPtr<Sub> sub = super.cast<Sub>();
177 /// poco_assert (sub.get());
178 {
179 Other* pOther = dynamic_cast<Other*>(_ptr);
180 return AutoPtr<Other>(pOther, true);
181 }
182
183 template <class Other>
184 AutoPtr<Other> unsafeCast() const
185 /// Casts the AutoPtr via a static cast to the given type.
186 /// Example: (assume class Sub: public Super)
187 /// AutoPtr<Super> super(new Sub());
188 /// AutoPtr<Sub> sub = super.unsafeCast<Sub>();
189 /// poco_assert (sub.get());
190 {
191 Other* pOther = static_cast<Other*>(_ptr);
192 return AutoPtr<Other>(pOther, true);
193 }
194
195 C* operator -> ()
196 {
197 if (_ptr)
198 return _ptr;
199 else
200 throw NullPointerException();
201 }
202
203 const C* operator -> () const
204 {
205 if (_ptr)
206 return _ptr;
207 else
208 throw NullPointerException();
209 }
210
211 C& operator * ()
212 {
213 if (_ptr)
214 return *_ptr;
215 else
216 throw NullPointerException();
217 }
218
219 const C& operator * () const
220 {
221 if (_ptr)
222 return *_ptr;
223 else
224 throw NullPointerException();
225 }
226
227 C* get()
228 {
229 return _ptr;
230 }
231
232 const C* get() const
233 {
234 return _ptr;
235 }
236
237 operator C* ()
238 {
239 return _ptr;
240 }
241
242 operator const C* () const
243 {
244 return _ptr;
245 }
246
247 bool operator ! () const
248 {
249 return _ptr == 0;
250 }
251
252 bool isNull() const
253 {
254 return _ptr == 0;
255 }
256
257 C* duplicate()
258 {
259 if (_ptr) _ptr->duplicate();
260 return _ptr;
261 }
262
263 bool operator == (const AutoPtr& ptr) const
264 {
265 return _ptr == ptr._ptr;
266 }
267
268 bool operator == (const C* ptr) const
269 {
270 return _ptr == ptr;
271 }
272
273 bool operator == (C* ptr) const
274 {
275 return _ptr == ptr;
276 }
277
278 bool operator != (const AutoPtr& ptr) const
279 {
280 return _ptr != ptr._ptr;
281 }
282
283 bool operator != (const C* ptr) const
284 {
285 return _ptr != ptr;
286 }
287
288 bool operator != (C* ptr) const
289 {
290 return _ptr != ptr;
291 }
292
293 bool operator < (const AutoPtr& ptr) const
294 {
295 return _ptr < ptr._ptr;
296 }
297
298 bool operator < (const C* ptr) const
299 {
300 return _ptr < ptr;
301 }
302
303 bool operator < (C* ptr) const
304 {
305 return _ptr < ptr;
306 }
307
308 bool operator <= (const AutoPtr& ptr) const
309 {
310 return _ptr <= ptr._ptr;
311 }
312
313 bool operator <= (const C* ptr) const
314 {
315 return _ptr <= ptr;
316 }
317
318 bool operator <= (C* ptr) const
319 {
320 return _ptr <= ptr;
321 }
322
323 bool operator > (const AutoPtr& ptr) const
324 {
325 return _ptr > ptr._ptr;
326 }
327
328 bool operator > (const C* ptr) const
329 {
330 return _ptr > ptr;
331 }
332
333 bool operator > (C* ptr) const
334 {
335 return _ptr > ptr;
336 }
337
338 bool operator >= (const AutoPtr& ptr) const
339 {
340 return _ptr >= ptr._ptr;
341 }
342
343 bool operator >= (const C* ptr) const
344 {
345 return _ptr >= ptr;
346 }
347
348 bool operator >= (C* ptr) const
349 {
350 return _ptr >= ptr;
351 }
352
353private:
354 C* _ptr;
355};
356
357
358template <class C>
359inline void swap(AutoPtr<C>& p1, AutoPtr<C>& p2)
360{
361 p1.swap(p2);
362}
363
364
365} // namespace Poco
366
367
368#endif // Foundation_AutoPtr_INCLUDED
369