1//
2// SharedPtr.h
3//
4// Library: Foundation
5// Package: Core
6// Module: SharedPtr
7//
8// Definition of the SharedPtr template class.
9//
10// Copyright (c) 2005-2008, Applied Informatics Software Engineering GmbH.
11// and Contributors.
12//
13// SPDX-License-Identifier: BSL-1.0
14//
15
16
17#ifndef Foundation_SharedPtr_INCLUDED
18#define Foundation_SharedPtr_INCLUDED
19
20
21#include "Poco/Foundation.h"
22#include "Poco/Exception.h"
23#include <memory>
24#include <algorithm>
25#include <utility>
26
27
28namespace Poco {
29
30
31template <class C>
32class SharedPtr
33 /// As of POCO C++ Libraries Release 2.0, SharedPtr is a small wrapper around
34 /// std::shared_ptr, providing basic backwards compatibility to the 1.x SharedPtr
35 /// implementation.
36 ///
37 /// Note: ReleasePolicy is no longer supported.
38{
39public:
40 typedef C Type;
41
42 SharedPtr()
43 {
44 }
45
46 SharedPtr(C* ptr):
47 _ptr(ptr)
48 {
49 }
50
51 SharedPtr(const std::shared_ptr<C>& ptr):
52 _ptr(ptr)
53 {
54 }
55
56 template <class Other>
57 SharedPtr(const SharedPtr<Other>& ptr):
58 _ptr(std::dynamic_pointer_cast<C>(ptr.shared_ptr()))
59 {
60 }
61
62 SharedPtr(const SharedPtr& ptr):
63 _ptr(ptr._ptr)
64 {
65 }
66
67 SharedPtr(SharedPtr&& ptr):
68 _ptr(std::move(ptr._ptr))
69 {
70 }
71
72 SharedPtr(std::shared_ptr<C>&& ptr):
73 _ptr(std::move(ptr))
74 {
75 }
76
77 ~SharedPtr() noexcept
78 {
79 }
80
81 SharedPtr& assign(C* ptr)
82 {
83 _ptr.reset(ptr);
84 return *this;
85 }
86
87 SharedPtr& assign(const SharedPtr& ptr)
88 {
89 if (&ptr != this)
90 {
91 SharedPtr tmp(ptr);
92 swap(tmp);
93 }
94 return *this;
95 }
96
97 template <class Other>
98 SharedPtr& assign(const SharedPtr<Other>& ptr)
99 {
100 if (ptr.get() != _ptr.get())
101 {
102 SharedPtr tmp(ptr);
103 swap(tmp);
104 }
105 return *this;
106 }
107
108 void reset() noexcept
109 {
110 _ptr.reset();
111 }
112
113 void reset(C* ptr)
114 {
115 _ptr.reset(ptr);
116 }
117
118 void reset(const SharedPtr& ptr)
119 {
120 assign(ptr);
121 }
122
123 template <class Other>
124 void reset(const SharedPtr<Other>& ptr)
125 {
126 assign<Other>(ptr);
127 }
128
129 SharedPtr& operator = (C* ptr)
130 {
131 return assign(ptr);
132 }
133
134 SharedPtr& operator = (const SharedPtr& ptr)
135 {
136 return assign(ptr);
137 }
138
139 template <class Other>
140 SharedPtr& operator = (const SharedPtr<Other>& ptr)
141 {
142 return assign<Other>(ptr);
143 }
144
145 SharedPtr& operator = (SharedPtr&& ptr)
146 {
147 _ptr = std::move(ptr._ptr);
148 return *this;
149 }
150
151 SharedPtr& operator = (std::shared_ptr<C>&& ptr)
152 {
153 _ptr = std::move(ptr);
154 return *this;
155 }
156
157 void swap(SharedPtr& ptr)
158 {
159 std::swap(_ptr, ptr._ptr);
160 }
161
162 template <class Other>
163 SharedPtr<Other> cast() const
164 /// Casts the SharedPtr via a dynamic cast to the given type.
165 /// Returns an SharedPtr containing NULL if the cast fails.
166 /// Example: (assume class Sub: public Super)
167 /// SharedPtr<Super> super(new Sub());
168 /// SharedPtr<Sub> sub = super.cast<Sub>();
169 /// poco_assert (sub.get());
170 {
171 return SharedPtr(std::dynamic_pointer_cast<Other>(_ptr));
172 }
173
174 template <class Other>
175 SharedPtr<Other> unsafeCast() const
176 /// Casts the SharedPtr via a static cast to the given type.
177 /// Example: (assume class Sub: public Super)
178 /// SharedPtr<Super> super(new Sub());
179 /// SharedPtr<Sub> sub = super.unsafeCast<Sub>();
180 /// poco_assert (sub.get());
181 {
182 return SharedPtr(std::static_pointer_cast<Other>(_ptr));
183 }
184
185 operator std::shared_ptr<C>()
186 {
187 return _ptr;
188 }
189
190 const std::shared_ptr<C>& shared_ptr() const
191 {
192 return _ptr;
193 }
194
195 std::shared_ptr<C>& shared_ptr()
196 {
197 return _ptr;
198 }
199
200 C* operator -> ()
201 {
202 return deref();
203 }
204
205 const C* operator -> () const
206 {
207 return deref();
208 }
209
210 C& operator * ()
211 {
212 return *deref();
213 }
214
215 const C& operator * () const
216 {
217 return *deref();
218 }
219
220 C* get()
221 {
222 return _ptr.get();
223 }
224
225 const C* get() const
226 {
227 return _ptr.get();
228 }
229
230 operator C* ()
231 {
232 return _ptr.get();
233 }
234
235 operator const C* () const
236 {
237 return _ptr.get();
238 }
239
240 bool operator ! () const
241 {
242 return _ptr == 0;
243 }
244
245 bool isNull() const
246 {
247 return _ptr == 0;
248 }
249
250 bool operator == (const SharedPtr& ptr) const
251 {
252 return get() == ptr.get();
253 }
254
255 bool operator == (const C* ptr) const
256 {
257 return get() == ptr;
258 }
259
260 bool operator == (C* ptr) const
261 {
262 return get() == ptr;
263 }
264
265 bool operator != (const SharedPtr& ptr) const
266 {
267 return get() != ptr.get();
268 }
269
270 bool operator != (const C* ptr) const
271 {
272 return get() != ptr;
273 }
274
275 bool operator != (C* ptr) const
276 {
277 return get() != ptr;
278 }
279
280 bool operator < (const SharedPtr& ptr) const
281 {
282 return get() < ptr.get();
283 }
284
285 bool operator < (const C* ptr) const
286 {
287 return get() < ptr;
288 }
289
290 bool operator < (C* ptr) const
291 {
292 return get() < ptr;
293 }
294
295 bool operator <= (const SharedPtr& ptr) const
296 {
297 return get() <= ptr.get();
298 }
299
300 bool operator <= (const C* ptr) const
301 {
302 return get() <= ptr;
303 }
304
305 bool operator <= (C* ptr) const
306 {
307 return get() <= ptr;
308 }
309
310 bool operator > (const SharedPtr& ptr) const
311 {
312 return get() > ptr.get();
313 }
314
315 bool operator > (const C* ptr) const
316 {
317 return get() > ptr;
318 }
319
320 bool operator > (C* ptr) const
321 {
322 return get() > ptr;
323 }
324
325 bool operator >= (const SharedPtr& ptr) const
326 {
327 return get() >= ptr.get();
328 }
329
330 bool operator >= (const C* ptr) const
331 {
332 return get() >= ptr;
333 }
334
335 bool operator >= (C* ptr) const
336 {
337 return get() >= ptr;
338 }
339
340 long referenceCount() const
341 {
342 return _ptr.use_count();
343 }
344
345protected:
346 C* deref() const
347 {
348 if (!_ptr)
349 throw NullPointerException();
350
351 return _ptr.get();
352 }
353
354protected:
355 std::shared_ptr<C> _ptr;
356};
357
358
359template <class C>
360inline void swap(SharedPtr<C>& p1, SharedPtr<C>& p2)
361{
362 p1.swap(p2);
363}
364
365
366} // namespace Poco
367
368
369#endif // Foundation_SharedPtr_INCLUDED
370