Line data Source code
1 : // shared_ptr and weak_ptr implementation -*- C++ -*-
2 :
3 : // Copyright (C) 2007-2019 Free Software Foundation, Inc.
4 : //
5 : // This file is part of the GNU ISO C++ Library. This library is free
6 : // software; you can redistribute it and/or modify it under the
7 : // terms of the GNU General Public License as published by the
8 : // Free Software Foundation; either version 3, or (at your option)
9 : // any later version.
10 :
11 : // This library is distributed in the hope that it will be useful,
12 : // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 : // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 : // GNU General Public License for more details.
15 :
16 : // Under Section 7 of GPL version 3, you are granted additional
17 : // permissions described in the GCC Runtime Library Exception, version
18 : // 3.1, as published by the Free Software Foundation.
19 :
20 : // You should have received a copy of the GNU General Public License and
21 : // a copy of the GCC Runtime Library Exception along with this program;
22 : // see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
23 : // <http://www.gnu.org/licenses/>.
24 :
25 : // GCC Note: Based on files from version 1.32.0 of the Boost library.
26 :
27 : // shared_count.hpp
28 : // Copyright (c) 2001, 2002, 2003 Peter Dimov and Multi Media Ltd.
29 :
30 : // shared_ptr.hpp
31 : // Copyright (C) 1998, 1999 Greg Colvin and Beman Dawes.
32 : // Copyright (C) 2001, 2002, 2003 Peter Dimov
33 :
34 : // weak_ptr.hpp
35 : // Copyright (C) 2001, 2002, 2003 Peter Dimov
36 :
37 : // enable_shared_from_this.hpp
38 : // Copyright (C) 2002 Peter Dimov
39 :
40 : // Distributed under the Boost Software License, Version 1.0. (See
41 : // accompanying file LICENSE_1_0.txt or copy at
42 : // http://www.boost.org/LICENSE_1_0.txt)
43 :
44 : /** @file
45 : * This is an internal header file, included by other library headers.
46 : * Do not attempt to use it directly. @headername{memory}
47 : */
48 :
49 : #ifndef _SHARED_PTR_H
50 : #define _SHARED_PTR_H 1
51 :
52 : #include <bits/shared_ptr_base.h>
53 :
54 : namespace std _GLIBCXX_VISIBILITY(default)
55 : {
56 : _GLIBCXX_BEGIN_NAMESPACE_VERSION
57 :
58 : /**
59 : * @addtogroup pointer_abstractions
60 : * @{
61 : */
62 :
63 : /// 20.7.2.2.11 shared_ptr I/O
64 : template<typename _Ch, typename _Tr, typename _Tp, _Lock_policy _Lp>
65 : inline std::basic_ostream<_Ch, _Tr>&
66 : operator<<(std::basic_ostream<_Ch, _Tr>& __os,
67 : const __shared_ptr<_Tp, _Lp>& __p)
68 : {
69 : __os << __p.get();
70 : return __os;
71 : }
72 :
73 : template<typename _Del, typename _Tp, _Lock_policy _Lp>
74 : inline _Del*
75 : get_deleter(const __shared_ptr<_Tp, _Lp>& __p) noexcept
76 : {
77 : #if __cpp_rtti
78 : return static_cast<_Del*>(__p._M_get_deleter(typeid(_Del)));
79 : #else
80 : return 0;
81 : #endif
82 : }
83 :
84 : /// 20.7.2.2.10 shared_ptr get_deleter
85 : template<typename _Del, typename _Tp>
86 : inline _Del*
87 : get_deleter(const shared_ptr<_Tp>& __p) noexcept
88 : {
89 : #if __cpp_rtti
90 : return static_cast<_Del*>(__p._M_get_deleter(typeid(_Del)));
91 : #else
92 : return 0;
93 : #endif
94 : }
95 :
96 : /**
97 : * @brief A smart pointer with reference-counted copy semantics.
98 : *
99 : * The object pointed to is deleted when the last shared_ptr pointing to
100 : * it is destroyed or reset.
101 : */
102 : template<typename _Tp>
103 1910 : class shared_ptr : public __shared_ptr<_Tp>
104 : {
105 : template<typename... _Args>
106 : using _Constructible = typename enable_if<
107 : is_constructible<__shared_ptr<_Tp>, _Args...>::value
108 : >::type;
109 :
110 : template<typename _Arg>
111 : using _Assignable = typename enable_if<
112 : is_assignable<__shared_ptr<_Tp>&, _Arg>::value, shared_ptr&
113 : >::type;
114 :
115 : public:
116 :
117 : using element_type = typename __shared_ptr<_Tp>::element_type;
118 :
119 : #if __cplusplus > 201402L
120 : # define __cpp_lib_shared_ptr_weak_type 201606
121 : using weak_type = weak_ptr<_Tp>;
122 : #endif
123 : /**
124 : * @brief Construct an empty %shared_ptr.
125 : * @post use_count()==0 && get()==0
126 : */
127 : constexpr shared_ptr() noexcept : __shared_ptr<_Tp>() { }
128 :
129 : shared_ptr(const shared_ptr&) noexcept = default;
130 :
131 : /**
132 : * @brief Construct a %shared_ptr that owns the pointer @a __p.
133 : * @param __p A pointer that is convertible to element_type*.
134 : * @post use_count() == 1 && get() == __p
135 : * @throw std::bad_alloc, in which case @c delete @a __p is called.
136 : */
137 : template<typename _Yp, typename = _Constructible<_Yp*>>
138 : explicit
139 : shared_ptr(_Yp* __p) : __shared_ptr<_Tp>(__p) { }
140 :
141 : /**
142 : * @brief Construct a %shared_ptr that owns the pointer @a __p
143 : * and the deleter @a __d.
144 : * @param __p A pointer.
145 : * @param __d A deleter.
146 : * @post use_count() == 1 && get() == __p
147 : * @throw std::bad_alloc, in which case @a __d(__p) is called.
148 : *
149 : * Requirements: _Deleter's copy constructor and destructor must
150 : * not throw
151 : *
152 : * __shared_ptr will release __p by calling __d(__p)
153 : */
154 : template<typename _Yp, typename _Deleter,
155 : typename = _Constructible<_Yp*, _Deleter>>
156 : shared_ptr(_Yp* __p, _Deleter __d)
157 : : __shared_ptr<_Tp>(__p, std::move(__d)) { }
158 :
159 : /**
160 : * @brief Construct a %shared_ptr that owns a null pointer
161 : * and the deleter @a __d.
162 : * @param __p A null pointer constant.
163 : * @param __d A deleter.
164 : * @post use_count() == 1 && get() == __p
165 : * @throw std::bad_alloc, in which case @a __d(__p) is called.
166 : *
167 : * Requirements: _Deleter's copy constructor and destructor must
168 : * not throw
169 : *
170 : * The last owner will call __d(__p)
171 : */
172 : template<typename _Deleter>
173 : shared_ptr(nullptr_t __p, _Deleter __d)
174 : : __shared_ptr<_Tp>(__p, std::move(__d)) { }
175 :
176 : /**
177 : * @brief Construct a %shared_ptr that owns the pointer @a __p
178 : * and the deleter @a __d.
179 : * @param __p A pointer.
180 : * @param __d A deleter.
181 : * @param __a An allocator.
182 : * @post use_count() == 1 && get() == __p
183 : * @throw std::bad_alloc, in which case @a __d(__p) is called.
184 : *
185 : * Requirements: _Deleter's copy constructor and destructor must
186 : * not throw _Alloc's copy constructor and destructor must not
187 : * throw.
188 : *
189 : * __shared_ptr will release __p by calling __d(__p)
190 : */
191 : template<typename _Yp, typename _Deleter, typename _Alloc,
192 : typename = _Constructible<_Yp*, _Deleter, _Alloc>>
193 : shared_ptr(_Yp* __p, _Deleter __d, _Alloc __a)
194 : : __shared_ptr<_Tp>(__p, std::move(__d), std::move(__a)) { }
195 :
196 : /**
197 : * @brief Construct a %shared_ptr that owns a null pointer
198 : * and the deleter @a __d.
199 : * @param __p A null pointer constant.
200 : * @param __d A deleter.
201 : * @param __a An allocator.
202 : * @post use_count() == 1 && get() == __p
203 : * @throw std::bad_alloc, in which case @a __d(__p) is called.
204 : *
205 : * Requirements: _Deleter's copy constructor and destructor must
206 : * not throw _Alloc's copy constructor and destructor must not
207 : * throw.
208 : *
209 : * The last owner will call __d(__p)
210 : */
211 : template<typename _Deleter, typename _Alloc>
212 : shared_ptr(nullptr_t __p, _Deleter __d, _Alloc __a)
213 : : __shared_ptr<_Tp>(__p, std::move(__d), std::move(__a)) { }
214 :
215 : // Aliasing constructor
216 :
217 : /**
218 : * @brief Constructs a %shared_ptr instance that stores @a __p
219 : * and shares ownership with @a __r.
220 : * @param __r A %shared_ptr.
221 : * @param __p A pointer that will remain valid while @a *__r is valid.
222 : * @post get() == __p && use_count() == __r.use_count()
223 : *
224 : * This can be used to construct a @c shared_ptr to a sub-object
225 : * of an object managed by an existing @c shared_ptr.
226 : *
227 : * @code
228 : * shared_ptr< pair<int,int> > pii(new pair<int,int>());
229 : * shared_ptr<int> pi(pii, &pii->first);
230 : * assert(pii.use_count() == 2);
231 : * @endcode
232 : */
233 : template<typename _Yp>
234 : shared_ptr(const shared_ptr<_Yp>& __r, element_type* __p) noexcept
235 : : __shared_ptr<_Tp>(__r, __p) { }
236 :
237 : /**
238 : * @brief If @a __r is empty, constructs an empty %shared_ptr;
239 : * otherwise construct a %shared_ptr that shares ownership
240 : * with @a __r.
241 : * @param __r A %shared_ptr.
242 : * @post get() == __r.get() && use_count() == __r.use_count()
243 : */
244 : template<typename _Yp,
245 : typename = _Constructible<const shared_ptr<_Yp>&>>
246 : shared_ptr(const shared_ptr<_Yp>& __r) noexcept
247 : : __shared_ptr<_Tp>(__r) { }
248 :
249 : /**
250 : * @brief Move-constructs a %shared_ptr instance from @a __r.
251 : * @param __r A %shared_ptr rvalue.
252 : * @post *this contains the old value of @a __r, @a __r is empty.
253 : */
254 : shared_ptr(shared_ptr&& __r) noexcept
255 : : __shared_ptr<_Tp>(std::move(__r)) { }
256 :
257 : /**
258 : * @brief Move-constructs a %shared_ptr instance from @a __r.
259 : * @param __r A %shared_ptr rvalue.
260 : * @post *this contains the old value of @a __r, @a __r is empty.
261 : */
262 : template<typename _Yp, typename = _Constructible<shared_ptr<_Yp>>>
263 955 : shared_ptr(shared_ptr<_Yp>&& __r) noexcept
264 955 : : __shared_ptr<_Tp>(std::move(__r)) { }
265 :
266 : /**
267 : * @brief Constructs a %shared_ptr that shares ownership with @a __r
268 : * and stores a copy of the pointer stored in @a __r.
269 : * @param __r A weak_ptr.
270 : * @post use_count() == __r.use_count()
271 : * @throw bad_weak_ptr when __r.expired(),
272 : * in which case the constructor has no effect.
273 : */
274 : template<typename _Yp, typename = _Constructible<const weak_ptr<_Yp>&>>
275 : explicit shared_ptr(const weak_ptr<_Yp>& __r)
276 : : __shared_ptr<_Tp>(__r) { }
277 :
278 : #if _GLIBCXX_USE_DEPRECATED
279 : #pragma GCC diagnostic push
280 : #pragma GCC diagnostic ignored "-Wdeprecated-declarations"
281 : template<typename _Yp, typename = _Constructible<auto_ptr<_Yp>>>
282 : shared_ptr(auto_ptr<_Yp>&& __r);
283 : #pragma GCC diagnostic pop
284 : #endif
285 :
286 : // _GLIBCXX_RESOLVE_LIB_DEFECTS
287 : // 2399. shared_ptr's constructor from unique_ptr should be constrained
288 : template<typename _Yp, typename _Del,
289 : typename = _Constructible<unique_ptr<_Yp, _Del>>>
290 : shared_ptr(unique_ptr<_Yp, _Del>&& __r)
291 : : __shared_ptr<_Tp>(std::move(__r)) { }
292 :
293 : #if __cplusplus <= 201402L && _GLIBCXX_USE_DEPRECATED
294 : // This non-standard constructor exists to support conversions that
295 : // were possible in C++11 and C++14 but are ill-formed in C++17.
296 : // If an exception is thrown this constructor has no effect.
297 : template<typename _Yp, typename _Del,
298 : _Constructible<unique_ptr<_Yp, _Del>, __sp_array_delete>* = 0>
299 : shared_ptr(unique_ptr<_Yp, _Del>&& __r)
300 : : __shared_ptr<_Tp>(std::move(__r), __sp_array_delete()) { }
301 : #endif
302 :
303 : /**
304 : * @brief Construct an empty %shared_ptr.
305 : * @post use_count() == 0 && get() == nullptr
306 : */
307 : constexpr shared_ptr(nullptr_t) noexcept : shared_ptr() { }
308 :
309 : shared_ptr& operator=(const shared_ptr&) noexcept = default;
310 :
311 : template<typename _Yp>
312 : _Assignable<const shared_ptr<_Yp>&>
313 : operator=(const shared_ptr<_Yp>& __r) noexcept
314 : {
315 : this->__shared_ptr<_Tp>::operator=(__r);
316 : return *this;
317 : }
318 :
319 : #if _GLIBCXX_USE_DEPRECATED
320 : #pragma GCC diagnostic push
321 : #pragma GCC diagnostic ignored "-Wdeprecated-declarations"
322 : template<typename _Yp>
323 : _Assignable<auto_ptr<_Yp>>
324 : operator=(auto_ptr<_Yp>&& __r)
325 : {
326 : this->__shared_ptr<_Tp>::operator=(std::move(__r));
327 : return *this;
328 : }
329 : #pragma GCC diagnostic pop
330 : #endif
331 :
332 : shared_ptr&
333 : operator=(shared_ptr&& __r) noexcept
334 : {
335 : this->__shared_ptr<_Tp>::operator=(std::move(__r));
336 : return *this;
337 : }
338 :
339 : template<class _Yp>
340 : _Assignable<shared_ptr<_Yp>>
341 : operator=(shared_ptr<_Yp>&& __r) noexcept
342 : {
343 : this->__shared_ptr<_Tp>::operator=(std::move(__r));
344 : return *this;
345 : }
346 :
347 : template<typename _Yp, typename _Del>
348 : _Assignable<unique_ptr<_Yp, _Del>>
349 : operator=(unique_ptr<_Yp, _Del>&& __r)
350 : {
351 : this->__shared_ptr<_Tp>::operator=(std::move(__r));
352 : return *this;
353 : }
354 :
355 : private:
356 : // This constructor is non-standard, it is used by allocate_shared.
357 : template<typename _Alloc, typename... _Args>
358 955 : shared_ptr(_Sp_alloc_shared_tag<_Alloc> __tag, _Args&&... __args)
359 1910 : : __shared_ptr<_Tp>(__tag, std::forward<_Args>(__args)...)
360 : { }
361 :
362 : template<typename _Yp, typename _Alloc, typename... _Args>
363 : friend shared_ptr<_Yp>
364 : allocate_shared(const _Alloc& __a, _Args&&... __args);
365 :
366 : // This constructor is non-standard, it is used by weak_ptr::lock().
367 : shared_ptr(const weak_ptr<_Tp>& __r, std::nothrow_t)
368 : : __shared_ptr<_Tp>(__r, std::nothrow) { }
369 :
370 : friend class weak_ptr<_Tp>;
371 : };
372 :
373 : #if __cpp_deduction_guides >= 201606
374 : template<typename _Tp>
375 : shared_ptr(weak_ptr<_Tp>) -> shared_ptr<_Tp>;
376 : template<typename _Tp, typename _Del>
377 : shared_ptr(unique_ptr<_Tp, _Del>) -> shared_ptr<_Tp>;
378 : #endif
379 :
380 : // 20.7.2.2.7 shared_ptr comparisons
381 : template<typename _Tp, typename _Up>
382 : _GLIBCXX_NODISCARD inline bool
383 : operator==(const shared_ptr<_Tp>& __a, const shared_ptr<_Up>& __b) noexcept
384 : { return __a.get() == __b.get(); }
385 :
386 : template<typename _Tp>
387 : _GLIBCXX_NODISCARD inline bool
388 955 : operator==(const shared_ptr<_Tp>& __a, nullptr_t) noexcept
389 955 : { return !__a; }
390 :
391 : template<typename _Tp>
392 : _GLIBCXX_NODISCARD inline bool
393 : operator==(nullptr_t, const shared_ptr<_Tp>& __a) noexcept
394 : { return !__a; }
395 :
396 : template<typename _Tp, typename _Up>
397 : _GLIBCXX_NODISCARD inline bool
398 : operator!=(const shared_ptr<_Tp>& __a, const shared_ptr<_Up>& __b) noexcept
399 : { return __a.get() != __b.get(); }
400 :
401 : template<typename _Tp>
402 : _GLIBCXX_NODISCARD inline bool
403 : operator!=(const shared_ptr<_Tp>& __a, nullptr_t) noexcept
404 : { return (bool)__a; }
405 :
406 : template<typename _Tp>
407 : _GLIBCXX_NODISCARD inline bool
408 : operator!=(nullptr_t, const shared_ptr<_Tp>& __a) noexcept
409 : { return (bool)__a; }
410 :
411 : template<typename _Tp, typename _Up>
412 : _GLIBCXX_NODISCARD inline bool
413 : operator<(const shared_ptr<_Tp>& __a, const shared_ptr<_Up>& __b) noexcept
414 : {
415 : using _Tp_elt = typename shared_ptr<_Tp>::element_type;
416 : using _Up_elt = typename shared_ptr<_Up>::element_type;
417 : using _Vp = typename common_type<_Tp_elt*, _Up_elt*>::type;
418 : return less<_Vp>()(__a.get(), __b.get());
419 : }
420 :
421 : template<typename _Tp>
422 : _GLIBCXX_NODISCARD inline bool
423 : operator<(const shared_ptr<_Tp>& __a, nullptr_t) noexcept
424 : {
425 : using _Tp_elt = typename shared_ptr<_Tp>::element_type;
426 : return less<_Tp_elt*>()(__a.get(), nullptr);
427 : }
428 :
429 : template<typename _Tp>
430 : _GLIBCXX_NODISCARD inline bool
431 : operator<(nullptr_t, const shared_ptr<_Tp>& __a) noexcept
432 : {
433 : using _Tp_elt = typename shared_ptr<_Tp>::element_type;
434 : return less<_Tp_elt*>()(nullptr, __a.get());
435 : }
436 :
437 : template<typename _Tp, typename _Up>
438 : _GLIBCXX_NODISCARD inline bool
439 : operator<=(const shared_ptr<_Tp>& __a, const shared_ptr<_Up>& __b) noexcept
440 : { return !(__b < __a); }
441 :
442 : template<typename _Tp>
443 : _GLIBCXX_NODISCARD inline bool
444 : operator<=(const shared_ptr<_Tp>& __a, nullptr_t) noexcept
445 : { return !(nullptr < __a); }
446 :
447 : template<typename _Tp>
448 : _GLIBCXX_NODISCARD inline bool
449 : operator<=(nullptr_t, const shared_ptr<_Tp>& __a) noexcept
450 : { return !(__a < nullptr); }
451 :
452 : template<typename _Tp, typename _Up>
453 : _GLIBCXX_NODISCARD inline bool
454 : operator>(const shared_ptr<_Tp>& __a, const shared_ptr<_Up>& __b) noexcept
455 : { return (__b < __a); }
456 :
457 : template<typename _Tp>
458 : _GLIBCXX_NODISCARD inline bool
459 : operator>(const shared_ptr<_Tp>& __a, nullptr_t) noexcept
460 : { return nullptr < __a; }
461 :
462 : template<typename _Tp>
463 : _GLIBCXX_NODISCARD inline bool
464 : operator>(nullptr_t, const shared_ptr<_Tp>& __a) noexcept
465 : { return __a < nullptr; }
466 :
467 : template<typename _Tp, typename _Up>
468 : _GLIBCXX_NODISCARD inline bool
469 : operator>=(const shared_ptr<_Tp>& __a, const shared_ptr<_Up>& __b) noexcept
470 : { return !(__a < __b); }
471 :
472 : template<typename _Tp>
473 : _GLIBCXX_NODISCARD inline bool
474 : operator>=(const shared_ptr<_Tp>& __a, nullptr_t) noexcept
475 : { return !(__a < nullptr); }
476 :
477 : template<typename _Tp>
478 : _GLIBCXX_NODISCARD inline bool
479 : operator>=(nullptr_t, const shared_ptr<_Tp>& __a) noexcept
480 : { return !(nullptr < __a); }
481 :
482 : // 20.7.2.2.8 shared_ptr specialized algorithms.
483 : template<typename _Tp>
484 : inline void
485 : swap(shared_ptr<_Tp>& __a, shared_ptr<_Tp>& __b) noexcept
486 : { __a.swap(__b); }
487 :
488 : // 20.7.2.2.9 shared_ptr casts.
489 : template<typename _Tp, typename _Up>
490 : inline shared_ptr<_Tp>
491 : static_pointer_cast(const shared_ptr<_Up>& __r) noexcept
492 : {
493 : using _Sp = shared_ptr<_Tp>;
494 : return _Sp(__r, static_cast<typename _Sp::element_type*>(__r.get()));
495 : }
496 :
497 : template<typename _Tp, typename _Up>
498 : inline shared_ptr<_Tp>
499 : const_pointer_cast(const shared_ptr<_Up>& __r) noexcept
500 : {
501 : using _Sp = shared_ptr<_Tp>;
502 : return _Sp(__r, const_cast<typename _Sp::element_type*>(__r.get()));
503 : }
504 :
505 : template<typename _Tp, typename _Up>
506 : inline shared_ptr<_Tp>
507 : dynamic_pointer_cast(const shared_ptr<_Up>& __r) noexcept
508 : {
509 : using _Sp = shared_ptr<_Tp>;
510 : if (auto* __p = dynamic_cast<typename _Sp::element_type*>(__r.get()))
511 : return _Sp(__r, __p);
512 : return _Sp();
513 : }
514 :
515 : #if __cplusplus > 201402L
516 : template<typename _Tp, typename _Up>
517 : inline shared_ptr<_Tp>
518 : reinterpret_pointer_cast(const shared_ptr<_Up>& __r) noexcept
519 : {
520 : using _Sp = shared_ptr<_Tp>;
521 : return _Sp(__r, reinterpret_cast<typename _Sp::element_type*>(__r.get()));
522 : }
523 : #endif
524 :
525 : /**
526 : * @brief A smart pointer with weak semantics.
527 : *
528 : * With forwarding constructors and assignment operators.
529 : */
530 : template<typename _Tp>
531 : class weak_ptr : public __weak_ptr<_Tp>
532 : {
533 : template<typename _Arg>
534 : using _Constructible = typename enable_if<
535 : is_constructible<__weak_ptr<_Tp>, _Arg>::value
536 : >::type;
537 :
538 : template<typename _Arg>
539 : using _Assignable = typename enable_if<
540 : is_assignable<__weak_ptr<_Tp>&, _Arg>::value, weak_ptr&
541 : >::type;
542 :
543 : public:
544 : constexpr weak_ptr() noexcept = default;
545 :
546 : template<typename _Yp,
547 : typename = _Constructible<const shared_ptr<_Yp>&>>
548 : weak_ptr(const shared_ptr<_Yp>& __r) noexcept
549 : : __weak_ptr<_Tp>(__r) { }
550 :
551 : weak_ptr(const weak_ptr&) noexcept = default;
552 :
553 : template<typename _Yp, typename = _Constructible<const weak_ptr<_Yp>&>>
554 : weak_ptr(const weak_ptr<_Yp>& __r) noexcept
555 : : __weak_ptr<_Tp>(__r) { }
556 :
557 : weak_ptr(weak_ptr&&) noexcept = default;
558 :
559 : template<typename _Yp, typename = _Constructible<weak_ptr<_Yp>>>
560 : weak_ptr(weak_ptr<_Yp>&& __r) noexcept
561 : : __weak_ptr<_Tp>(std::move(__r)) { }
562 :
563 : weak_ptr&
564 : operator=(const weak_ptr& __r) noexcept = default;
565 :
566 : template<typename _Yp>
567 : _Assignable<const weak_ptr<_Yp>&>
568 : operator=(const weak_ptr<_Yp>& __r) noexcept
569 : {
570 : this->__weak_ptr<_Tp>::operator=(__r);
571 : return *this;
572 : }
573 :
574 : template<typename _Yp>
575 : _Assignable<const shared_ptr<_Yp>&>
576 : operator=(const shared_ptr<_Yp>& __r) noexcept
577 : {
578 : this->__weak_ptr<_Tp>::operator=(__r);
579 : return *this;
580 : }
581 :
582 : weak_ptr&
583 : operator=(weak_ptr&& __r) noexcept = default;
584 :
585 : template<typename _Yp>
586 : _Assignable<weak_ptr<_Yp>>
587 : operator=(weak_ptr<_Yp>&& __r) noexcept
588 : {
589 : this->__weak_ptr<_Tp>::operator=(std::move(__r));
590 : return *this;
591 : }
592 :
593 : shared_ptr<_Tp>
594 : lock() const noexcept
595 : { return shared_ptr<_Tp>(*this, std::nothrow); }
596 : };
597 :
598 : #if __cpp_deduction_guides >= 201606
599 : template<typename _Tp>
600 : weak_ptr(shared_ptr<_Tp>) -> weak_ptr<_Tp>;
601 : #endif
602 :
603 : // 20.7.2.3.6 weak_ptr specialized algorithms.
604 : template<typename _Tp>
605 : inline void
606 : swap(weak_ptr<_Tp>& __a, weak_ptr<_Tp>& __b) noexcept
607 : { __a.swap(__b); }
608 :
609 :
610 : /// Primary template owner_less
611 : template<typename _Tp = void>
612 : struct owner_less;
613 :
614 : /// Void specialization of owner_less
615 : template<>
616 : struct owner_less<void> : _Sp_owner_less<void, void>
617 : { };
618 :
619 : /// Partial specialization of owner_less for shared_ptr.
620 : template<typename _Tp>
621 : struct owner_less<shared_ptr<_Tp>>
622 : : public _Sp_owner_less<shared_ptr<_Tp>, weak_ptr<_Tp>>
623 : { };
624 :
625 : /// Partial specialization of owner_less for weak_ptr.
626 : template<typename _Tp>
627 : struct owner_less<weak_ptr<_Tp>>
628 : : public _Sp_owner_less<weak_ptr<_Tp>, shared_ptr<_Tp>>
629 : { };
630 :
631 : /**
632 : * @brief Base class allowing use of member function shared_from_this.
633 : */
634 : template<typename _Tp>
635 : class enable_shared_from_this
636 : {
637 : protected:
638 : constexpr enable_shared_from_this() noexcept { }
639 :
640 : enable_shared_from_this(const enable_shared_from_this&) noexcept { }
641 :
642 : enable_shared_from_this&
643 : operator=(const enable_shared_from_this&) noexcept
644 : { return *this; }
645 :
646 : ~enable_shared_from_this() { }
647 :
648 : public:
649 : shared_ptr<_Tp>
650 : shared_from_this()
651 : { return shared_ptr<_Tp>(this->_M_weak_this); }
652 :
653 : shared_ptr<const _Tp>
654 : shared_from_this() const
655 : { return shared_ptr<const _Tp>(this->_M_weak_this); }
656 :
657 : #if __cplusplus > 201402L || !defined(__STRICT_ANSI__) // c++1z or gnu++11
658 : #define __cpp_lib_enable_shared_from_this 201603
659 : weak_ptr<_Tp>
660 : weak_from_this() noexcept
661 : { return this->_M_weak_this; }
662 :
663 : weak_ptr<const _Tp>
664 : weak_from_this() const noexcept
665 : { return this->_M_weak_this; }
666 : #endif
667 :
668 : private:
669 : template<typename _Tp1>
670 : void
671 : _M_weak_assign(_Tp1* __p, const __shared_count<>& __n) const noexcept
672 : { _M_weak_this._M_assign(__p, __n); }
673 :
674 : // Found by ADL when this is an associated class.
675 : friend const enable_shared_from_this*
676 : __enable_shared_from_this_base(const __shared_count<>&,
677 : const enable_shared_from_this* __p)
678 : { return __p; }
679 :
680 : template<typename, _Lock_policy>
681 : friend class __shared_ptr;
682 :
683 : mutable weak_ptr<_Tp> _M_weak_this;
684 : };
685 :
686 : /**
687 : * @brief Create an object that is owned by a shared_ptr.
688 : * @param __a An allocator.
689 : * @param __args Arguments for the @a _Tp object's constructor.
690 : * @return A shared_ptr that owns the newly created object.
691 : * @throw An exception thrown from @a _Alloc::allocate or from the
692 : * constructor of @a _Tp.
693 : *
694 : * A copy of @a __a will be used to allocate memory for the shared_ptr
695 : * and the new object.
696 : */
697 : template<typename _Tp, typename _Alloc, typename... _Args>
698 : inline shared_ptr<_Tp>
699 955 : allocate_shared(const _Alloc& __a, _Args&&... __args)
700 : {
701 : return shared_ptr<_Tp>(_Sp_alloc_shared_tag<_Alloc>{__a},
702 955 : std::forward<_Args>(__args)...);
703 : }
704 :
705 : /**
706 : * @brief Create an object that is owned by a shared_ptr.
707 : * @param __args Arguments for the @a _Tp object's constructor.
708 : * @return A shared_ptr that owns the newly created object.
709 : * @throw std::bad_alloc, or an exception thrown from the
710 : * constructor of @a _Tp.
711 : */
712 : template<typename _Tp, typename... _Args>
713 : inline shared_ptr<_Tp>
714 955 : make_shared(_Args&&... __args)
715 : {
716 : typedef typename std::remove_cv<_Tp>::type _Tp_nc;
717 : return std::allocate_shared<_Tp>(std::allocator<_Tp_nc>(),
718 955 : std::forward<_Args>(__args)...);
719 : }
720 :
721 : /// std::hash specialization for shared_ptr.
722 : template<typename _Tp>
723 : struct hash<shared_ptr<_Tp>>
724 : : public __hash_base<size_t, shared_ptr<_Tp>>
725 : {
726 : size_t
727 : operator()(const shared_ptr<_Tp>& __s) const noexcept
728 : {
729 : return std::hash<typename shared_ptr<_Tp>::element_type*>()(__s.get());
730 : }
731 : };
732 :
733 : /// @} group pointer_abstractions
734 :
735 : #if __cplusplus >= 201703L
736 : namespace __detail::__variant
737 : {
738 : template<typename> struct _Never_valueless_alt; // see <variant>
739 :
740 : // Provide the strong exception-safety guarantee when emplacing a
741 : // shared_ptr into a variant.
742 : template<typename _Tp>
743 : struct _Never_valueless_alt<std::shared_ptr<_Tp>>
744 : : std::true_type
745 : { };
746 :
747 : // Provide the strong exception-safety guarantee when emplacing a
748 : // weak_ptr into a variant.
749 : template<typename _Tp>
750 : struct _Never_valueless_alt<std::weak_ptr<_Tp>>
751 : : std::true_type
752 : { };
753 : } // namespace __detail::__variant
754 : #endif // C++17
755 :
756 : _GLIBCXX_END_NAMESPACE_VERSION
757 : } // namespace
758 :
759 : #endif // _SHARED_PTR_H
|