1 // Experimental shared_ptr with array support -*- C++ -*-
3 // Copyright (C) 2015-2025 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 #ifdef _GLIBCXX_SYSHDR
34 #pragma GCC system_header
37 #if __cplusplus >= 201402L
40 #include <experimental/type_traits>
42 namespace std
_GLIBCXX_VISIBILITY(default)
44 _GLIBCXX_BEGIN_NAMESPACE_VERSION
46 namespace experimental
48 inline namespace fundamentals_v2
52 template<typename _Tp
> class shared_ptr
;
53 template<typename _Tp
> class weak_ptr
;
54 template<typename _Tp
> class enable_shared_from_this
;
56 template<typename _Yp
, typename _Tp
>
57 constexpr bool __sp_compatible_v
58 = std::__sp_compatible_with
<_Yp
*, _Tp
*>::value
;
60 template<typename _Tp
, typename _Yp
>
61 constexpr bool __sp_is_constructible_v
62 = std::__sp_is_constructible
<_Tp
, _Yp
>::value
;
64 template<typename _Tp
>
65 class shared_ptr
: public __shared_ptr
<_Tp
>
67 using _Base_type
= __shared_ptr
<_Tp
>;
70 using element_type
= typename
_Base_type::element_type
;
73 // Constraint for construction from a pointer of type _Yp*:
74 template<typename _Yp
>
75 using _SafeConv
= enable_if_t
<__sp_is_constructible_v
<_Tp
, _Yp
>>;
77 template<typename _Tp1
, typename _Res
= void>
79 = enable_if_t
<__sp_compatible_v
<_Tp1
, _Tp
>, _Res
>;
81 template<typename _Tp1
, typename _Del
,
82 typename _Ptr
= typename unique_ptr
<_Tp1
, _Del
>::pointer
,
84 using _UniqCompatible
= enable_if_t
<
85 __sp_compatible_v
<_Tp1
, _Tp
>
86 && experimental::is_convertible_v
<_Ptr
, element_type
*>,
91 // 8.2.1.1, shared_ptr constructors
92 constexpr shared_ptr() noexcept
= default;
94 template<typename _Tp1
, typename
= _SafeConv
<_Tp1
>>
96 shared_ptr(_Tp1
* __p
) : _Base_type(__p
)
97 { _M_enable_shared_from_this_with(__p
); }
99 template<typename _Tp1
, typename _Deleter
, typename
= _SafeConv
<_Tp1
>>
100 shared_ptr(_Tp1
* __p
, _Deleter __d
)
101 : _Base_type(__p
, __d
)
102 { _M_enable_shared_from_this_with(__p
); }
104 template<typename _Tp1
, typename _Deleter
, typename _Alloc
,
105 typename
= _SafeConv
<_Tp1
>>
106 shared_ptr(_Tp1
* __p
, _Deleter __d
, _Alloc __a
)
107 : _Base_type(__p
, __d
, __a
)
108 { _M_enable_shared_from_this_with(__p
); }
110 template<typename _Deleter
>
111 shared_ptr(nullptr_t __p
, _Deleter __d
)
112 : _Base_type(__p
, __d
) { }
114 template<typename _Deleter
, typename _Alloc
>
115 shared_ptr(nullptr_t __p
, _Deleter __d
, _Alloc __a
)
116 : _Base_type(__p
, __d
, __a
) { }
118 template<typename _Tp1
>
119 shared_ptr(const shared_ptr
<_Tp1
>& __r
, element_type
* __p
) noexcept
120 : _Base_type(__r
, __p
) { }
122 shared_ptr(const shared_ptr
& __r
) noexcept
123 : _Base_type(__r
) { }
125 template<typename _Tp1
, typename
= _Compatible
<_Tp1
>>
126 shared_ptr(const shared_ptr
<_Tp1
>& __r
) noexcept
127 : _Base_type(__r
) { }
129 shared_ptr(shared_ptr
&& __r
) noexcept
130 : _Base_type(std::move(__r
)) { }
132 template<typename _Tp1
, typename
= _Compatible
<_Tp1
>>
133 shared_ptr(shared_ptr
<_Tp1
>&& __r
) noexcept
134 : _Base_type(std::move(__r
)) { }
136 template<typename _Tp1
, typename
= _Compatible
<_Tp1
>>
138 shared_ptr(const weak_ptr
<_Tp1
>& __r
)
139 : _Base_type(__r
) { }
141 #if _GLIBCXX_USE_DEPRECATED
142 #pragma GCC diagnostic push
143 #pragma GCC diagnostic ignored "-Wdeprecated-declarations"
144 template<typename _Tp1
, typename
= _Compatible
<_Tp1
>>
145 shared_ptr(std::auto_ptr
<_Tp1
>&& __r
)
146 : _Base_type(std::move(__r
))
147 { _M_enable_shared_from_this_with(static_cast<_Tp1
*>(this->get())); }
148 #pragma GCC diagnostic pop
151 template<typename _Tp1
, typename _Del
,
152 typename
= _UniqCompatible
<_Tp1
, _Del
>>
153 shared_ptr(unique_ptr
<_Tp1
, _Del
>&& __r
)
154 : _Base_type(std::move(__r
))
156 // XXX assume conversion from __r.get() to this->get() to __elem_t*
157 // is a round trip, which might not be true in all cases.
158 using __elem_t
= typename unique_ptr
<_Tp1
, _Del
>::element_type
;
159 _M_enable_shared_from_this_with(static_cast<__elem_t
*>(this->get()));
162 constexpr shared_ptr(nullptr_t __p
)
163 : _Base_type(__p
) { }
166 ~shared_ptr() = default;
169 shared_ptr
& operator=(const shared_ptr
&) noexcept
= default;
171 template <typename _Tp1
>
172 _Compatible
<_Tp1
, shared_ptr
&>
173 operator=(const shared_ptr
<_Tp1
>& __r
) noexcept
175 _Base_type::operator=(__r
);
180 operator=(shared_ptr
&& __r
) noexcept
182 _Base_type::operator=(std::move(__r
));
186 template <typename _Tp1
>
187 _Compatible
<_Tp1
, shared_ptr
&>
188 operator=(shared_ptr
<_Tp1
>&& __r
) noexcept
190 _Base_type::operator=(std::move(__r
));
194 #if _GLIBCXX_USE_DEPRECATED
195 #pragma GCC diagnostic push
196 #pragma GCC diagnostic ignored "-Wdeprecated-declarations"
197 template<typename _Tp1
>
198 _Compatible
<_Tp1
, shared_ptr
&>
199 operator=(std::auto_ptr
<_Tp1
>&& __r
)
201 __shared_ptr
<_Tp
>::operator=(std::move(__r
));
204 #pragma GCC diagnostic pop
207 template <typename _Tp1
, typename _Del
>
208 _UniqCompatible
<_Tp1
, _Del
, shared_ptr
&>
209 operator=(unique_ptr
<_Tp1
, _Del
>&& __r
)
211 _Base_type::operator=(std::move(__r
));
217 // 8.2.1.2 shared_ptr observers
221 template<typename _Alloc
, typename
... _Args
>
222 shared_ptr(_Sp_make_shared_tag __tag
, const _Alloc
& __a
,
224 : _Base_type(__tag
, __a
, std::forward
<_Args
>(__args
)...)
225 { _M_enable_shared_from_this_with(this->get()); }
227 template<typename _Tp1
, typename _Alloc
, typename
... _Args
>
228 friend shared_ptr
<_Tp1
>
229 allocate_shared(const _Alloc
& __a
, _Args
&&... __args
);
231 shared_ptr(const weak_ptr
<_Tp
>& __r
, std::nothrow_t
)
232 : _Base_type(__r
, std::nothrow
) { }
234 friend class weak_ptr
<_Tp
>;
236 template<typename _Yp
>
237 using __esft_base_t
=
238 decltype(__expt_enable_shared_from_this_base(std::declval
<_Yp
*>()));
240 // Detect an accessible and unambiguous enable_shared_from_this base.
241 template<typename _Yp
, typename
= void>
242 struct __has_esft_base
245 template<typename _Yp
>
246 struct __has_esft_base
<_Yp
, __void_t
<__esft_base_t
<_Yp
>>>
247 : __bool_constant
<!is_array_v
<_Tp
>> { }; // ignore base for arrays
249 template<typename _Yp
>
250 typename enable_if
<__has_esft_base
<_Yp
>::value
>::type
251 _M_enable_shared_from_this_with(const _Yp
* __p
) noexcept
253 if (auto __base
= __expt_enable_shared_from_this_base(__p
))
256 = shared_ptr
<_Yp
>(*this, const_cast<_Yp
*>(__p
));
260 template<typename _Yp
>
261 typename enable_if
<!__has_esft_base
<_Yp
>::value
>::type
262 _M_enable_shared_from_this_with(const _Yp
*) noexcept
267 template<typename _Tp1
, typename _Tp2
>
268 bool operator==(const shared_ptr
<_Tp1
>& __a
,
269 const shared_ptr
<_Tp2
>& __b
) noexcept
270 { return __a
.get() == __b
.get(); }
272 template<typename _Tp
>
274 operator==(const shared_ptr
<_Tp
>& __a
, nullptr_t
) noexcept
277 template<typename _Tp
>
279 operator==(nullptr_t
, const shared_ptr
<_Tp
>& __a
) noexcept
282 template<typename _Tp1
, typename _Tp2
>
284 operator!=(const shared_ptr
<_Tp1
>& __a
,
285 const shared_ptr
<_Tp2
>& __b
) noexcept
286 { return __a
.get() != __b
.get(); }
288 template<typename _Tp
>
290 operator!=(const shared_ptr
<_Tp
>& __a
, nullptr_t
) noexcept
291 { return (bool)__a
; }
293 template<typename _Tp
>
295 operator!=(nullptr_t
, const shared_ptr
<_Tp
>& __a
) noexcept
296 { return (bool)__a
; }
298 template<typename _Tp1
, typename _Tp2
>
300 operator<(const shared_ptr
<_Tp1
>& __a
,
301 const shared_ptr
<_Tp2
>& __b
) noexcept
303 using __elem_t1
= typename shared_ptr
<_Tp1
>::element_type
;
304 using __elem_t2
= typename shared_ptr
<_Tp2
>::element_type
;
305 using _CT
= common_type_t
<__elem_t1
*, __elem_t2
*>;
306 return std::less
<_CT
>()(__a
.get(), __b
.get());
309 template<typename _Tp
>
311 operator<(const shared_ptr
<_Tp
>& __a
, nullptr_t
) noexcept
313 using __elem_t
= typename shared_ptr
<_Tp
>::element_type
;
314 return std::less
<__elem_t
*>()(__a
.get(), nullptr);
317 template<typename _Tp
>
319 operator<(nullptr_t
, const shared_ptr
<_Tp
>& __a
) noexcept
321 using __elem_t
= typename shared_ptr
<_Tp
>::element_type
;
322 return std::less
<__elem_t
*>()(nullptr, __a
.get());
325 template<typename _Tp1
, typename _Tp2
>
327 operator<=(const shared_ptr
<_Tp1
>& __a
,
328 const shared_ptr
<_Tp2
>& __b
) noexcept
329 { return !(__b
< __a
); }
331 template<typename _Tp
>
333 operator<=(const shared_ptr
<_Tp
>& __a
, nullptr_t
) noexcept
334 { return !(nullptr < __a
); }
336 template<typename _Tp
>
338 operator<=(nullptr_t
, const shared_ptr
<_Tp
>& __a
) noexcept
339 { return !(__a
< nullptr); }
341 template<typename _Tp1
, typename _Tp2
>
343 operator>(const shared_ptr
<_Tp1
>& __a
,
344 const shared_ptr
<_Tp2
>& __b
) noexcept
345 { return (__b
< __a
); }
347 template<typename _Tp
>
349 operator>(const shared_ptr
<_Tp
>& __a
, nullptr_t
) noexcept
351 using __elem_t
= typename shared_ptr
<_Tp
>::element_type
;
352 return std::less
<__elem_t
*>()(nullptr, __a
.get());
355 template<typename _Tp
>
357 operator>(nullptr_t
, const shared_ptr
<_Tp
>& __a
) noexcept
359 using __elem_t
= typename shared_ptr
<_Tp
>::element_type
;
360 return std::less
<__elem_t
*>()(__a
.get(), nullptr);
363 template<typename _Tp1
, typename _Tp2
>
365 operator>=(const shared_ptr
<_Tp1
>& __a
,
366 const shared_ptr
<_Tp2
>& __b
) noexcept
367 { return !(__a
< __b
); }
369 template<typename _Tp
>
371 operator>=(const shared_ptr
<_Tp
>& __a
, nullptr_t
) noexcept
372 { return !(__a
< nullptr); }
374 template<typename _Tp
>
376 operator>=(nullptr_t
, const shared_ptr
<_Tp
>& __a
) noexcept
377 { return !(nullptr < __a
); }
380 template<typename _Tp
>
382 swap(shared_ptr
<_Tp
>& __a
, shared_ptr
<_Tp
>& __b
) noexcept
385 // 8.2.1.3, shared_ptr casts
386 template<typename _Tp
, typename _Tp1
>
387 inline shared_ptr
<_Tp
>
388 static_pointer_cast(const shared_ptr
<_Tp1
>& __r
) noexcept
390 using __elem_t
= typename shared_ptr
<_Tp
>::element_type
;
391 return shared_ptr
<_Tp
>(__r
, static_cast<__elem_t
*>(__r
.get()));
394 template<typename _Tp
, typename _Tp1
>
395 inline shared_ptr
<_Tp
>
396 dynamic_pointer_cast(const shared_ptr
<_Tp1
>& __r
) noexcept
398 using __elem_t
= typename shared_ptr
<_Tp
>::element_type
;
399 if (_Tp
* __p
= dynamic_cast<__elem_t
*>(__r
.get()))
400 return shared_ptr
<_Tp
>(__r
, __p
);
401 return shared_ptr
<_Tp
>();
404 template<typename _Tp
, typename _Tp1
>
405 inline shared_ptr
<_Tp
>
406 const_pointer_cast(const shared_ptr
<_Tp1
>& __r
) noexcept
408 using __elem_t
= typename shared_ptr
<_Tp
>::element_type
;
409 return shared_ptr
<_Tp
>(__r
, const_cast<__elem_t
*>(__r
.get()));
412 template<typename _Tp
, typename _Tp1
>
413 inline shared_ptr
<_Tp
>
414 reinterpret_pointer_cast(const shared_ptr
<_Tp1
>& __r
) noexcept
416 using __elem_t
= typename shared_ptr
<_Tp
>::element_type
;
417 return shared_ptr
<_Tp
>(__r
, reinterpret_cast<__elem_t
*>(__r
.get()));
421 template<typename _Tp
>
422 class weak_ptr
: public __weak_ptr
<_Tp
>
424 template<typename _Tp1
, typename _Res
= void>
425 using _Compatible
= enable_if_t
<__sp_compatible_v
<_Tp1
, _Tp
>, _Res
>;
427 using _Base_type
= __weak_ptr
<_Tp
>;
430 constexpr weak_ptr() noexcept
= default;
432 template<typename _Tp1
, typename
= _Compatible
<_Tp1
>>
433 weak_ptr(const shared_ptr
<_Tp1
>& __r
) noexcept
434 : _Base_type(__r
) { }
436 weak_ptr(const weak_ptr
&) noexcept
= default;
438 template<typename _Tp1
, typename
= _Compatible
<_Tp1
>>
439 weak_ptr(const weak_ptr
<_Tp1
>& __r
) noexcept
440 : _Base_type(__r
) { }
442 weak_ptr(weak_ptr
&&) noexcept
= default;
444 template<typename _Tp1
, typename
= _Compatible
<_Tp1
>>
445 weak_ptr(weak_ptr
<_Tp1
>&& __r
) noexcept
446 : _Base_type(std::move(__r
)) { }
449 operator=(const weak_ptr
& __r
) noexcept
= default;
451 template<typename _Tp1
>
452 _Compatible
<_Tp1
, weak_ptr
&>
453 operator=(const weak_ptr
<_Tp1
>& __r
) noexcept
455 this->_Base_type::operator=(__r
);
459 template<typename _Tp1
>
460 _Compatible
<_Tp1
, weak_ptr
&>
461 operator=(const shared_ptr
<_Tp1
>& __r
) noexcept
463 this->_Base_type::operator=(__r
);
468 operator=(weak_ptr
&& __r
) noexcept
= default;
470 template<typename _Tp1
>
471 _Compatible
<_Tp1
, weak_ptr
&>
472 operator=(weak_ptr
<_Tp1
>&& __r
) noexcept
474 this->_Base_type::operator=(std::move(__r
));
479 lock() const noexcept
480 { return shared_ptr
<_Tp
>(*this, std::nothrow
); }
482 friend class enable_shared_from_this
<_Tp
>;
486 template<typename _Tp
>
488 swap(weak_ptr
<_Tp
>& __a
, weak_ptr
<_Tp
>& __b
) noexcept
491 /// C++14 20.8.2.2.10
492 template<typename _Del
, typename _Tp
>
494 get_deleter(const shared_ptr
<_Tp
>& __p
) noexcept
495 { return std::get_deleter
<_Del
>(__p
); }
498 template<typename _Ch
, typename _Tr
, typename _Tp
>
499 inline std::basic_ostream
<_Ch
, _Tr
>&
500 operator<<(std::basic_ostream
<_Ch
, _Tr
>& __os
, const shared_ptr
<_Tp
>& __p
)
507 template<typename _Tp
= void> class owner_less
;
509 /// Partial specialization of owner_less for shared_ptr.
510 template<typename _Tp
>
511 struct owner_less
<shared_ptr
<_Tp
>>
512 : public _Sp_owner_less
<shared_ptr
<_Tp
>, weak_ptr
<_Tp
>>
515 /// Partial specialization of owner_less for weak_ptr.
516 template<typename _Tp
>
517 struct owner_less
<weak_ptr
<_Tp
>>
518 : public _Sp_owner_less
<weak_ptr
<_Tp
>, shared_ptr
<_Tp
>>
522 class owner_less
<void>
524 template<typename _Tp
, typename _Up
>
526 operator()(shared_ptr
<_Tp
> const& __lhs
,
527 shared_ptr
<_Up
> const& __rhs
) const
528 { return __lhs
.owner_before(__rhs
); }
530 template<typename _Tp
, typename _Up
>
532 operator()(shared_ptr
<_Tp
> const& __lhs
,
533 weak_ptr
<_Up
> const& __rhs
) const
534 { return __lhs
.owner_before(__rhs
); }
536 template<typename _Tp
, typename _Up
>
538 operator()(weak_ptr
<_Tp
> const& __lhs
,
539 shared_ptr
<_Up
> const& __rhs
) const
540 { return __lhs
.owner_before(__rhs
); }
542 template<typename _Tp
, typename _Up
>
544 operator()(weak_ptr
<_Tp
> const& __lhs
,
545 weak_ptr
<_Up
> const& __rhs
) const
546 { return __lhs
.owner_before(__rhs
); }
548 typedef void is_transparent
;
552 template<typename _Tp
>
554 atomic_is_lock_free(const shared_ptr
<_Tp
>* __p
)
555 { return std::atomic_is_lock_free
<_Tp
, __default_lock_policy
>(__p
); }
557 template<typename _Tp
>
558 shared_ptr
<_Tp
> atomic_load(const shared_ptr
<_Tp
>* __p
)
559 { return std::atomic_load
<_Tp
>(__p
); }
561 template<typename _Tp
>
563 atomic_load_explicit(const shared_ptr
<_Tp
>* __p
, memory_order __mo
)
564 { return std::atomic_load_explicit
<_Tp
>(__p
, __mo
); }
566 template<typename _Tp
>
567 void atomic_store(shared_ptr
<_Tp
>* __p
, shared_ptr
<_Tp
> __r
)
568 { return std::atomic_store
<_Tp
>(__p
, __r
); }
570 template<typename _Tp
>
572 atomic_store_explicit(const shared_ptr
<_Tp
>* __p
,
575 { return std::atomic_store_explicit
<_Tp
>(__p
, __r
, __mo
); }
577 template<typename _Tp
>
578 void atomic_exchange(shared_ptr
<_Tp
>* __p
, shared_ptr
<_Tp
> __r
)
579 { return std::atomic_exchange
<_Tp
>(__p
, __r
); }
581 template<typename _Tp
>
583 atomic_exchange_explicit(const shared_ptr
<_Tp
>* __p
,
586 { return std::atomic_exchange_explicit
<_Tp
>(__p
, __r
, __mo
); }
588 template<typename _Tp
>
589 bool atomic_compare_exchange_weak(shared_ptr
<_Tp
>* __p
,
590 shared_ptr
<_Tp
>* __v
,
592 { return std::atomic_compare_exchange_weak
<_Tp
>(__p
, __v
, __w
); }
594 template<typename _Tp
>
595 bool atomic_compare_exchange_strong(shared_ptr
<_Tp
>* __p
,
596 shared_ptr
<_Tp
>* __v
,
598 { return std::atomic_compare_exchange_strong
<_Tp
>(__p
, __v
, __w
); }
600 template<typename _Tp
>
601 bool atomic_compare_exchange_weak_explicit(shared_ptr
<_Tp
>* __p
,
602 shared_ptr
<_Tp
>* __v
,
604 memory_order __success
,
605 memory_order __failure
)
606 { return std::atomic_compare_exchange_weak_explicit
<_Tp
>(__p
, __v
, __w
,
610 template<typename _Tp
>
611 bool atomic_compare_exchange_strong_explicit(shared_ptr
<_Tp
>* __p
,
612 shared_ptr
<_Tp
>* __v
,
614 memory_order __success
,
615 memory_order __failure
)
616 { return std::atomic_compare_exchange_strong_explicit
<_Tp
>(__p
, __v
, __w
,
620 //enable_shared_from_this
621 template<typename _Tp
>
622 class enable_shared_from_this
625 constexpr enable_shared_from_this() noexcept
{ }
627 enable_shared_from_this(const enable_shared_from_this
&) noexcept
{ }
629 enable_shared_from_this
&
630 operator=(const enable_shared_from_this
&) noexcept
633 ~enable_shared_from_this() { }
638 { return shared_ptr
<_Tp
>(this->_M_weak_this
); }
640 shared_ptr
<const _Tp
>
641 shared_from_this() const
642 { return shared_ptr
<const _Tp
>(this->_M_weak_this
); }
645 weak_from_this() noexcept
646 { return _M_weak_this
; }
649 weak_from_this() const noexcept
650 { return _M_weak_this
; }
653 template<typename _Tp1
>
655 _M_weak_assign(_Tp1
* __p
, const __shared_count
<>& __n
) const noexcept
656 { _M_weak_this
._M_assign(__p
, __n
); }
658 // Found by ADL when this is an associated class.
659 friend const enable_shared_from_this
*
660 __expt_enable_shared_from_this_base(const enable_shared_from_this
* __p
)
664 friend class shared_ptr
;
666 mutable weak_ptr
<_Tp
> _M_weak_this
;
668 } // namespace fundamentals_v2
669 } // namespace experimental
671 /// std::hash specialization for shared_ptr.
672 template<typename _Tp
>
673 struct hash
<experimental::shared_ptr
<_Tp
>>
674 : public __hash_base
<size_t, experimental::shared_ptr
<_Tp
>>
677 operator()(const experimental::shared_ptr
<_Tp
>& __s
) const noexcept
678 { return std::hash
<_Tp
*>()(__s
.get()); }
681 _GLIBCXX_END_NAMESPACE_VERSION
684 #endif // __cplusplus <= 201103L
686 #endif // _GLIBCXX_EXPERIMENTAL_SHARED_PTR_H