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 | |
28 | namespace Poco { |
29 | |
30 | |
31 | template <class C> |
32 | class 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 | { |
39 | public: |
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 | |
345 | protected: |
346 | C* deref() const |
347 | { |
348 | if (!_ptr) |
349 | throw NullPointerException(); |
350 | |
351 | return _ptr.get(); |
352 | } |
353 | |
354 | protected: |
355 | std::shared_ptr<C> _ptr; |
356 | }; |
357 | |
358 | |
359 | template <class C> |
360 | inline 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 | |