libstdc++
experimental/bits/shared_ptr.h
Go to the documentation of this file.
1// Experimental shared_ptr with array support -*- C++ -*-
2
3// Copyright (C) 2015-2016 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/** @file experimental/bits/shared_ptr.h
26 * This is an internal header file, included by other library headers.
27 * Do not attempt to use it directly. @headername{experimental/memory}
28 */
29
30#ifndef _GLIBCXX_EXPERIMENTAL_SHARED_PTR_H
31#define _GLIBCXX_EXPERIMENTAL_SHARED_PTR_H 1
32
33#pragma GCC system_header
34
35#if __cplusplus <= 201103L
36# include <bits/c++14_warning.h>
37#else
38
39#include <memory>
41
42namespace std _GLIBCXX_VISIBILITY(default)
43{
44namespace experimental
45{
46inline namespace fundamentals_v2
47{
48_GLIBCXX_BEGIN_NAMESPACE_VERSION
49 template<typename _Tp> class enable_shared_from_this;
50_GLIBCXX_END_NAMESPACE_VERSION
51} // namespace fundamentals_v2
52} // namespace experimental
53
54#define __cpp_lib_experimental_shared_ptr_arrays 201406
55
56_GLIBCXX_BEGIN_NAMESPACE_VERSION
57
58 /*
59 * The specification of std::experimental::shared_ptr is slightly different
60 * to std::shared_ptr (specifically in terms of "compatible" pointers) so
61 * to implement std::experimental::shared_ptr without too much duplication
62 * we make it derive from a partial specialization of std::__shared_ptr
63 * using a special tag type, __libfund_v1.
64 *
65 * There are two partial specializations for the tag type, supporting the
66 * different interfaces of the array and non-array forms.
67 */
68
69 template <typename _Tp, bool = is_array<_Tp>::value>
70 struct __libfund_v1 { using type = _Tp; };
71
72 // Partial specialization for base class of experimental::shared_ptr<T>
73 // (i.e. the non-array form of experimental::shared_ptr)
74 template<typename _Tp, _Lock_policy _Lp>
75 class __shared_ptr<__libfund_v1<_Tp, false>, _Lp>
76 : private __shared_ptr<_Tp, _Lp>
77 {
78 // For non-arrays, Y* is compatible with T* if Y* is convertible to T*.
79 template<typename _Yp, typename _Res = void>
80 using _Compatible
81 = enable_if_t<experimental::is_convertible_v<_Yp*, _Tp*>, _Res>;
82
83 template<typename _Yp, typename _Del,
84 typename _Ptr = typename unique_ptr<_Yp, _Del>::pointer,
85 typename _Res = void>
86 using _UniqCompatible = enable_if_t<
87 experimental::is_convertible_v<_Yp*, _Tp*>
88 && experimental::is_convertible_v<_Ptr, _Tp*>,
89 _Res>;
90
91 using _Base_type = __shared_ptr<_Tp>;
92
93 _Base_type& _M_get_base() { return *this; }
94 const _Base_type& _M_get_base() const { return *this; }
95
96 public:
97 using element_type = _Tp;
98
99 constexpr __shared_ptr() noexcept = default;
100
101 template<typename _Tp1, typename = _Compatible<_Tp1>>
102 explicit
103 __shared_ptr(_Tp1* __p)
104 : _Base_type(__p)
105 { }
106
107 template<typename _Tp1, typename _Deleter, typename = _Compatible<_Tp1>>
108 __shared_ptr(_Tp1* __p, _Deleter __d)
109 : _Base_type(__p, __d)
110 { }
111
112 template<typename _Tp1, typename _Deleter, typename _Alloc,
113 typename = _Compatible<_Tp1>>
114 __shared_ptr(_Tp1* __p, _Deleter __d, _Alloc __a)
115 : _Base_type(__p, __d, __a)
116 { }
117
118 template<typename _Deleter>
119 __shared_ptr(nullptr_t __p, _Deleter __d)
120 : _Base_type(__p, __d)
121 { }
122
123 template<typename _Deleter, typename _Alloc>
124 __shared_ptr(nullptr_t __p, _Deleter __d, _Alloc __a)
125 : _Base_type(__p, __d, __a)
126 { }
127
128 template<typename _Tp1>
129 __shared_ptr(const __shared_ptr<__libfund_v1<_Tp1>, _Lp>& __r,
130 element_type* __p) noexcept
131 : _Base_type(__r._M_get_base(), __p)
132 { }
133
134 __shared_ptr(const __shared_ptr&) noexcept = default;
135 __shared_ptr(__shared_ptr&&) noexcept = default;
136 __shared_ptr& operator=(const __shared_ptr&) noexcept = default;
137 __shared_ptr& operator=(__shared_ptr&&) noexcept = default;
138 ~__shared_ptr() = default;
139
140 template<typename _Tp1, typename = _Compatible<_Tp1>>
141 __shared_ptr(const __shared_ptr<__libfund_v1<_Tp1>, _Lp>& __r) noexcept
142 : _Base_type(__r._M_get_base())
143 { }
144
145 template<typename _Tp1, typename = _Compatible<_Tp1>>
146 __shared_ptr(__shared_ptr<__libfund_v1<_Tp1>, _Lp>&& __r) noexcept
147 : _Base_type(std::move((__r._M_get_base())))
148 { }
149
150 template<typename _Tp1, typename = _Compatible<_Tp1>>
151 explicit
152 __shared_ptr(const __weak_ptr<__libfund_v1<_Tp1>, _Lp>& __r)
153 : _Base_type(__r._M_get_base())
154 { }
155
156 template<typename _Tp1, typename _Del,
157 typename = _UniqCompatible<_Tp1, _Del>>
158 __shared_ptr(unique_ptr<_Tp1, _Del>&& __r)
159 : _Base_type(std::move(__r))
160 { }
161
162#if _GLIBCXX_USE_DEPRECATED
163 // Postcondition: use_count() == 1 and __r.get() == 0
164 template<typename _Tp1, typename = _Compatible<_Tp1>>
165 __shared_ptr(std::auto_ptr<_Tp1>&& __r)
166 : _Base_type(std::move(__r))
167 { }
168#endif
169
170 constexpr __shared_ptr(nullptr_t) noexcept : __shared_ptr() { }
171
172 // reset
173 void
174 reset() noexcept
175 { __shared_ptr(nullptr).swap(*this); }
176
177 template<typename _Tp1>
178 _Compatible<_Tp1>
179 reset(_Tp1* __p)
180 {
181 _GLIBCXX_DEBUG_ASSERT(__p == 0 || __p != get());
182 __shared_ptr(__p).swap(*this);
183 }
184
185 template<typename _Tp1, typename _Deleter>
186 _Compatible<_Tp1>
187 reset(_Tp1* __p, _Deleter __d)
188 { __shared_ptr(__p, __d).swap(*this); }
189
190 template<typename _Tp1, typename _Deleter, typename _Alloc>
191 _Compatible<_Tp1>
192 reset(_Tp1* __p, _Deleter __d, _Alloc __a)
193 { __shared_ptr(__p, __d, std::move(__a)).swap(*this); }
194
195 using _Base_type::operator*;
196 using _Base_type::operator->;
197
198 template<typename _Tp1>
199 _Compatible<_Tp1, __shared_ptr&>
200 operator=(const __shared_ptr<__libfund_v1<_Tp1>, _Lp>& __r) noexcept
201 {
202 _Base_type::operator=(__r._M_get_base());
203 return *this;
204 }
205
206 template<class _Tp1>
207 _Compatible<_Tp1, __shared_ptr&>
208 operator=(__shared_ptr<__libfund_v1<_Tp1>, _Lp>&& __r) noexcept
209 {
210 _Base_type::operator=(std::move(__r._M_get_base()));
211 return *this;
212 }
213
214 template<typename _Tp1, typename _Del>
215 _UniqCompatible<_Tp1, _Del, __shared_ptr&>
216 operator=(unique_ptr<_Tp1, _Del>&& __r)
217 {
218 _Base_type::operator=(std::move(__r));
219 return *this;
220 }
221
222#if _GLIBCXX_USE_DEPRECATED
223 template<typename _Tp1>
224 _Compatible<_Tp1, __shared_ptr&>
225 operator=(std::auto_ptr<_Tp1>&& __r)
226 {
227 _Base_type::operator=(std::move(__r));
228 return *this;
229 }
230#endif
231
232 void
233 swap(__shared_ptr& __other) noexcept
234 { _Base_type::swap(__other); }
235
236 template<typename _Tp1>
237 bool
238 owner_before(__shared_ptr<__libfund_v1<_Tp1>, _Lp> const& __rhs) const
239 { return _Base_type::owner_before(__rhs._M_get_base()); }
240
241 template<typename _Tp1>
242 bool
243 owner_before(__weak_ptr<__libfund_v1<_Tp1>, _Lp> const& __rhs) const
244 { return _Base_type::owner_before(__rhs._M_get_base()); }
245
246 using _Base_type::operator bool;
247 using _Base_type::get;
248 using _Base_type::unique;
249 using _Base_type::use_count;
250
251 protected:
252
253 // make_shared not yet support for shared_ptr_arrays
254 //template<typename _Alloc, typename... _Args>
255 // __shared_ptr(_Sp_make_shared_tag __tag, const _Alloc& __a,
256 // _Args&&... __args)
257 // : _M_ptr(), _M_refcount(__tag, (_Tp*)0, __a,
258 // std::forward<_Args>(__args)...)
259 // {
260 // void* __p = _M_refcount._M_get_deleter(typeid(__tag));
261 // _M_ptr = static_cast<_Tp*>(__p);
262 // }
263
264 // __weak_ptr::lock()
265 __shared_ptr(const __weak_ptr<__libfund_v1<_Tp>, _Lp>& __r,
266 std::nothrow_t)
267 : _Base_type(__r._M_get_base(), std::nothrow)
268 { }
269
270 private:
271 template<typename _Tp1, _Lock_policy _Lp1> friend class __weak_ptr;
272 template<typename _Tp1, _Lock_policy _Lp1> friend class __shared_ptr;
273
274 // TODO
275 template<typename _Del, typename _Tp1, _Lock_policy _Lp1>
276 friend _Del* get_deleter(const __shared_ptr<_Tp1, _Lp1>&) noexcept;
277 };
278
279 // Helper traits for shared_ptr of array:
280
281 // Trait that tests if Y* is compatible with T*, for shared_ptr purposes.
282 template<typename _Yp, typename _Tp>
283 struct __sp_compatible
284 : is_convertible<_Yp*, _Tp*>::type
285 { };
286
287 template<size_t _Nm, typename _Tp>
288 struct __sp_compatible<_Tp[_Nm], _Tp[]>
289 : true_type
290 { };
291
292 template<size_t _Nm, typename _Tp>
293 struct __sp_compatible<_Tp[_Nm], const _Tp[]>
294 : true_type
295 { };
296
297 template<typename _Yp, typename _Tp>
298 constexpr bool __sp_compatible_v
299 = __sp_compatible<_Yp, _Tp>::value;
300
301 // Test conversion from Y(*)[N] to U(*)[N] without forming invalid type Y[N].
302 template<typename _Up, size_t _Nm, typename _Yp, typename = void>
303 struct __sp_is_constructible_arrN
304 : false_type
305 { };
306
307 template<typename _Up, size_t _Nm, typename _Yp>
308 struct __sp_is_constructible_arrN<_Up, _Nm, _Yp, __void_t<_Yp[_Nm]>>
309 : is_convertible<_Yp(*)[_Nm], _Up(*)[_Nm]>::type
310 { };
311
312 // Test conversion from Y(*)[] to U(*)[] without forming invalid type Y[].
313 template<typename _Up, typename _Yp, typename = void>
314 struct __sp_is_constructible_arr
315 : false_type
316 { };
317
318 template<typename _Up, typename _Yp>
319 struct __sp_is_constructible_arr<_Up, _Yp, __void_t<_Yp[]>>
320 : is_convertible<_Yp(*)[], _Up(*)[]>::type
321 { };
322
323 // Trait to check if shared_ptr<T> can be constructed from Y*.
324 template<typename _Tp, typename _Yp>
325 struct __sp_is_constructible;
326
327 // When T is U[N], Y(*)[N] shall be convertible to T*;
328 template<typename _Up, size_t _Nm, typename _Yp>
329 struct __sp_is_constructible<_Up[_Nm], _Yp>
330 : __sp_is_constructible_arrN<_Up, _Nm, _Yp>::type
331 { };
332
333 // when T is U[], Y(*)[] shall be convertible to T*;
334 template<typename _Up, typename _Yp>
335 struct __sp_is_constructible<_Up[], _Yp>
336 : __sp_is_constructible_arr<_Up, _Yp>::type
337 { };
338
339 // otherwise, Y* shall be convertible to T*.
340 template<typename _Tp, typename _Yp>
341 struct __sp_is_constructible
342 : is_convertible<_Yp*, _Tp*>::type
343 { };
344
345 template<typename _Tp, typename _Yp>
346 constexpr bool __sp_is_constructible_v
347 = __sp_is_constructible<_Tp, _Yp>::value;
348
349
350 // Partial specialization for base class of experimental::shared_ptr<T[N]>
351 // and experimental::shared_ptr<T[]> (i.e. the array forms).
352 template<typename _Tp, _Lock_policy _Lp>
353 class __shared_ptr<__libfund_v1<_Tp, true>, _Lp>
354 : private __shared_ptr<remove_extent_t<_Tp>, _Lp>
355 {
356 public:
357 using element_type = remove_extent_t<_Tp>;
358
359 private:
360 struct _Array_deleter
361 {
362 void
363 operator()(element_type const *__p) const
364 { delete [] __p; }
365 };
366
367 // Constraint for constructing/resetting with a pointer of type _Yp*:
368 template<typename _Yp>
369 using _SafeConv = enable_if_t<__sp_is_constructible_v<_Tp, _Yp>>;
370
371 // Constraint for constructing/assigning from smart_pointer<_Tp1>:
372 template<typename _Tp1, typename _Res = void>
373 using _Compatible = enable_if_t<__sp_compatible_v<_Tp1, _Tp>, _Res>;
374
375 // Constraint for constructing/assigning from unique_ptr<_Tp1, _Del>:
376 template<typename _Tp1, typename _Del,
377 typename _Ptr = typename unique_ptr<_Tp1, _Del>::pointer,
378 typename _Res = void>
379 using _UniqCompatible = enable_if_t<
380 __sp_compatible_v<_Tp1, _Tp>
381 && experimental::is_convertible_v<_Ptr, element_type*>,
382 _Res>;
383
384 using _Base_type = __shared_ptr<element_type>;
385
386 _Base_type& _M_get_base() { return *this; }
387 const _Base_type& _M_get_base() const { return *this; }
388
389 public:
390 constexpr __shared_ptr() noexcept
391 : _Base_type()
392 { }
393
394 template<typename _Tp1, typename = _SafeConv<_Tp1>>
395 explicit
396 __shared_ptr(_Tp1* __p)
397 : _Base_type(__p, _Array_deleter())
398 { }
399
400 template<typename _Tp1, typename _Deleter, typename = _SafeConv<_Tp1>>
401 __shared_ptr(_Tp1* __p, _Deleter __d)
402 : _Base_type(__p, __d)
403 { }
404
405 template<typename _Tp1, typename _Deleter, typename _Alloc,
406 typename = _SafeConv<_Tp1>>
407 __shared_ptr(_Tp1* __p, _Deleter __d, _Alloc __a)
408 : _Base_type(__p, __d, __a)
409 { }
410
411 template<typename _Deleter>
412 __shared_ptr(nullptr_t __p, _Deleter __d)
413 : _Base_type(__p, __d)
414 { }
415
416 template<typename _Deleter, typename _Alloc>
417 __shared_ptr(nullptr_t __p, _Deleter __d, _Alloc __a)
418 : _Base_type(__p, __d, __a)
419 { }
420
421 template<typename _Tp1>
422 __shared_ptr(const __shared_ptr<__libfund_v1<_Tp1>, _Lp>& __r,
423 element_type* __p) noexcept
424 : _Base_type(__r._M_get_base(), __p)
425 { }
426
427 __shared_ptr(const __shared_ptr&) noexcept = default;
428 __shared_ptr(__shared_ptr&&) noexcept = default;
429 __shared_ptr& operator=(const __shared_ptr&) noexcept = default;
430 __shared_ptr& operator=(__shared_ptr&&) noexcept = default;
431 ~__shared_ptr() = default;
432
433 template<typename _Tp1, typename = _Compatible<_Tp1>>
434 __shared_ptr(const __shared_ptr<__libfund_v1<_Tp1>, _Lp>& __r) noexcept
435 : _Base_type(__r._M_get_base())
436 { }
437
438 template<typename _Tp1, typename = _Compatible<_Tp1>>
439 __shared_ptr(__shared_ptr<__libfund_v1<_Tp1>, _Lp>&& __r) noexcept
440 : _Base_type(std::move((__r._M_get_base())))
441 { }
442
443 template<typename _Tp1, typename = _Compatible<_Tp1>>
444 explicit
445 __shared_ptr(const __weak_ptr<__libfund_v1<_Tp1>, _Lp>& __r)
446 : _Base_type(__r._M_get_base())
447 { }
448
449 template<typename _Tp1, typename _Del,
450 typename = _UniqCompatible<_Tp1, _Del>>
451 __shared_ptr(unique_ptr<_Tp1, _Del>&& __r)
452 : _Base_type(std::move(__r))
453 { }
454
455#if _GLIBCXX_USE_DEPRECATED
456 // Postcondition: use_count() == 1 and __r.get() == 0
457 template<typename _Tp1, typename = _Compatible<_Tp1>>
458 __shared_ptr(auto_ptr<_Tp1>&& __r)
459 : _Base_type(std::move(__r))
460 { }
461#endif
462
463 constexpr __shared_ptr(nullptr_t) noexcept : __shared_ptr() { }
464
465 // reset
466 void
467 reset() noexcept
468 { __shared_ptr(nullptr).swap(*this); }
469
470 template<typename _Tp1>
471 _SafeConv<_Tp1>
472 reset(_Tp1* __p)
473 {
474 _GLIBCXX_DEBUG_ASSERT(__p == 0 || __p != get());
475 __shared_ptr(__p, _Array_deleter()).swap(*this);
476 }
477
478 template<typename _Tp1, typename _Deleter>
479 _SafeConv<_Tp1>
480 reset(_Tp1* __p, _Deleter __d)
481 { __shared_ptr(__p, __d).swap(*this); }
482
483 template<typename _Tp1, typename _Deleter, typename _Alloc>
484 _SafeConv<_Tp1>
485 reset(_Tp1* __p, _Deleter __d, _Alloc __a)
486 { __shared_ptr(__p, __d, std::move(__a)).swap(*this); }
487
488 element_type&
489 operator[](ptrdiff_t i) const noexcept
490 {
491 _GLIBCXX_DEBUG_ASSERT(get() != 0 && i >= 0);
492 return get()[i];
493 }
494
495 template<typename _Tp1>
496 _Compatible<_Tp1, __shared_ptr&>
497 operator=(const __shared_ptr<__libfund_v1<_Tp1>, _Lp>& __r) noexcept
498 {
499 _Base_type::operator=(__r._M_get_base());
500 return *this;
501 }
502
503 template<class _Tp1>
504 _Compatible<_Tp1, __shared_ptr&>
505 operator=(__shared_ptr<__libfund_v1<_Tp1>, _Lp>&& __r) noexcept
506 {
507 _Base_type::operator=(std::move(__r._M_get_base()));
508 return *this;
509 }
510
511 template<typename _Tp1, typename _Del>
512 _UniqCompatible<_Tp1, _Del, __shared_ptr&>
513 operator=(unique_ptr<_Tp1, _Del>&& __r)
514 {
515 _Base_type::operator=(std::move(__r));
516 return *this;
517 }
518
519#if _GLIBCXX_USE_DEPRECATED
520 template<typename _Tp1>
521 _Compatible<_Tp1, __shared_ptr&>
522 operator=(auto_ptr<_Tp1>&& __r)
523 {
524 _Base_type::operator=(std::move(__r));
525 return *this;
526 }
527#endif
528
529 void
530 swap(__shared_ptr& __other) noexcept
531 { _Base_type::swap(__other); }
532
533 template<typename _Tp1>
534 bool
535 owner_before(__shared_ptr<__libfund_v1<_Tp1>, _Lp> const& __rhs) const
536 { return _Base_type::owner_before(__rhs._M_get_base()); }
537
538 template<typename _Tp1>
539 bool
540 owner_before(__weak_ptr<__libfund_v1<_Tp1>, _Lp> const& __rhs) const
541 { return _Base_type::owner_before(__rhs._M_get_base()); }
542
543 using _Base_type::operator bool;
544 using _Base_type::get;
545 using _Base_type::unique;
546 using _Base_type::use_count;
547
548 protected:
549
550 // make_shared not yet support for shared_ptr_arrays
551 //template<typename _Alloc, typename... _Args>
552 // __shared_ptr(_Sp_make_shared_tag __tag, const _Alloc& __a,
553 // _Args&&... __args)
554 // : _M_ptr(), _M_refcount(__tag, (_Tp*)0, __a,
555 // std::forward<_Args>(__args)...)
556 // {
557 // void* __p = _M_refcount._M_get_deleter(typeid(__tag));
558 // _M_ptr = static_cast<_Tp*>(__p);
559 // }
560
561 // __weak_ptr::lock()
562 __shared_ptr(const __weak_ptr<__libfund_v1<_Tp>, _Lp>& __r,
563 std::nothrow_t)
564 : _Base_type(__r._M_get_base(), std::nothrow)
565 { }
566
567 private:
568 template<typename _Tp1, _Lock_policy _Lp1> friend class __weak_ptr;
569 template<typename _Tp1, _Lock_policy _Lp1> friend class __shared_ptr;
570
571 // TODO
572 template<typename _Del, typename _Tp1, _Lock_policy _Lp1>
573 friend _Del* get_deleter(const __shared_ptr<_Tp1, _Lp1>&) noexcept;
574 };
575
576 // weak_ptr specialization for __shared_ptr array
577 template<typename _Tp, _Lock_policy _Lp>
578 class __weak_ptr<__libfund_v1<_Tp>, _Lp>
579 : __weak_ptr<remove_extent_t<_Tp>, _Lp>
580 {
581 template<typename _Tp1, typename _Res = void>
582 using _Compatible
583 = enable_if_t<__sp_compatible_v<_Tp1, _Tp>, _Res>;
584
585 using _Base_type = __weak_ptr<remove_extent_t<_Tp>>;
586
587 _Base_type& _M_get_base() { return *this; }
588 const _Base_type& _M_get_base() const { return *this; }
589
590 public:
591 using element_type = remove_extent_t<_Tp>;
592
593 constexpr __weak_ptr() noexcept
594 : _Base_type()
595 { }
596
597 __weak_ptr(const __weak_ptr&) noexcept = default;
598
599 ~__weak_ptr() = default;
600
601 template<typename _Tp1, typename = _Compatible<_Tp1>>
602 __weak_ptr(const __weak_ptr<__libfund_v1<_Tp1>, _Lp>& __r) noexcept
603 : _Base_type(__r._M_get_base())
604 { }
605
606 template<typename _Tp1, typename = _Compatible<_Tp1>>
607 __weak_ptr(const __shared_ptr<__libfund_v1<_Tp1>, _Lp>& __r) noexcept
608 : _Base_type(__r._M_get_base())
609 { }
610
611 __weak_ptr(__weak_ptr&& __r) noexcept
612 : _Base_type(std::move(__r))
613 { }
614
615 template<typename _Tp1, typename = _Compatible<_Tp1>>
616 __weak_ptr(__weak_ptr<__libfund_v1<_Tp1>, _Lp>&& __r) noexcept
617 : _Base_type(std::move(__r._M_get_base()))
618 { }
619
620 __weak_ptr&
621 operator=(const __weak_ptr& __r) noexcept = default;
622
623 template<typename _Tp1>
624 _Compatible<_Tp1, __weak_ptr&>
625 operator=(const __weak_ptr<__libfund_v1<_Tp1>, _Lp>& __r) noexcept
626 {
627 this->_Base_type::operator=(__r._M_get_base());
628 return *this;
629 }
630
631 template<typename _Tp1>
632 _Compatible<_Tp1, __weak_ptr&>
633 operator=(const __shared_ptr<_Tp1, _Lp>& __r) noexcept
634 {
635 this->_Base_type::operator=(__r._M_get_base());
636 return *this;
637 }
638
639 __weak_ptr&
640 operator=(__weak_ptr&& __r) noexcept
641 {
642 this->_Base_type::operator=(std::move(__r));
643 return *this;
644 }
645
646 template<typename _Tp1>
647 _Compatible<_Tp1, __weak_ptr&>
648 operator=(__weak_ptr<_Tp1, _Lp>&& __r) noexcept
649 {
650 this->_Base_type::operator=(std::move(__r._M_get_base()));
651 return *this;
652 }
653
654 void
655 swap(__weak_ptr& __other) noexcept
656 { this->_Base_type::swap(__other); }
657
658 template<typename _Tp1>
659 bool
660 owner_before(const __shared_ptr<__libfund_v1<_Tp1>, _Lp>& __rhs) const
661 { return _Base_type::owner_before(__rhs._M_get_base()); }
662
663 template<typename _Tp1>
664 bool
665 owner_before(const __weak_ptr<__libfund_v1<_Tp1>, _Lp>& __rhs) const
666 { return _Base_type::owner_before(__rhs._M_get_base()); }
667
668 __shared_ptr<__libfund_v1<_Tp>, _Lp>
669 lock() const noexcept // should not be element_type
670 { return __shared_ptr<__libfund_v1<_Tp>, _Lp>(*this, std::nothrow); }
671
672 using _Base_type::use_count;
673 using _Base_type::expired;
674 using _Base_type::reset;
675
676 private:
677 // Used by __enable_shared_from_this.
678 void
679 _M_assign(element_type* __ptr,
680 const __shared_count<_Lp>& __refcount) noexcept
681 { this->_Base_type::_M_assign(__ptr, __refcount); }
682
683 template<typename _Tp1, _Lock_policy _Lp1> friend class __shared_ptr;
684 template<typename _Tp1, _Lock_policy _Lp1> friend class __weak_ptr;
685 friend class __enable_shared_from_this<_Tp, _Lp>;
686 friend class experimental::enable_shared_from_this<_Tp>;
687 friend class enable_shared_from_this<_Tp>;
688 };
689
690_GLIBCXX_END_NAMESPACE_VERSION
691
692namespace experimental
693{
694inline namespace fundamentals_v2
695{
696_GLIBCXX_BEGIN_NAMESPACE_VERSION
697
698 // 8.2.1
699
700 template<typename _Tp> class shared_ptr;
701 template<typename _Tp> class weak_ptr;
702
703 template<typename _Tp, _Lock_policy _Lp = __default_lock_policy>
704 using __shared_ptr = std::__shared_ptr<__libfund_v1<_Tp>, _Lp>;
705
706 template<typename _Tp, _Lock_policy _Lp = __default_lock_policy>
707 using __weak_ptr = std::__weak_ptr<__libfund_v1<_Tp>, _Lp>;
708
709 template<typename _Tp>
710 class shared_ptr : public __shared_ptr<_Tp>
711 {
712 using _Base_type = __shared_ptr<_Tp>;
713
714 public:
715 using element_type = typename _Base_type::element_type;
716
717 private:
718 // Constraint for construction from a pointer of type _Yp*:
719 template<typename _Yp>
720 using _SafeConv = enable_if_t<__sp_is_constructible_v<_Tp, _Yp>>;
721
722 template<typename _Tp1, typename _Res = void>
723 using _Compatible
724 = enable_if_t<__sp_compatible_v<_Tp1, _Tp>, _Res>;
725
726 template<typename _Tp1, typename _Del,
727 typename _Ptr = typename unique_ptr<_Tp1, _Del>::pointer,
728 typename _Res = void>
729 using _UniqCompatible = enable_if_t<
730 __sp_compatible_v<_Tp1, _Tp>
731 && experimental::is_convertible_v<_Ptr, element_type*>,
732 _Res>;
733
734 public:
735
736 // 8.2.1.1, shared_ptr constructors
737 constexpr shared_ptr() noexcept = default;
738
739 template<typename _Tp1, typename = _SafeConv<_Tp1>>
740 explicit
741 shared_ptr(_Tp1* __p) : _Base_type(__p)
742 { _M_enable_shared_from_this_with(__p); }
743
744 template<typename _Tp1, typename _Deleter, typename = _SafeConv<_Tp1>>
745 shared_ptr(_Tp1* __p, _Deleter __d)
746 : _Base_type(__p, __d)
747 { _M_enable_shared_from_this_with(__p); }
748
749 template<typename _Tp1, typename _Deleter, typename _Alloc,
750 typename = _SafeConv<_Tp1>>
751 shared_ptr(_Tp1* __p, _Deleter __d, _Alloc __a)
752 : _Base_type(__p, __d, __a)
753 { _M_enable_shared_from_this_with(__p); }
754
755 template<typename _Deleter>
756 shared_ptr(nullptr_t __p, _Deleter __d)
757 : _Base_type(__p, __d) { }
758
759 template<typename _Deleter, typename _Alloc>
760 shared_ptr(nullptr_t __p, _Deleter __d, _Alloc __a)
761 : _Base_type(__p, __d, __a) { }
762
763 template<typename _Tp1>
764 shared_ptr(const shared_ptr<_Tp1>& __r, element_type* __p) noexcept
765 : _Base_type(__r, __p) { }
766
767 shared_ptr(const shared_ptr& __r) noexcept
768 : _Base_type(__r) { }
769
770 template<typename _Tp1, typename = _Compatible<_Tp1>>
771 shared_ptr(const shared_ptr<_Tp1>& __r) noexcept
772 : _Base_type(__r) { }
773
774 shared_ptr(shared_ptr&& __r) noexcept
775 : _Base_type(std::move(__r)) { }
776
777 template<typename _Tp1, typename = _Compatible<_Tp1>>
778 shared_ptr(shared_ptr<_Tp1>&& __r) noexcept
779 : _Base_type(std::move(__r)) { }
780
781 template<typename _Tp1, typename = _Compatible<_Tp1>>
782 explicit
783 shared_ptr(const weak_ptr<_Tp1>& __r)
784 : _Base_type(__r) { }
785
786#if _GLIBCXX_USE_DEPRECATED
787 template<typename _Tp1, typename = _Compatible<_Tp1>>
788 shared_ptr(std::auto_ptr<_Tp1>&& __r)
789 : _Base_type(std::move(__r))
790 { _M_enable_shared_from_this_with(static_cast<_Tp1*>(this->get())); }
791#endif
792
793 template<typename _Tp1, typename _Del,
794 typename = _UniqCompatible<_Tp1, _Del>>
795 shared_ptr(unique_ptr<_Tp1, _Del>&& __r)
796 : _Base_type(std::move(__r))
797 {
798 // XXX assume conversion from __r.get() to this->get() to __elem_t*
799 // is a round trip, which might not be true in all cases.
800 using __elem_t = typename unique_ptr<_Tp1, _Del>::element_type;
801 _M_enable_shared_from_this_with(static_cast<__elem_t*>(this->get()));
802 }
803
804 constexpr shared_ptr(nullptr_t __p)
805 : _Base_type(__p) { }
806
807 // C++14 §20.8.2.2
808 ~shared_ptr() = default;
809
810 // C++14 §20.8.2.3
811 shared_ptr& operator=(const shared_ptr&) noexcept = default;
812
813 template <typename _Tp1>
814 _Compatible<_Tp1, shared_ptr&>
815 operator=(const shared_ptr<_Tp1>& __r) noexcept
816 {
817 _Base_type::operator=(__r);
818 return *this;
819 }
820
821 shared_ptr&
822 operator=(shared_ptr&& __r) noexcept
823 {
824 _Base_type::operator=(std::move(__r));
825 return *this;
826 }
827
828 template <typename _Tp1>
829 _Compatible<_Tp1, shared_ptr&>
830 operator=(shared_ptr<_Tp1>&& __r) noexcept
831 {
832 _Base_type::operator=(std::move(__r));
833 return *this;
834 }
835
836#if _GLIBCXX_USE_DEPRECATED
837 template<typename _Tp1>
838 _Compatible<_Tp1, shared_ptr&>
839 operator=(std::auto_ptr<_Tp1>&& __r)
840 {
841 __shared_ptr<_Tp>::operator=(std::move(__r));
842 return *this;
843 }
844#endif
845
846 template <typename _Tp1, typename _Del>
847 _UniqCompatible<_Tp1, _Del, shared_ptr&>
848 operator=(unique_ptr<_Tp1, _Del>&& __r)
849 {
850 _Base_type::operator=(std::move(__r));
851 return *this;
852 }
853
854 // C++14 §20.8.2.2.4
855 // swap & reset
856 // 8.2.1.2 shared_ptr observers
857 // in __shared_ptr
858
859 private:
860 template<typename _Alloc, typename... _Args>
861 shared_ptr(_Sp_make_shared_tag __tag, const _Alloc& __a,
862 _Args&&... __args)
863 : _Base_type(__tag, __a, std::forward<_Args>(__args)...)
864 { _M_enable_shared_from_this_with(this->get()); }
865
866 template<typename _Tp1, typename _Alloc, typename... _Args>
867 friend shared_ptr<_Tp1>
868 allocate_shared(const _Alloc& __a, _Args&&... __args);
869
870 shared_ptr(const weak_ptr<_Tp>& __r, std::nothrow_t)
871 : _Base_type(__r, std::nothrow) { }
872
873 friend class weak_ptr<_Tp>;
874
875 template<typename _Yp>
876 using __esft_base_t =
877 decltype(__expt_enable_shared_from_this_base(std::declval<_Yp*>()));
878
879 // Detect an accessible and unambiguous enable_shared_from_this base.
880 template<typename _Yp, typename = void>
881 struct __has_esft_base
882 : false_type { };
883
884 template<typename _Yp>
885 struct __has_esft_base<_Yp, __void_t<__esft_base_t<_Yp>>>
886 : __bool_constant<!is_array_v<_Tp>> { }; // ignore base for arrays
887
888 template<typename _Yp>
889 typename enable_if<__has_esft_base<_Yp>::value>::type
890 _M_enable_shared_from_this_with(const _Yp* __p) noexcept
891 {
892 if (auto __base = __expt_enable_shared_from_this_base(__p))
893 {
894 __base->_M_weak_this
895 = shared_ptr<_Yp>(*this, const_cast<_Yp*>(__p));
896 }
897 }
898
899 template<typename _Yp>
900 typename enable_if<!__has_esft_base<_Yp>::value>::type
901 _M_enable_shared_from_this_with(const _Yp*) noexcept
902 { }
903 };
904
905 // C++14 §20.8.2.2.7 //DOING
906 template<typename _Tp1, typename _Tp2>
907 bool operator==(const shared_ptr<_Tp1>& __a,
908 const shared_ptr<_Tp2>& __b) noexcept
909 { return __a.get() == __b.get(); }
910
911 template<typename _Tp>
912 inline bool
913 operator==(const shared_ptr<_Tp>& __a, nullptr_t) noexcept
914 { return !__a; }
915
916 template<typename _Tp>
917 inline bool
918 operator==(nullptr_t, const shared_ptr<_Tp>& __a) noexcept
919 { return !__a; }
920
921 template<typename _Tp1, typename _Tp2>
922 inline bool
923 operator!=(const shared_ptr<_Tp1>& __a,
924 const shared_ptr<_Tp2>& __b) noexcept
925 { return __a.get() != __b.get(); }
926
927 template<typename _Tp>
928 inline bool
929 operator!=(const shared_ptr<_Tp>& __a, nullptr_t) noexcept
930 { return (bool)__a; }
931
932 template<typename _Tp>
933 inline bool
934 operator!=(nullptr_t, const shared_ptr<_Tp>& __a) noexcept
935 { return (bool)__a; }
936
937 template<typename _Tp1, typename _Tp2>
938 inline bool
939 operator<(const shared_ptr<_Tp1>& __a,
940 const shared_ptr<_Tp2>& __b) noexcept
941 {
942 using __elem_t1 = typename shared_ptr<_Tp1>::element_type;
943 using __elem_t2 = typename shared_ptr<_Tp2>::element_type;
944 using _CT = common_type_t<__elem_t1*, __elem_t2*>;
945 return std::less<_CT>()(__a.get(), __b.get());
946 }
947
948 template<typename _Tp>
949 inline bool
950 operator<(const shared_ptr<_Tp>& __a, nullptr_t) noexcept
951 {
952 using __elem_t = typename shared_ptr<_Tp>::element_type;
953 return std::less<__elem_t*>()(__a.get(), nullptr);
954 }
955
956 template<typename _Tp>
957 inline bool
958 operator<(nullptr_t, const shared_ptr<_Tp>& __a) noexcept
959 {
960 using __elem_t = typename shared_ptr<_Tp>::element_type;
961 return std::less<__elem_t*>()(nullptr, __a.get());
962 }
963
964 template<typename _Tp1, typename _Tp2>
965 inline bool
966 operator<=(const shared_ptr<_Tp1>& __a,
967 const shared_ptr<_Tp2>& __b) noexcept
968 { return !(__b < __a); }
969
970 template<typename _Tp>
971 inline bool
972 operator<=(const shared_ptr<_Tp>& __a, nullptr_t) noexcept
973 { return !(nullptr < __a); }
974
975 template<typename _Tp>
976 inline bool
977 operator<=(nullptr_t, const shared_ptr<_Tp>& __a) noexcept
978 { return !(__a < nullptr); }
979
980 template<typename _Tp1, typename _Tp2>
981 inline bool
982 operator>(const shared_ptr<_Tp1>& __a,
983 const shared_ptr<_Tp2>& __b) noexcept
984 { return (__b < __a); }
985
986 template<typename _Tp>
987 inline bool
988 operator>(const shared_ptr<_Tp>& __a, nullptr_t) noexcept
989 {
990 using __elem_t = typename shared_ptr<_Tp>::element_type;
991 return std::less<__elem_t*>()(nullptr, __a.get());
992 }
993
994 template<typename _Tp>
995 inline bool
996 operator>(nullptr_t, const shared_ptr<_Tp>& __a) noexcept
997 {
998 using __elem_t = typename shared_ptr<_Tp>::element_type;
999 return std::less<__elem_t*>()(__a.get(), nullptr);
1000 }
1001
1002 template<typename _Tp1, typename _Tp2>
1003 inline bool
1004 operator>=(const shared_ptr<_Tp1>& __a,
1005 const shared_ptr<_Tp2>& __b) noexcept
1006 { return !(__a < __b); }
1007
1008 template<typename _Tp>
1009 inline bool
1010 operator>=(const shared_ptr<_Tp>& __a, nullptr_t) noexcept
1011 { return !(__a < nullptr); }
1012
1013 template<typename _Tp>
1014 inline bool
1015 operator>=(nullptr_t, const shared_ptr<_Tp>& __a) noexcept
1016 { return !(nullptr < __a); }
1017
1018 // C++14 §20.8.2.2.8
1019 template<typename _Tp>
1020 inline void
1021 swap(shared_ptr<_Tp>& __a, shared_ptr<_Tp>& __b) noexcept
1022 { __a.swap(__b); }
1023
1024 // 8.2.1.3, shared_ptr casts
1025 template<typename _Tp, typename _Tp1>
1026 inline shared_ptr<_Tp>
1027 static_pointer_cast(const shared_ptr<_Tp1>& __r) noexcept
1028 {
1029 using __elem_t = typename shared_ptr<_Tp>::element_type;
1030 return shared_ptr<_Tp>(__r, static_cast<__elem_t*>(__r.get()));
1031 }
1032
1033 template<typename _Tp, typename _Tp1>
1034 inline shared_ptr<_Tp>
1035 dynamic_pointer_cast(const shared_ptr<_Tp1>& __r) noexcept
1036 {
1037 using __elem_t = typename shared_ptr<_Tp>::element_type;
1038 if (_Tp* __p = dynamic_cast<__elem_t*>(__r.get()))
1039 return shared_ptr<_Tp>(__r, __p);
1040 return shared_ptr<_Tp>();
1041 }
1042
1043 template<typename _Tp, typename _Tp1>
1044 inline shared_ptr<_Tp>
1045 const_pointer_cast(const shared_ptr<_Tp1>& __r) noexcept
1046 {
1047 using __elem_t = typename shared_ptr<_Tp>::element_type;
1048 return shared_ptr<_Tp>(__r, const_cast<__elem_t*>(__r.get()));
1049 }
1050
1051 template<typename _Tp, typename _Tp1>
1052 inline shared_ptr<_Tp>
1053 reinterpret_pointer_cast(const shared_ptr<_Tp1>& __r) noexcept
1054 {
1055 using __elem_t = typename shared_ptr<_Tp>::element_type;
1056 return shared_ptr<_Tp>(__r, reinterpret_cast<__elem_t*>(__r.get()));
1057 }
1058
1059 // C++14 §20.8.2.3
1060 template<typename _Tp>
1061 class weak_ptr : public __weak_ptr<_Tp>
1062 {
1063 template<typename _Tp1, typename _Res = void>
1064 using _Compatible = enable_if_t<__sp_compatible_v<_Tp1, _Tp>, _Res>;
1065
1066 using _Base_type = __weak_ptr<_Tp>;
1067
1068 public:
1069 constexpr weak_ptr() noexcept = default;
1070
1071 template<typename _Tp1, typename = _Compatible<_Tp1>>
1072 weak_ptr(const shared_ptr<_Tp1>& __r) noexcept
1073 : _Base_type(__r) { }
1074
1075 weak_ptr(const weak_ptr&) noexcept = default;
1076
1077 template<typename _Tp1, typename = _Compatible<_Tp1>>
1078 weak_ptr(const weak_ptr<_Tp1>& __r) noexcept
1079 : _Base_type(__r) { }
1080
1081 weak_ptr(weak_ptr&&) noexcept = default;
1082
1083 template<typename _Tp1, typename = _Compatible<_Tp1>>
1084 weak_ptr(weak_ptr<_Tp1>&& __r) noexcept
1085 : _Base_type(std::move(__r)) { }
1086
1087 weak_ptr&
1088 operator=(const weak_ptr& __r) noexcept = default;
1089
1090 template<typename _Tp1>
1091 _Compatible<_Tp1, weak_ptr&>
1092 operator=(const weak_ptr<_Tp1>& __r) noexcept
1093 {
1094 this->_Base_type::operator=(__r);
1095 return *this;
1096 }
1097
1098 template<typename _Tp1>
1099 _Compatible<_Tp1, weak_ptr&>
1100 operator=(const shared_ptr<_Tp1>& __r) noexcept
1101 {
1102 this->_Base_type::operator=(__r);
1103 return *this;
1104 }
1105
1106 weak_ptr&
1107 operator=(weak_ptr&& __r) noexcept = default;
1108
1109 template<typename _Tp1>
1110 _Compatible<_Tp1, weak_ptr&>
1111 operator=(weak_ptr<_Tp1>&& __r) noexcept
1112 {
1113 this->_Base_type::operator=(std::move(__r));
1114 return *this;
1115 }
1116
1117 shared_ptr<_Tp>
1118 lock() const noexcept
1119 { return shared_ptr<_Tp>(*this, std::nothrow); }
1120
1121 friend class enable_shared_from_this<_Tp>;
1122 };
1123
1124 // C++14 §20.8.2.3.6
1125 template<typename _Tp>
1126 inline void
1127 swap(weak_ptr<_Tp>& __a, weak_ptr<_Tp>& __b) noexcept
1128 { __a.swap(__b); }
1129
1130 /// C++14 §20.8.2.2.10
1131 template<typename _Del, typename _Tp, _Lock_policy _Lp>
1132 inline _Del*
1133 get_deleter(const __shared_ptr<_Tp, _Lp>& __p) noexcept
1134 { return std::get_deleter<_Del>(__p); }
1135
1136 // C++14 §20.8.2.2.11
1137 template<typename _Ch, typename _Tr, typename _Tp, _Lock_policy _Lp>
1139 operator<<(std::basic_ostream<_Ch, _Tr>& __os,
1140 const __shared_ptr<_Tp, _Lp>& __p)
1141 {
1142 __os << __p.get();
1143 return __os;
1144 }
1145
1146 // C++14 §20.8.2.4
1147 template<typename _Tp = void> class owner_less;
1148
1149 /// Partial specialization of owner_less for shared_ptr.
1150 template<typename _Tp>
1151 struct owner_less<shared_ptr<_Tp>>
1152 : public _Sp_owner_less<shared_ptr<_Tp>, weak_ptr<_Tp>>
1153 { };
1154
1155 /// Partial specialization of owner_less for weak_ptr.
1156 template<typename _Tp>
1157 struct owner_less<weak_ptr<_Tp>>
1158 : public _Sp_owner_less<weak_ptr<_Tp>, shared_ptr<_Tp>>
1159 { };
1160
1161 template<>
1162 class owner_less<void>
1163 {
1164 template<typename _Tp, typename _Up>
1165 bool
1166 operator()(shared_ptr<_Tp> const& __lhs,
1167 shared_ptr<_Up> const& __rhs) const
1168 { return __lhs.owner_before(__rhs); }
1169
1170 template<typename _Tp, typename _Up>
1171 bool
1172 operator()(shared_ptr<_Tp> const& __lhs,
1173 weak_ptr<_Up> const& __rhs) const
1174 { return __lhs.owner_before(__rhs); }
1175
1176 template<typename _Tp, typename _Up>
1177 bool
1178 operator()(weak_ptr<_Tp> const& __lhs,
1179 shared_ptr<_Up> const& __rhs) const
1180 { return __lhs.owner_before(__rhs); }
1181
1182 template<typename _Tp, typename _Up>
1183 bool
1184 operator()(weak_ptr<_Tp> const& __lhs,
1185 weak_ptr<_Up> const& __rhs) const
1186 { return __lhs.owner_before(__rhs); }
1187
1188 typedef void is_transparent;
1189 };
1190
1191 // C++14 §20.8.2.6
1192 template<typename _Tp>
1193 inline bool
1194 atomic_is_lock_free(const shared_ptr<_Tp>* __p)
1196
1197 template<typename _Tp>
1198 shared_ptr<_Tp> atomic_load(const shared_ptr<_Tp>* __p)
1199 { return std::atomic_load<_Tp>(__p); }
1200
1201 template<typename _Tp>
1202 shared_ptr<_Tp>
1203 atomic_load_explicit(const shared_ptr<_Tp>* __p, memory_order __mo)
1204 { return std::atomic_load_explicit<_Tp>(__p, __mo); }
1205
1206 template<typename _Tp>
1207 void atomic_store(shared_ptr<_Tp>* __p, shared_ptr<_Tp> __r)
1208 { return std::atomic_store<_Tp>(__p, __r); }
1209
1210 template<typename _Tp>
1211 shared_ptr<_Tp>
1212 atomic_store_explicit(const shared_ptr<_Tp>* __p,
1213 shared_ptr<_Tp> __r,
1214 memory_order __mo)
1215 { return std::atomic_store_explicit<_Tp>(__p, __r, __mo); }
1216
1217 template<typename _Tp>
1218 void atomic_exchange(shared_ptr<_Tp>* __p, shared_ptr<_Tp> __r)
1219 { return std::atomic_exchange<_Tp>(__p, __r); }
1220
1221 template<typename _Tp>
1222 shared_ptr<_Tp>
1223 atomic_exchange_explicit(const shared_ptr<_Tp>* __p,
1224 shared_ptr<_Tp> __r,
1225 memory_order __mo)
1226 { return std::atomic_exchange_explicit<_Tp>(__p, __r, __mo); }
1227
1228 template<typename _Tp>
1229 bool atomic_compare_exchange_weak(shared_ptr<_Tp>* __p,
1230 shared_ptr<_Tp>* __v,
1231 shared_ptr<_Tp> __w)
1232 { return std::atomic_compare_exchange_weak<_Tp>(__p, __v, __w); }
1233
1234 template<typename _Tp>
1235 bool atomic_compare_exchange_strong(shared_ptr<_Tp>* __p,
1236 shared_ptr<_Tp>* __v,
1237 shared_ptr<_Tp> __w)
1238 { return std::atomic_compare_exchange_strong<_Tp>(__p, __v, __w); }
1239
1240 template<typename _Tp>
1241 bool atomic_compare_exchange_weak_explicit(shared_ptr<_Tp>* __p,
1242 shared_ptr<_Tp>* __v,
1243 shared_ptr<_Tp> __w,
1244 memory_order __success,
1245 memory_order __failure)
1247 __success,
1248 __failure); }
1249
1250 template<typename _Tp>
1251 bool atomic_compare_exchange_strong_explicit(shared_ptr<_Tp>* __p,
1252 shared_ptr<_Tp>* __v,
1253 shared_ptr<_Tp> __w,
1254 memory_order __success,
1255 memory_order __failure)
1257 __success,
1258 __failure); }
1259
1260 //enable_shared_from_this
1261 template<typename _Tp>
1262 class enable_shared_from_this
1263 {
1264 protected:
1265 constexpr enable_shared_from_this() noexcept { }
1266
1267 enable_shared_from_this(const enable_shared_from_this&) noexcept { }
1268
1269 enable_shared_from_this&
1270 operator=(const enable_shared_from_this&) noexcept
1271 { return *this; }
1272
1273 ~enable_shared_from_this() { }
1274
1275 public:
1276 shared_ptr<_Tp>
1277 shared_from_this()
1278 { return shared_ptr<_Tp>(this->_M_weak_this); }
1279
1280 shared_ptr<const _Tp>
1281 shared_from_this() const
1282 { return shared_ptr<const _Tp>(this->_M_weak_this); }
1283
1284 weak_ptr<_Tp>
1285 weak_from_this() noexcept
1286 { return _M_weak_this; }
1287
1288 weak_ptr<const _Tp>
1289 weak_from_this() const noexcept
1290 { return _M_weak_this; }
1291
1292 private:
1293 template<typename _Tp1>
1294 void
1295 _M_weak_assign(_Tp1* __p, const __shared_count<>& __n) const noexcept
1296 { _M_weak_this._M_assign(__p, __n); }
1297
1298 // Found by ADL when this is an associated class.
1299 friend const enable_shared_from_this*
1300 __expt_enable_shared_from_this_base(const enable_shared_from_this* __p)
1301 { return __p; }
1302
1303 template<typename>
1304 friend class shared_ptr;
1305
1306 mutable weak_ptr<_Tp> _M_weak_this;
1307 };
1308
1309_GLIBCXX_END_NAMESPACE_VERSION
1310} // namespace fundamentals_v2
1311} // namespace experimental
1312
1313_GLIBCXX_BEGIN_NAMESPACE_VERSION
1314
1315 /// std::hash specialization for shared_ptr.
1316 template<typename _Tp>
1317 struct hash<experimental::shared_ptr<_Tp>>
1318 : public __hash_base<size_t, experimental::shared_ptr<_Tp>>
1319 {
1320 size_t
1321 operator()(const experimental::shared_ptr<_Tp>& __s) const noexcept
1322 { return std::hash<_Tp*>()(__s.get()); }
1323 };
1324
1325_GLIBCXX_END_NAMESPACE_VERSION
1326} // namespace std
1327
1328#endif // __cplusplus <= 201103L
1329
1330#endif // _GLIBCXX_EXPERIMENTAL_SHARED_PTR_H
_Del * get_deleter(const __shared_ptr< _Tp, _Lp > &__p) noexcept
20.7.2.2.10 shared_ptr get_deleter
shared_ptr< _Tp > allocate_shared(const _Alloc &__a, _Args &&... __args)
Create an object that is owned by a shared_ptr.
integral_constant< bool, true > true_type
The type used as a compile-time boolean with true value.
Definition type_traits:87
integral_constant< bool, false > false_type
The type used as a compile-time boolean with false value.
Definition type_traits:90
constexpr _Tp && forward(typename std::remove_reference< _Tp >::type &__t) noexcept
Forward an lvalue.
Definition move.h:76
memory_order
Enumeration for memory_order.
Definition atomic_base.h:56
ISO C++ entities toplevel namespace is std.
void lock(_L1 &__l1, _L2 &__l2, _L3 &... __l3)
Generic lock.
Definition mutex:540
Primary class template hash.
A smart pointer with reference-counted copy semantics.