1 // Experimental shared_ptr with array support -*- C++ -*-
3 // Copyright (C) 2015-2021 Free Software Foundation, Inc.
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)
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.
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.
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/>.
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}
30 #ifndef _GLIBCXX_EXPERIMENTAL_SHARED_PTR_H
31 #define _GLIBCXX_EXPERIMENTAL_SHARED_PTR_H 1
33 #pragma GCC system_header
35 #if __cplusplus >= 201402L
38 #include <experimental/type_traits>
40 namespace std
_GLIBCXX_VISIBILITY(default)
42 _GLIBCXX_BEGIN_NAMESPACE_VERSION
44 namespace experimental
46 inline namespace fundamentals_v2
50 template<typename _Tp
> class shared_ptr
;
51 template<typename _Tp
> class weak_ptr
;
52 template<typename _Tp
> class enable_shared_from_this
;
54 template<typename _Yp
, typename _Tp
>
55 constexpr bool __sp_compatible_v
56 = std::__sp_compatible_with
<_Yp
*, _Tp
*>::value
;
58 template<typename _Tp
, typename _Yp
>
59 constexpr bool __sp_is_constructible_v
60 = std::__sp_is_constructible
<_Tp
, _Yp
>::value
;
62 template<typename _Tp
>
63 class shared_ptr
: public __shared_ptr
<_Tp
>
65 using _Base_type
= __shared_ptr
<_Tp
>;
68 using element_type
= typename
_Base_type::element_type
;
71 // Constraint for construction from a pointer of type _Yp*:
72 template<typename _Yp
>
73 using _SafeConv
= enable_if_t
<__sp_is_constructible_v
<_Tp
, _Yp
>>;
75 template<typename _Tp1
, typename _Res
= void>
77 = enable_if_t
<__sp_compatible_v
<_Tp1
, _Tp
>, _Res
>;
79 template<typename _Tp1
, typename _Del
,
80 typename _Ptr
= typename unique_ptr
<_Tp1
, _Del
>::pointer
,
82 using _UniqCompatible
= enable_if_t
<
83 __sp_compatible_v
<_Tp1
, _Tp
>
84 && experimental::is_convertible_v
<_Ptr
, element_type
*>,
89 // 8.2.1.1, shared_ptr constructors
90 constexpr shared_ptr() noexcept
= default;
92 template<typename _Tp1
, typename
= _SafeConv
<_Tp1
>>
94 shared_ptr(_Tp1
* __p
) : _Base_type(__p
)
95 { _M_enable_shared_from_this_with(__p
); }
97 template<typename _Tp1
, typename _Deleter
, typename
= _SafeConv
<_Tp1
>>
98 shared_ptr(_Tp1
* __p
, _Deleter __d
)
99 : _Base_type(__p
, __d
)
100 { _M_enable_shared_from_this_with(__p
); }
102 template<typename _Tp1
, typename _Deleter
, typename _Alloc
,
103 typename
= _SafeConv
<_Tp1
>>
104 shared_ptr(_Tp1
* __p
, _Deleter __d
, _Alloc __a
)
105 : _Base_type(__p
, __d
, __a
)
106 { _M_enable_shared_from_this_with(__p
); }
108 template<typename _Deleter
>
109 shared_ptr(nullptr_t __p
, _Deleter __d
)
110 : _Base_type(__p
, __d
) { }
112 template<typename _Deleter
, typename _Alloc
>
113 shared_ptr(nullptr_t __p
, _Deleter __d
, _Alloc __a
)
114 : _Base_type(__p
, __d
, __a
) { }
116 template<typename _Tp1
>
117 shared_ptr(const shared_ptr
<_Tp1
>& __r
, element_type
* __p
) noexcept
118 : _Base_type(__r
, __p
) { }
120 shared_ptr(const shared_ptr
& __r
) noexcept
121 : _Base_type(__r
) { }
123 template<typename _Tp1
, typename
= _Compatible
<_Tp1
>>
124 shared_ptr(const shared_ptr
<_Tp1
>& __r
) noexcept
125 : _Base_type(__r
) { }
127 shared_ptr(shared_ptr
&& __r
) noexcept
128 : _Base_type(std::move(__r
)) { }
130 template<typename _Tp1
, typename
= _Compatible
<_Tp1
>>
131 shared_ptr(shared_ptr
<_Tp1
>&& __r
) noexcept
132 : _Base_type(std::move(__r
)) { }
134 template<typename _Tp1
, typename
= _Compatible
<_Tp1
>>
136 shared_ptr(const weak_ptr
<_Tp1
>& __r
)
137 : _Base_type(__r
) { }
139 #if _GLIBCXX_USE_DEPRECATED
140 #pragma GCC diagnostic push
141 #pragma GCC diagnostic ignored "-Wdeprecated-declarations"
142 template<typename _Tp1
, typename
= _Compatible
<_Tp1
>>
143 shared_ptr(std::auto_ptr
<_Tp1
>&& __r
)
144 : _Base_type(std::move(__r
))
145 { _M_enable_shared_from_this_with(static_cast<_Tp1
*>(this->get())); }
146 #pragma GCC diagnostic pop
149 template<typename _Tp1
, typename _Del
,
150 typename
= _UniqCompatible
<_Tp1
, _Del
>>
151 shared_ptr(unique_ptr
<_Tp1
, _Del
>&& __r
)
152 : _Base_type(std::move(__r
))
154 // XXX assume conversion from __r.get() to this->get() to __elem_t*
155 // is a round trip, which might not be true in all cases.
156 using __elem_t
= typename unique_ptr
<_Tp1
, _Del
>::element_type
;
157 _M_enable_shared_from_this_with(static_cast<__elem_t
*>(this->get()));
160 constexpr shared_ptr(nullptr_t __p
)
161 : _Base_type(__p
) { }
164 ~shared_ptr() = default;
167 shared_ptr
& operator=(const shared_ptr
&) noexcept
= default;
169 template <typename _Tp1
>
170 _Compatible
<_Tp1
, shared_ptr
&>
171 operator=(const shared_ptr
<_Tp1
>& __r
) noexcept
173 _Base_type::operator=(__r
);
178 operator=(shared_ptr
&& __r
) noexcept
180 _Base_type::operator=(std::move(__r
));
184 template <typename _Tp1
>
185 _Compatible
<_Tp1
, shared_ptr
&>
186 operator=(shared_ptr
<_Tp1
>&& __r
) noexcept
188 _Base_type::operator=(std::move(__r
));
192 #if _GLIBCXX_USE_DEPRECATED
193 #pragma GCC diagnostic push
194 #pragma GCC diagnostic ignored "-Wdeprecated-declarations"
195 template<typename _Tp1
>
196 _Compatible
<_Tp1
, shared_ptr
&>
197 operator=(std::auto_ptr
<_Tp1
>&& __r
)
199 __shared_ptr
<_Tp
>::operator=(std::move(__r
));
202 #pragma GCC diagnostic pop
205 template <typename _Tp1
, typename _Del
>
206 _UniqCompatible
<_Tp1
, _Del
, shared_ptr
&>
207 operator=(unique_ptr
<_Tp1
, _Del
>&& __r
)
209 _Base_type::operator=(std::move(__r
));
215 // 8.2.1.2 shared_ptr observers
219 template<typename _Alloc
, typename
... _Args
>
220 shared_ptr(_Sp_make_shared_tag __tag
, const _Alloc
& __a
,
222 : _Base_type(__tag
, __a
, std::forward
<_Args
>(__args
)...)
223 { _M_enable_shared_from_this_with(this->get()); }
225 template<typename _Tp1
, typename _Alloc
, typename
... _Args
>
226 friend shared_ptr
<_Tp1
>
227 allocate_shared(const _Alloc
& __a
, _Args
&&... __args
);
229 shared_ptr(const weak_ptr
<_Tp
>& __r
, std::nothrow_t
)
230 : _Base_type(__r
, std::nothrow
) { }
232 friend class weak_ptr
<_Tp
>;
234 template<typename _Yp
>
235 using __esft_base_t
=
236 decltype(__expt_enable_shared_from_this_base(std::declval
<_Yp
*>()));
238 // Detect an accessible and unambiguous enable_shared_from_this base.
239 template<typename _Yp
, typename
= void>
240 struct __has_esft_base
243 template<typename _Yp
>
244 struct __has_esft_base
<_Yp
, __void_t
<__esft_base_t
<_Yp
>>>
245 : __bool_constant
<!is_array_v
<_Tp
>> { }; // ignore base for arrays
247 template<typename _Yp
>
248 typename enable_if
<__has_esft_base
<_Yp
>::value
>::type
249 _M_enable_shared_from_this_with(const _Yp
* __p
) noexcept
251 if (auto __base
= __expt_enable_shared_from_this_base(__p
))
254 = shared_ptr
<_Yp
>(*this, const_cast<_Yp
*>(__p
));
258 template<typename _Yp
>
259 typename enable_if
<!__has_esft_base
<_Yp
>::value
>::type
260 _M_enable_shared_from_this_with(const _Yp
*) noexcept
265 template<typename _Tp1
, typename _Tp2
>
266 bool operator==(const shared_ptr
<_Tp1
>& __a
,
267 const shared_ptr
<_Tp2
>& __b
) noexcept
268 { return __a
.get() == __b
.get(); }
270 template<typename _Tp
>
272 operator==(const shared_ptr
<_Tp
>& __a
, nullptr_t
) noexcept
275 template<typename _Tp
>
277 operator==(nullptr_t
, const shared_ptr
<_Tp
>& __a
) noexcept
280 template<typename _Tp1
, typename _Tp2
>
282 operator!=(const shared_ptr
<_Tp1
>& __a
,
283 const shared_ptr
<_Tp2
>& __b
) noexcept
284 { return __a
.get() != __b
.get(); }
286 template<typename _Tp
>
288 operator!=(const shared_ptr
<_Tp
>& __a
, nullptr_t
) noexcept
289 { return (bool)__a
; }
291 template<typename _Tp
>
293 operator!=(nullptr_t
, const shared_ptr
<_Tp
>& __a
) noexcept
294 { return (bool)__a
; }
296 template<typename _Tp1
, typename _Tp2
>
298 operator<(const shared_ptr
<_Tp1
>& __a
,
299 const shared_ptr
<_Tp2
>& __b
) noexcept
301 using __elem_t1
= typename shared_ptr
<_Tp1
>::element_type
;
302 using __elem_t2
= typename shared_ptr
<_Tp2
>::element_type
;
303 using _CT
= common_type_t
<__elem_t1
*, __elem_t2
*>;
304 return std::less
<_CT
>()(__a
.get(), __b
.get());
307 template<typename _Tp
>
309 operator<(const shared_ptr
<_Tp
>& __a
, nullptr_t
) noexcept
311 using __elem_t
= typename shared_ptr
<_Tp
>::element_type
;
312 return std::less
<__elem_t
*>()(__a
.get(), nullptr);
315 template<typename _Tp
>
317 operator<(nullptr_t
, const shared_ptr
<_Tp
>& __a
) noexcept
319 using __elem_t
= typename shared_ptr
<_Tp
>::element_type
;
320 return std::less
<__elem_t
*>()(nullptr, __a
.get());
323 template<typename _Tp1
, typename _Tp2
>
325 operator<=(const shared_ptr
<_Tp1
>& __a
,
326 const shared_ptr
<_Tp2
>& __b
) noexcept
327 { return !(__b
< __a
); }
329 template<typename _Tp
>
331 operator<=(const shared_ptr
<_Tp
>& __a
, nullptr_t
) noexcept
332 { return !(nullptr < __a
); }
334 template<typename _Tp
>
336 operator<=(nullptr_t
, const shared_ptr
<_Tp
>& __a
) noexcept
337 { return !(__a
< nullptr); }
339 template<typename _Tp1
, typename _Tp2
>
341 operator>(const shared_ptr
<_Tp1
>& __a
,
342 const shared_ptr
<_Tp2
>& __b
) noexcept
343 { return (__b
< __a
); }
345 template<typename _Tp
>
347 operator>(const shared_ptr
<_Tp
>& __a
, nullptr_t
) noexcept
349 using __elem_t
= typename shared_ptr
<_Tp
>::element_type
;
350 return std::less
<__elem_t
*>()(nullptr, __a
.get());
353 template<typename _Tp
>
355 operator>(nullptr_t
, const shared_ptr
<_Tp
>& __a
) noexcept
357 using __elem_t
= typename shared_ptr
<_Tp
>::element_type
;
358 return std::less
<__elem_t
*>()(__a
.get(), nullptr);
361 template<typename _Tp1
, typename _Tp2
>
363 operator>=(const shared_ptr
<_Tp1
>& __a
,
364 const shared_ptr
<_Tp2
>& __b
) noexcept
365 { return !(__a
< __b
); }
367 template<typename _Tp
>
369 operator>=(const shared_ptr
<_Tp
>& __a
, nullptr_t
) noexcept
370 { return !(__a
< nullptr); }
372 template<typename _Tp
>
374 operator>=(nullptr_t
, const shared_ptr
<_Tp
>& __a
) noexcept
375 { return !(nullptr < __a
); }
378 template<typename _Tp
>
380 swap(shared_ptr
<_Tp
>& __a
, shared_ptr
<_Tp
>& __b
) noexcept
383 // 8.2.1.3, shared_ptr casts
384 template<typename _Tp
, typename _Tp1
>
385 inline shared_ptr
<_Tp
>
386 static_pointer_cast(const shared_ptr
<_Tp1
>& __r
) noexcept
388 using __elem_t
= typename shared_ptr
<_Tp
>::element_type
;
389 return shared_ptr
<_Tp
>(__r
, static_cast<__elem_t
*>(__r
.get()));
392 template<typename _Tp
, typename _Tp1
>
393 inline shared_ptr
<_Tp
>
394 dynamic_pointer_cast(const shared_ptr
<_Tp1
>& __r
) noexcept
396 using __elem_t
= typename shared_ptr
<_Tp
>::element_type
;
397 if (_Tp
* __p
= dynamic_cast<__elem_t
*>(__r
.get()))
398 return shared_ptr
<_Tp
>(__r
, __p
);
399 return shared_ptr
<_Tp
>();
402 template<typename _Tp
, typename _Tp1
>
403 inline shared_ptr
<_Tp
>
404 const_pointer_cast(const shared_ptr
<_Tp1
>& __r
) noexcept
406 using __elem_t
= typename shared_ptr
<_Tp
>::element_type
;
407 return shared_ptr
<_Tp
>(__r
, const_cast<__elem_t
*>(__r
.get()));
410 template<typename _Tp
, typename _Tp1
>
411 inline shared_ptr
<_Tp
>
412 reinterpret_pointer_cast(const shared_ptr
<_Tp1
>& __r
) noexcept
414 using __elem_t
= typename shared_ptr
<_Tp
>::element_type
;
415 return shared_ptr
<_Tp
>(__r
, reinterpret_cast<__elem_t
*>(__r
.get()));
419 template<typename _Tp
>
420 class weak_ptr
: public __weak_ptr
<_Tp
>
422 template<typename _Tp1
, typename _Res
= void>
423 using _Compatible
= enable_if_t
<__sp_compatible_v
<_Tp1
, _Tp
>, _Res
>;
425 using _Base_type
= __weak_ptr
<_Tp
>;
428 constexpr weak_ptr() noexcept
= default;
430 template<typename _Tp1
, typename
= _Compatible
<_Tp1
>>
431 weak_ptr(const shared_ptr
<_Tp1
>& __r
) noexcept
432 : _Base_type(__r
) { }
434 weak_ptr(const weak_ptr
&) noexcept
= default;
436 template<typename _Tp1
, typename
= _Compatible
<_Tp1
>>
437 weak_ptr(const weak_ptr
<_Tp1
>& __r
) noexcept
438 : _Base_type(__r
) { }
440 weak_ptr(weak_ptr
&&) noexcept
= default;
442 template<typename _Tp1
, typename
= _Compatible
<_Tp1
>>
443 weak_ptr(weak_ptr
<_Tp1
>&& __r
) noexcept
444 : _Base_type(std::move(__r
)) { }
447 operator=(const weak_ptr
& __r
) noexcept
= default;
449 template<typename _Tp1
>
450 _Compatible
<_Tp1
, weak_ptr
&>
451 operator=(const weak_ptr
<_Tp1
>& __r
) noexcept
453 this->_Base_type::operator=(__r
);
457 template<typename _Tp1
>
458 _Compatible
<_Tp1
, weak_ptr
&>
459 operator=(const shared_ptr
<_Tp1
>& __r
) noexcept
461 this->_Base_type::operator=(__r
);
466 operator=(weak_ptr
&& __r
) noexcept
= default;
468 template<typename _Tp1
>
469 _Compatible
<_Tp1
, weak_ptr
&>
470 operator=(weak_ptr
<_Tp1
>&& __r
) noexcept
472 this->_Base_type::operator=(std::move(__r
));
477 lock() const noexcept
478 { return shared_ptr
<_Tp
>(*this, std::nothrow
); }
480 friend class enable_shared_from_this
<_Tp
>;
484 template<typename _Tp
>
486 swap(weak_ptr
<_Tp
>& __a
, weak_ptr
<_Tp
>& __b
) noexcept
489 /// C++14 20.8.2.2.10
490 template<typename _Del
, typename _Tp
>
492 get_deleter(const shared_ptr
<_Tp
>& __p
) noexcept
493 { return std::get_deleter
<_Del
>(__p
); }
496 template<typename _Ch
, typename _Tr
, typename _Tp
>
497 inline std::basic_ostream
<_Ch
, _Tr
>&
498 operator<<(std::basic_ostream
<_Ch
, _Tr
>& __os
, const shared_ptr
<_Tp
>& __p
)
505 template<typename _Tp
= void> class owner_less
;
507 /// Partial specialization of owner_less for shared_ptr.
508 template<typename _Tp
>
509 struct owner_less
<shared_ptr
<_Tp
>>
510 : public _Sp_owner_less
<shared_ptr
<_Tp
>, weak_ptr
<_Tp
>>
513 /// Partial specialization of owner_less for weak_ptr.
514 template<typename _Tp
>
515 struct owner_less
<weak_ptr
<_Tp
>>
516 : public _Sp_owner_less
<weak_ptr
<_Tp
>, shared_ptr
<_Tp
>>
520 class owner_less
<void>
522 template<typename _Tp
, typename _Up
>
524 operator()(shared_ptr
<_Tp
> const& __lhs
,
525 shared_ptr
<_Up
> const& __rhs
) const
526 { return __lhs
.owner_before(__rhs
); }
528 template<typename _Tp
, typename _Up
>
530 operator()(shared_ptr
<_Tp
> const& __lhs
,
531 weak_ptr
<_Up
> const& __rhs
) const
532 { return __lhs
.owner_before(__rhs
); }
534 template<typename _Tp
, typename _Up
>
536 operator()(weak_ptr
<_Tp
> const& __lhs
,
537 shared_ptr
<_Up
> const& __rhs
) const
538 { return __lhs
.owner_before(__rhs
); }
540 template<typename _Tp
, typename _Up
>
542 operator()(weak_ptr
<_Tp
> const& __lhs
,
543 weak_ptr
<_Up
> const& __rhs
) const
544 { return __lhs
.owner_before(__rhs
); }
546 typedef void is_transparent
;
550 template<typename _Tp
>
552 atomic_is_lock_free(const shared_ptr
<_Tp
>* __p
)
553 { return std::atomic_is_lock_free
<_Tp
, __default_lock_policy
>(__p
); }
555 template<typename _Tp
>
556 shared_ptr
<_Tp
> atomic_load(const shared_ptr
<_Tp
>* __p
)
557 { return std::atomic_load
<_Tp
>(__p
); }
559 template<typename _Tp
>
561 atomic_load_explicit(const shared_ptr
<_Tp
>* __p
, memory_order __mo
)
562 { return std::atomic_load_explicit
<_Tp
>(__p
, __mo
); }
564 template<typename _Tp
>
565 void atomic_store(shared_ptr
<_Tp
>* __p
, shared_ptr
<_Tp
> __r
)
566 { return std::atomic_store
<_Tp
>(__p
, __r
); }
568 template<typename _Tp
>
570 atomic_store_explicit(const shared_ptr
<_Tp
>* __p
,
573 { return std::atomic_store_explicit
<_Tp
>(__p
, __r
, __mo
); }
575 template<typename _Tp
>
576 void atomic_exchange(shared_ptr
<_Tp
>* __p
, shared_ptr
<_Tp
> __r
)
577 { return std::atomic_exchange
<_Tp
>(__p
, __r
); }
579 template<typename _Tp
>
581 atomic_exchange_explicit(const shared_ptr
<_Tp
>* __p
,
584 { return std::atomic_exchange_explicit
<_Tp
>(__p
, __r
, __mo
); }
586 template<typename _Tp
>
587 bool atomic_compare_exchange_weak(shared_ptr
<_Tp
>* __p
,
588 shared_ptr
<_Tp
>* __v
,
590 { return std::atomic_compare_exchange_weak
<_Tp
>(__p
, __v
, __w
); }
592 template<typename _Tp
>
593 bool atomic_compare_exchange_strong(shared_ptr
<_Tp
>* __p
,
594 shared_ptr
<_Tp
>* __v
,
596 { return std::atomic_compare_exchange_strong
<_Tp
>(__p
, __v
, __w
); }
598 template<typename _Tp
>
599 bool atomic_compare_exchange_weak_explicit(shared_ptr
<_Tp
>* __p
,
600 shared_ptr
<_Tp
>* __v
,
602 memory_order __success
,
603 memory_order __failure
)
604 { return std::atomic_compare_exchange_weak_explicit
<_Tp
>(__p
, __v
, __w
,
608 template<typename _Tp
>
609 bool atomic_compare_exchange_strong_explicit(shared_ptr
<_Tp
>* __p
,
610 shared_ptr
<_Tp
>* __v
,
612 memory_order __success
,
613 memory_order __failure
)
614 { return std::atomic_compare_exchange_strong_explicit
<_Tp
>(__p
, __v
, __w
,
618 //enable_shared_from_this
619 template<typename _Tp
>
620 class enable_shared_from_this
623 constexpr enable_shared_from_this() noexcept
{ }
625 enable_shared_from_this(const enable_shared_from_this
&) noexcept
{ }
627 enable_shared_from_this
&
628 operator=(const enable_shared_from_this
&) noexcept
631 ~enable_shared_from_this() { }
636 { return shared_ptr
<_Tp
>(this->_M_weak_this
); }
638 shared_ptr
<const _Tp
>
639 shared_from_this() const
640 { return shared_ptr
<const _Tp
>(this->_M_weak_this
); }
643 weak_from_this() noexcept
644 { return _M_weak_this
; }
647 weak_from_this() const noexcept
648 { return _M_weak_this
; }
651 template<typename _Tp1
>
653 _M_weak_assign(_Tp1
* __p
, const __shared_count
<>& __n
) const noexcept
654 { _M_weak_this
._M_assign(__p
, __n
); }
656 // Found by ADL when this is an associated class.
657 friend const enable_shared_from_this
*
658 __expt_enable_shared_from_this_base(const enable_shared_from_this
* __p
)
662 friend class shared_ptr
;
664 mutable weak_ptr
<_Tp
> _M_weak_this
;
666 } // namespace fundamentals_v2
667 } // namespace experimental
669 /// std::hash specialization for shared_ptr.
670 template<typename _Tp
>
671 struct hash
<experimental::shared_ptr
<_Tp
>>
672 : public __hash_base
<size_t, experimental::shared_ptr
<_Tp
>>
675 operator()(const experimental::shared_ptr
<_Tp
>& __s
) const noexcept
676 { return std::hash
<_Tp
*>()(__s
.get()); }
679 _GLIBCXX_END_NAMESPACE_VERSION
682 #endif // __cplusplus <= 201103L
684 #endif // _GLIBCXX_EXPERIMENTAL_SHARED_PTR_H