1 // Experimental shared_ptr with array support -*- C++ -*-
3 // Copyright (C) 2015-2019 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 template<typename _Tp1
, typename
= _Compatible
<_Tp1
>>
141 shared_ptr(std::auto_ptr
<_Tp1
>&& __r
)
142 : _Base_type(std::move(__r
))
143 { _M_enable_shared_from_this_with(static_cast<_Tp1
*>(this->get())); }
146 template<typename _Tp1
, typename _Del
,
147 typename
= _UniqCompatible
<_Tp1
, _Del
>>
148 shared_ptr(unique_ptr
<_Tp1
, _Del
>&& __r
)
149 : _Base_type(std::move(__r
))
151 // XXX assume conversion from __r.get() to this->get() to __elem_t*
152 // is a round trip, which might not be true in all cases.
153 using __elem_t
= typename unique_ptr
<_Tp1
, _Del
>::element_type
;
154 _M_enable_shared_from_this_with(static_cast<__elem_t
*>(this->get()));
157 constexpr shared_ptr(nullptr_t __p
)
158 : _Base_type(__p
) { }
161 ~shared_ptr() = default;
164 shared_ptr
& operator=(const shared_ptr
&) noexcept
= default;
166 template <typename _Tp1
>
167 _Compatible
<_Tp1
, shared_ptr
&>
168 operator=(const shared_ptr
<_Tp1
>& __r
) noexcept
170 _Base_type::operator=(__r
);
175 operator=(shared_ptr
&& __r
) noexcept
177 _Base_type::operator=(std::move(__r
));
181 template <typename _Tp1
>
182 _Compatible
<_Tp1
, shared_ptr
&>
183 operator=(shared_ptr
<_Tp1
>&& __r
) noexcept
185 _Base_type::operator=(std::move(__r
));
189 #if _GLIBCXX_USE_DEPRECATED
190 template<typename _Tp1
>
191 _Compatible
<_Tp1
, shared_ptr
&>
192 operator=(std::auto_ptr
<_Tp1
>&& __r
)
194 __shared_ptr
<_Tp
>::operator=(std::move(__r
));
199 template <typename _Tp1
, typename _Del
>
200 _UniqCompatible
<_Tp1
, _Del
, shared_ptr
&>
201 operator=(unique_ptr
<_Tp1
, _Del
>&& __r
)
203 _Base_type::operator=(std::move(__r
));
209 // 8.2.1.2 shared_ptr observers
213 template<typename _Alloc
, typename
... _Args
>
214 shared_ptr(_Sp_make_shared_tag __tag
, const _Alloc
& __a
,
216 : _Base_type(__tag
, __a
, std::forward
<_Args
>(__args
)...)
217 { _M_enable_shared_from_this_with(this->get()); }
219 template<typename _Tp1
, typename _Alloc
, typename
... _Args
>
220 friend shared_ptr
<_Tp1
>
221 allocate_shared(const _Alloc
& __a
, _Args
&&... __args
);
223 shared_ptr(const weak_ptr
<_Tp
>& __r
, std::nothrow_t
)
224 : _Base_type(__r
, std::nothrow
) { }
226 friend class weak_ptr
<_Tp
>;
228 template<typename _Yp
>
229 using __esft_base_t
=
230 decltype(__expt_enable_shared_from_this_base(std::declval
<_Yp
*>()));
232 // Detect an accessible and unambiguous enable_shared_from_this base.
233 template<typename _Yp
, typename
= void>
234 struct __has_esft_base
237 template<typename _Yp
>
238 struct __has_esft_base
<_Yp
, __void_t
<__esft_base_t
<_Yp
>>>
239 : __bool_constant
<!is_array_v
<_Tp
>> { }; // ignore base for arrays
241 template<typename _Yp
>
242 typename enable_if
<__has_esft_base
<_Yp
>::value
>::type
243 _M_enable_shared_from_this_with(const _Yp
* __p
) noexcept
245 if (auto __base
= __expt_enable_shared_from_this_base(__p
))
248 = shared_ptr
<_Yp
>(*this, const_cast<_Yp
*>(__p
));
252 template<typename _Yp
>
253 typename enable_if
<!__has_esft_base
<_Yp
>::value
>::type
254 _M_enable_shared_from_this_with(const _Yp
*) noexcept
258 // C++14 §20.8.2.2.7 //DOING
259 template<typename _Tp1
, typename _Tp2
>
260 bool operator==(const shared_ptr
<_Tp1
>& __a
,
261 const shared_ptr
<_Tp2
>& __b
) noexcept
262 { return __a
.get() == __b
.get(); }
264 template<typename _Tp
>
266 operator==(const shared_ptr
<_Tp
>& __a
, nullptr_t
) noexcept
269 template<typename _Tp
>
271 operator==(nullptr_t
, const shared_ptr
<_Tp
>& __a
) noexcept
274 template<typename _Tp1
, typename _Tp2
>
276 operator!=(const shared_ptr
<_Tp1
>& __a
,
277 const shared_ptr
<_Tp2
>& __b
) noexcept
278 { return __a
.get() != __b
.get(); }
280 template<typename _Tp
>
282 operator!=(const shared_ptr
<_Tp
>& __a
, nullptr_t
) noexcept
283 { return (bool)__a
; }
285 template<typename _Tp
>
287 operator!=(nullptr_t
, const shared_ptr
<_Tp
>& __a
) noexcept
288 { return (bool)__a
; }
290 template<typename _Tp1
, typename _Tp2
>
292 operator<(const shared_ptr
<_Tp1
>& __a
,
293 const shared_ptr
<_Tp2
>& __b
) noexcept
295 using __elem_t1
= typename shared_ptr
<_Tp1
>::element_type
;
296 using __elem_t2
= typename shared_ptr
<_Tp2
>::element_type
;
297 using _CT
= common_type_t
<__elem_t1
*, __elem_t2
*>;
298 return std::less
<_CT
>()(__a
.get(), __b
.get());
301 template<typename _Tp
>
303 operator<(const shared_ptr
<_Tp
>& __a
, nullptr_t
) noexcept
305 using __elem_t
= typename shared_ptr
<_Tp
>::element_type
;
306 return std::less
<__elem_t
*>()(__a
.get(), nullptr);
309 template<typename _Tp
>
311 operator<(nullptr_t
, const shared_ptr
<_Tp
>& __a
) noexcept
313 using __elem_t
= typename shared_ptr
<_Tp
>::element_type
;
314 return std::less
<__elem_t
*>()(nullptr, __a
.get());
317 template<typename _Tp1
, typename _Tp2
>
319 operator<=(const shared_ptr
<_Tp1
>& __a
,
320 const shared_ptr
<_Tp2
>& __b
) noexcept
321 { return !(__b
< __a
); }
323 template<typename _Tp
>
325 operator<=(const shared_ptr
<_Tp
>& __a
, nullptr_t
) noexcept
326 { return !(nullptr < __a
); }
328 template<typename _Tp
>
330 operator<=(nullptr_t
, const shared_ptr
<_Tp
>& __a
) noexcept
331 { return !(__a
< nullptr); }
333 template<typename _Tp1
, typename _Tp2
>
335 operator>(const shared_ptr
<_Tp1
>& __a
,
336 const shared_ptr
<_Tp2
>& __b
) noexcept
337 { return (__b
< __a
); }
339 template<typename _Tp
>
341 operator>(const shared_ptr
<_Tp
>& __a
, nullptr_t
) noexcept
343 using __elem_t
= typename shared_ptr
<_Tp
>::element_type
;
344 return std::less
<__elem_t
*>()(nullptr, __a
.get());
347 template<typename _Tp
>
349 operator>(nullptr_t
, const shared_ptr
<_Tp
>& __a
) noexcept
351 using __elem_t
= typename shared_ptr
<_Tp
>::element_type
;
352 return std::less
<__elem_t
*>()(__a
.get(), nullptr);
355 template<typename _Tp1
, typename _Tp2
>
357 operator>=(const shared_ptr
<_Tp1
>& __a
,
358 const shared_ptr
<_Tp2
>& __b
) noexcept
359 { return !(__a
< __b
); }
361 template<typename _Tp
>
363 operator>=(const shared_ptr
<_Tp
>& __a
, nullptr_t
) noexcept
364 { return !(__a
< nullptr); }
366 template<typename _Tp
>
368 operator>=(nullptr_t
, const shared_ptr
<_Tp
>& __a
) noexcept
369 { return !(nullptr < __a
); }
372 template<typename _Tp
>
374 swap(shared_ptr
<_Tp
>& __a
, shared_ptr
<_Tp
>& __b
) noexcept
377 // 8.2.1.3, shared_ptr casts
378 template<typename _Tp
, typename _Tp1
>
379 inline shared_ptr
<_Tp
>
380 static_pointer_cast(const shared_ptr
<_Tp1
>& __r
) noexcept
382 using __elem_t
= typename shared_ptr
<_Tp
>::element_type
;
383 return shared_ptr
<_Tp
>(__r
, static_cast<__elem_t
*>(__r
.get()));
386 template<typename _Tp
, typename _Tp1
>
387 inline shared_ptr
<_Tp
>
388 dynamic_pointer_cast(const shared_ptr
<_Tp1
>& __r
) noexcept
390 using __elem_t
= typename shared_ptr
<_Tp
>::element_type
;
391 if (_Tp
* __p
= dynamic_cast<__elem_t
*>(__r
.get()))
392 return shared_ptr
<_Tp
>(__r
, __p
);
393 return shared_ptr
<_Tp
>();
396 template<typename _Tp
, typename _Tp1
>
397 inline shared_ptr
<_Tp
>
398 const_pointer_cast(const shared_ptr
<_Tp1
>& __r
) noexcept
400 using __elem_t
= typename shared_ptr
<_Tp
>::element_type
;
401 return shared_ptr
<_Tp
>(__r
, const_cast<__elem_t
*>(__r
.get()));
404 template<typename _Tp
, typename _Tp1
>
405 inline shared_ptr
<_Tp
>
406 reinterpret_pointer_cast(const shared_ptr
<_Tp1
>& __r
) noexcept
408 using __elem_t
= typename shared_ptr
<_Tp
>::element_type
;
409 return shared_ptr
<_Tp
>(__r
, reinterpret_cast<__elem_t
*>(__r
.get()));
413 template<typename _Tp
>
414 class weak_ptr
: public __weak_ptr
<_Tp
>
416 template<typename _Tp1
, typename _Res
= void>
417 using _Compatible
= enable_if_t
<__sp_compatible_v
<_Tp1
, _Tp
>, _Res
>;
419 using _Base_type
= __weak_ptr
<_Tp
>;
422 constexpr weak_ptr() noexcept
= default;
424 template<typename _Tp1
, typename
= _Compatible
<_Tp1
>>
425 weak_ptr(const shared_ptr
<_Tp1
>& __r
) noexcept
426 : _Base_type(__r
) { }
428 weak_ptr(const weak_ptr
&) noexcept
= default;
430 template<typename _Tp1
, typename
= _Compatible
<_Tp1
>>
431 weak_ptr(const weak_ptr
<_Tp1
>& __r
) noexcept
432 : _Base_type(__r
) { }
434 weak_ptr(weak_ptr
&&) noexcept
= default;
436 template<typename _Tp1
, typename
= _Compatible
<_Tp1
>>
437 weak_ptr(weak_ptr
<_Tp1
>&& __r
) noexcept
438 : _Base_type(std::move(__r
)) { }
441 operator=(const weak_ptr
& __r
) noexcept
= default;
443 template<typename _Tp1
>
444 _Compatible
<_Tp1
, weak_ptr
&>
445 operator=(const weak_ptr
<_Tp1
>& __r
) noexcept
447 this->_Base_type::operator=(__r
);
451 template<typename _Tp1
>
452 _Compatible
<_Tp1
, weak_ptr
&>
453 operator=(const shared_ptr
<_Tp1
>& __r
) noexcept
455 this->_Base_type::operator=(__r
);
460 operator=(weak_ptr
&& __r
) noexcept
= default;
462 template<typename _Tp1
>
463 _Compatible
<_Tp1
, weak_ptr
&>
464 operator=(weak_ptr
<_Tp1
>&& __r
) noexcept
466 this->_Base_type::operator=(std::move(__r
));
471 lock() const noexcept
472 { return shared_ptr
<_Tp
>(*this, std::nothrow
); }
474 friend class enable_shared_from_this
<_Tp
>;
478 template<typename _Tp
>
480 swap(weak_ptr
<_Tp
>& __a
, weak_ptr
<_Tp
>& __b
) noexcept
483 /// C++14 §20.8.2.2.10
484 template<typename _Del
, typename _Tp
>
486 get_deleter(const shared_ptr
<_Tp
>& __p
) noexcept
487 { return std::get_deleter
<_Del
>(__p
); }
489 // C++14 §20.8.2.2.11
490 template<typename _Ch
, typename _Tr
, typename _Tp
>
491 inline std::basic_ostream
<_Ch
, _Tr
>&
492 operator<<(std::basic_ostream
<_Ch
, _Tr
>& __os
, const shared_ptr
<_Tp
>& __p
)
499 template<typename _Tp
= void> class owner_less
;
501 /// Partial specialization of owner_less for shared_ptr.
502 template<typename _Tp
>
503 struct owner_less
<shared_ptr
<_Tp
>>
504 : public _Sp_owner_less
<shared_ptr
<_Tp
>, weak_ptr
<_Tp
>>
507 /// Partial specialization of owner_less for weak_ptr.
508 template<typename _Tp
>
509 struct owner_less
<weak_ptr
<_Tp
>>
510 : public _Sp_owner_less
<weak_ptr
<_Tp
>, shared_ptr
<_Tp
>>
514 class owner_less
<void>
516 template<typename _Tp
, typename _Up
>
518 operator()(shared_ptr
<_Tp
> const& __lhs
,
519 shared_ptr
<_Up
> const& __rhs
) const
520 { return __lhs
.owner_before(__rhs
); }
522 template<typename _Tp
, typename _Up
>
524 operator()(shared_ptr
<_Tp
> const& __lhs
,
525 weak_ptr
<_Up
> const& __rhs
) const
526 { return __lhs
.owner_before(__rhs
); }
528 template<typename _Tp
, typename _Up
>
530 operator()(weak_ptr
<_Tp
> const& __lhs
,
531 shared_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 weak_ptr
<_Up
> const& __rhs
) const
538 { return __lhs
.owner_before(__rhs
); }
540 typedef void is_transparent
;
544 template<typename _Tp
>
546 atomic_is_lock_free(const shared_ptr
<_Tp
>* __p
)
547 { return std::atomic_is_lock_free
<_Tp
, __default_lock_policy
>(__p
); }
549 template<typename _Tp
>
550 shared_ptr
<_Tp
> atomic_load(const shared_ptr
<_Tp
>* __p
)
551 { return std::atomic_load
<_Tp
>(__p
); }
553 template<typename _Tp
>
555 atomic_load_explicit(const shared_ptr
<_Tp
>* __p
, memory_order __mo
)
556 { return std::atomic_load_explicit
<_Tp
>(__p
, __mo
); }
558 template<typename _Tp
>
559 void atomic_store(shared_ptr
<_Tp
>* __p
, shared_ptr
<_Tp
> __r
)
560 { return std::atomic_store
<_Tp
>(__p
, __r
); }
562 template<typename _Tp
>
564 atomic_store_explicit(const shared_ptr
<_Tp
>* __p
,
567 { return std::atomic_store_explicit
<_Tp
>(__p
, __r
, __mo
); }
569 template<typename _Tp
>
570 void atomic_exchange(shared_ptr
<_Tp
>* __p
, shared_ptr
<_Tp
> __r
)
571 { return std::atomic_exchange
<_Tp
>(__p
, __r
); }
573 template<typename _Tp
>
575 atomic_exchange_explicit(const shared_ptr
<_Tp
>* __p
,
578 { return std::atomic_exchange_explicit
<_Tp
>(__p
, __r
, __mo
); }
580 template<typename _Tp
>
581 bool atomic_compare_exchange_weak(shared_ptr
<_Tp
>* __p
,
582 shared_ptr
<_Tp
>* __v
,
584 { return std::atomic_compare_exchange_weak
<_Tp
>(__p
, __v
, __w
); }
586 template<typename _Tp
>
587 bool atomic_compare_exchange_strong(shared_ptr
<_Tp
>* __p
,
588 shared_ptr
<_Tp
>* __v
,
590 { return std::atomic_compare_exchange_strong
<_Tp
>(__p
, __v
, __w
); }
592 template<typename _Tp
>
593 bool atomic_compare_exchange_weak_explicit(shared_ptr
<_Tp
>* __p
,
594 shared_ptr
<_Tp
>* __v
,
596 memory_order __success
,
597 memory_order __failure
)
598 { return std::atomic_compare_exchange_weak_explicit
<_Tp
>(__p
, __v
, __w
,
602 template<typename _Tp
>
603 bool atomic_compare_exchange_strong_explicit(shared_ptr
<_Tp
>* __p
,
604 shared_ptr
<_Tp
>* __v
,
606 memory_order __success
,
607 memory_order __failure
)
608 { return std::atomic_compare_exchange_strong_explicit
<_Tp
>(__p
, __v
, __w
,
612 //enable_shared_from_this
613 template<typename _Tp
>
614 class enable_shared_from_this
617 constexpr enable_shared_from_this() noexcept
{ }
619 enable_shared_from_this(const enable_shared_from_this
&) noexcept
{ }
621 enable_shared_from_this
&
622 operator=(const enable_shared_from_this
&) noexcept
625 ~enable_shared_from_this() { }
630 { return shared_ptr
<_Tp
>(this->_M_weak_this
); }
632 shared_ptr
<const _Tp
>
633 shared_from_this() const
634 { return shared_ptr
<const _Tp
>(this->_M_weak_this
); }
637 weak_from_this() noexcept
638 { return _M_weak_this
; }
641 weak_from_this() const noexcept
642 { return _M_weak_this
; }
645 template<typename _Tp1
>
647 _M_weak_assign(_Tp1
* __p
, const __shared_count
<>& __n
) const noexcept
648 { _M_weak_this
._M_assign(__p
, __n
); }
650 // Found by ADL when this is an associated class.
651 friend const enable_shared_from_this
*
652 __expt_enable_shared_from_this_base(const enable_shared_from_this
* __p
)
656 friend class shared_ptr
;
658 mutable weak_ptr
<_Tp
> _M_weak_this
;
660 } // namespace fundamentals_v2
661 } // namespace experimental
663 /// std::hash specialization for shared_ptr.
664 template<typename _Tp
>
665 struct hash
<experimental::shared_ptr
<_Tp
>>
666 : public __hash_base
<size_t, experimental::shared_ptr
<_Tp
>>
669 operator()(const experimental::shared_ptr
<_Tp
>& __s
) const noexcept
670 { return std::hash
<_Tp
*>()(__s
.get()); }
673 _GLIBCXX_END_NAMESPACE_VERSION
676 #endif // __cplusplus <= 201103L
678 #endif // _GLIBCXX_EXPERIMENTAL_SHARED_PTR_H