1 // Experimental shared_ptr with array support -*- C++ -*-
3 // Copyright (C) 2015-2017 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 <= 201103L
36 # include <bits/c++14_warning.h>
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 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())); }
148 template<typename _Tp1
, typename _Del
,
149 typename
= _UniqCompatible
<_Tp1
, _Del
>>
150 shared_ptr(unique_ptr
<_Tp1
, _Del
>&& __r
)
151 : _Base_type(std::move(__r
))
153 // XXX assume conversion from __r.get() to this->get() to __elem_t*
154 // is a round trip, which might not be true in all cases.
155 using __elem_t
= typename unique_ptr
<_Tp1
, _Del
>::element_type
;
156 _M_enable_shared_from_this_with(static_cast<__elem_t
*>(this->get()));
159 constexpr shared_ptr(nullptr_t __p
)
160 : _Base_type(__p
) { }
163 ~shared_ptr() = default;
166 shared_ptr
& operator=(const shared_ptr
&) noexcept
= default;
168 template <typename _Tp1
>
169 _Compatible
<_Tp1
, shared_ptr
&>
170 operator=(const shared_ptr
<_Tp1
>& __r
) noexcept
172 _Base_type::operator=(__r
);
177 operator=(shared_ptr
&& __r
) noexcept
179 _Base_type::operator=(std::move(__r
));
183 template <typename _Tp1
>
184 _Compatible
<_Tp1
, shared_ptr
&>
185 operator=(shared_ptr
<_Tp1
>&& __r
) noexcept
187 _Base_type::operator=(std::move(__r
));
191 #if _GLIBCXX_USE_DEPRECATED
192 template<typename _Tp1
>
193 _Compatible
<_Tp1
, shared_ptr
&>
194 operator=(std::auto_ptr
<_Tp1
>&& __r
)
196 __shared_ptr
<_Tp
>::operator=(std::move(__r
));
201 template <typename _Tp1
, typename _Del
>
202 _UniqCompatible
<_Tp1
, _Del
, shared_ptr
&>
203 operator=(unique_ptr
<_Tp1
, _Del
>&& __r
)
205 _Base_type::operator=(std::move(__r
));
211 // 8.2.1.2 shared_ptr observers
215 template<typename _Alloc
, typename
... _Args
>
216 shared_ptr(_Sp_make_shared_tag __tag
, const _Alloc
& __a
,
218 : _Base_type(__tag
, __a
, std::forward
<_Args
>(__args
)...)
219 { _M_enable_shared_from_this_with(this->get()); }
221 template<typename _Tp1
, typename _Alloc
, typename
... _Args
>
222 friend shared_ptr
<_Tp1
>
223 allocate_shared(const _Alloc
& __a
, _Args
&&... __args
);
225 shared_ptr(const weak_ptr
<_Tp
>& __r
, std::nothrow_t
)
226 : _Base_type(__r
, std::nothrow
) { }
228 friend class weak_ptr
<_Tp
>;
230 template<typename _Yp
>
231 using __esft_base_t
=
232 decltype(__expt_enable_shared_from_this_base(std::declval
<_Yp
*>()));
234 // Detect an accessible and unambiguous enable_shared_from_this base.
235 template<typename _Yp
, typename
= void>
236 struct __has_esft_base
239 template<typename _Yp
>
240 struct __has_esft_base
<_Yp
, __void_t
<__esft_base_t
<_Yp
>>>
241 : __bool_constant
<!is_array_v
<_Tp
>> { }; // ignore base for arrays
243 template<typename _Yp
>
244 typename enable_if
<__has_esft_base
<_Yp
>::value
>::type
245 _M_enable_shared_from_this_with(const _Yp
* __p
) noexcept
247 if (auto __base
= __expt_enable_shared_from_this_base(__p
))
250 = shared_ptr
<_Yp
>(*this, const_cast<_Yp
*>(__p
));
254 template<typename _Yp
>
255 typename enable_if
<!__has_esft_base
<_Yp
>::value
>::type
256 _M_enable_shared_from_this_with(const _Yp
*) noexcept
260 // C++14 §20.8.2.2.7 //DOING
261 template<typename _Tp1
, typename _Tp2
>
262 bool operator==(const shared_ptr
<_Tp1
>& __a
,
263 const shared_ptr
<_Tp2
>& __b
) noexcept
264 { return __a
.get() == __b
.get(); }
266 template<typename _Tp
>
268 operator==(const shared_ptr
<_Tp
>& __a
, nullptr_t
) noexcept
271 template<typename _Tp
>
273 operator==(nullptr_t
, const shared_ptr
<_Tp
>& __a
) noexcept
276 template<typename _Tp1
, typename _Tp2
>
278 operator!=(const shared_ptr
<_Tp1
>& __a
,
279 const shared_ptr
<_Tp2
>& __b
) noexcept
280 { return __a
.get() != __b
.get(); }
282 template<typename _Tp
>
284 operator!=(const shared_ptr
<_Tp
>& __a
, nullptr_t
) noexcept
285 { return (bool)__a
; }
287 template<typename _Tp
>
289 operator!=(nullptr_t
, const shared_ptr
<_Tp
>& __a
) noexcept
290 { return (bool)__a
; }
292 template<typename _Tp1
, typename _Tp2
>
294 operator<(const shared_ptr
<_Tp1
>& __a
,
295 const shared_ptr
<_Tp2
>& __b
) noexcept
297 using __elem_t1
= typename shared_ptr
<_Tp1
>::element_type
;
298 using __elem_t2
= typename shared_ptr
<_Tp2
>::element_type
;
299 using _CT
= common_type_t
<__elem_t1
*, __elem_t2
*>;
300 return std::less
<_CT
>()(__a
.get(), __b
.get());
303 template<typename _Tp
>
305 operator<(const shared_ptr
<_Tp
>& __a
, nullptr_t
) noexcept
307 using __elem_t
= typename shared_ptr
<_Tp
>::element_type
;
308 return std::less
<__elem_t
*>()(__a
.get(), nullptr);
311 template<typename _Tp
>
313 operator<(nullptr_t
, const shared_ptr
<_Tp
>& __a
) noexcept
315 using __elem_t
= typename shared_ptr
<_Tp
>::element_type
;
316 return std::less
<__elem_t
*>()(nullptr, __a
.get());
319 template<typename _Tp1
, typename _Tp2
>
321 operator<=(const shared_ptr
<_Tp1
>& __a
,
322 const shared_ptr
<_Tp2
>& __b
) noexcept
323 { return !(__b
< __a
); }
325 template<typename _Tp
>
327 operator<=(const shared_ptr
<_Tp
>& __a
, nullptr_t
) noexcept
328 { return !(nullptr < __a
); }
330 template<typename _Tp
>
332 operator<=(nullptr_t
, const shared_ptr
<_Tp
>& __a
) noexcept
333 { return !(__a
< nullptr); }
335 template<typename _Tp1
, typename _Tp2
>
337 operator>(const shared_ptr
<_Tp1
>& __a
,
338 const shared_ptr
<_Tp2
>& __b
) noexcept
339 { return (__b
< __a
); }
341 template<typename _Tp
>
343 operator>(const shared_ptr
<_Tp
>& __a
, nullptr_t
) noexcept
345 using __elem_t
= typename shared_ptr
<_Tp
>::element_type
;
346 return std::less
<__elem_t
*>()(nullptr, __a
.get());
349 template<typename _Tp
>
351 operator>(nullptr_t
, const shared_ptr
<_Tp
>& __a
) noexcept
353 using __elem_t
= typename shared_ptr
<_Tp
>::element_type
;
354 return std::less
<__elem_t
*>()(__a
.get(), nullptr);
357 template<typename _Tp1
, typename _Tp2
>
359 operator>=(const shared_ptr
<_Tp1
>& __a
,
360 const shared_ptr
<_Tp2
>& __b
) noexcept
361 { return !(__a
< __b
); }
363 template<typename _Tp
>
365 operator>=(const shared_ptr
<_Tp
>& __a
, nullptr_t
) noexcept
366 { return !(__a
< nullptr); }
368 template<typename _Tp
>
370 operator>=(nullptr_t
, const shared_ptr
<_Tp
>& __a
) noexcept
371 { return !(nullptr < __a
); }
374 template<typename _Tp
>
376 swap(shared_ptr
<_Tp
>& __a
, shared_ptr
<_Tp
>& __b
) noexcept
379 // 8.2.1.3, shared_ptr casts
380 template<typename _Tp
, typename _Tp1
>
381 inline shared_ptr
<_Tp
>
382 static_pointer_cast(const shared_ptr
<_Tp1
>& __r
) noexcept
384 using __elem_t
= typename shared_ptr
<_Tp
>::element_type
;
385 return shared_ptr
<_Tp
>(__r
, static_cast<__elem_t
*>(__r
.get()));
388 template<typename _Tp
, typename _Tp1
>
389 inline shared_ptr
<_Tp
>
390 dynamic_pointer_cast(const shared_ptr
<_Tp1
>& __r
) noexcept
392 using __elem_t
= typename shared_ptr
<_Tp
>::element_type
;
393 if (_Tp
* __p
= dynamic_cast<__elem_t
*>(__r
.get()))
394 return shared_ptr
<_Tp
>(__r
, __p
);
395 return shared_ptr
<_Tp
>();
398 template<typename _Tp
, typename _Tp1
>
399 inline shared_ptr
<_Tp
>
400 const_pointer_cast(const shared_ptr
<_Tp1
>& __r
) noexcept
402 using __elem_t
= typename shared_ptr
<_Tp
>::element_type
;
403 return shared_ptr
<_Tp
>(__r
, const_cast<__elem_t
*>(__r
.get()));
406 template<typename _Tp
, typename _Tp1
>
407 inline shared_ptr
<_Tp
>
408 reinterpret_pointer_cast(const shared_ptr
<_Tp1
>& __r
) noexcept
410 using __elem_t
= typename shared_ptr
<_Tp
>::element_type
;
411 return shared_ptr
<_Tp
>(__r
, reinterpret_cast<__elem_t
*>(__r
.get()));
415 template<typename _Tp
>
416 class weak_ptr
: public __weak_ptr
<_Tp
>
418 template<typename _Tp1
, typename _Res
= void>
419 using _Compatible
= enable_if_t
<__sp_compatible_v
<_Tp1
, _Tp
>, _Res
>;
421 using _Base_type
= __weak_ptr
<_Tp
>;
424 constexpr weak_ptr() noexcept
= default;
426 template<typename _Tp1
, typename
= _Compatible
<_Tp1
>>
427 weak_ptr(const shared_ptr
<_Tp1
>& __r
) noexcept
428 : _Base_type(__r
) { }
430 weak_ptr(const weak_ptr
&) noexcept
= default;
432 template<typename _Tp1
, typename
= _Compatible
<_Tp1
>>
433 weak_ptr(const weak_ptr
<_Tp1
>& __r
) noexcept
434 : _Base_type(__r
) { }
436 weak_ptr(weak_ptr
&&) noexcept
= default;
438 template<typename _Tp1
, typename
= _Compatible
<_Tp1
>>
439 weak_ptr(weak_ptr
<_Tp1
>&& __r
) noexcept
440 : _Base_type(std::move(__r
)) { }
443 operator=(const weak_ptr
& __r
) noexcept
= default;
445 template<typename _Tp1
>
446 _Compatible
<_Tp1
, weak_ptr
&>
447 operator=(const weak_ptr
<_Tp1
>& __r
) noexcept
449 this->_Base_type::operator=(__r
);
453 template<typename _Tp1
>
454 _Compatible
<_Tp1
, weak_ptr
&>
455 operator=(const shared_ptr
<_Tp1
>& __r
) noexcept
457 this->_Base_type::operator=(__r
);
462 operator=(weak_ptr
&& __r
) noexcept
= default;
464 template<typename _Tp1
>
465 _Compatible
<_Tp1
, weak_ptr
&>
466 operator=(weak_ptr
<_Tp1
>&& __r
) noexcept
468 this->_Base_type::operator=(std::move(__r
));
473 lock() const noexcept
474 { return shared_ptr
<_Tp
>(*this, std::nothrow
); }
476 friend class enable_shared_from_this
<_Tp
>;
480 template<typename _Tp
>
482 swap(weak_ptr
<_Tp
>& __a
, weak_ptr
<_Tp
>& __b
) noexcept
485 /// C++14 §20.8.2.2.10
486 template<typename _Del
, typename _Tp
>
488 get_deleter(const shared_ptr
<_Tp
>& __p
) noexcept
489 { return std::get_deleter
<_Del
>(__p
); }
491 // C++14 §20.8.2.2.11
492 template<typename _Ch
, typename _Tr
, typename _Tp
>
493 inline std::basic_ostream
<_Ch
, _Tr
>&
494 operator<<(std::basic_ostream
<_Ch
, _Tr
>& __os
, const shared_ptr
<_Tp
>& __p
)
501 template<typename _Tp
= void> class owner_less
;
503 /// Partial specialization of owner_less for shared_ptr.
504 template<typename _Tp
>
505 struct owner_less
<shared_ptr
<_Tp
>>
506 : public _Sp_owner_less
<shared_ptr
<_Tp
>, weak_ptr
<_Tp
>>
509 /// Partial specialization of owner_less for weak_ptr.
510 template<typename _Tp
>
511 struct owner_less
<weak_ptr
<_Tp
>>
512 : public _Sp_owner_less
<weak_ptr
<_Tp
>, shared_ptr
<_Tp
>>
516 class owner_less
<void>
518 template<typename _Tp
, typename _Up
>
520 operator()(shared_ptr
<_Tp
> const& __lhs
,
521 shared_ptr
<_Up
> const& __rhs
) const
522 { return __lhs
.owner_before(__rhs
); }
524 template<typename _Tp
, typename _Up
>
526 operator()(shared_ptr
<_Tp
> const& __lhs
,
527 weak_ptr
<_Up
> const& __rhs
) const
528 { return __lhs
.owner_before(__rhs
); }
530 template<typename _Tp
, typename _Up
>
532 operator()(weak_ptr
<_Tp
> const& __lhs
,
533 shared_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 weak_ptr
<_Up
> const& __rhs
) const
540 { return __lhs
.owner_before(__rhs
); }
542 typedef void is_transparent
;
546 template<typename _Tp
>
548 atomic_is_lock_free(const shared_ptr
<_Tp
>* __p
)
549 { return std::atomic_is_lock_free
<_Tp
, __default_lock_policy
>(__p
); }
551 template<typename _Tp
>
552 shared_ptr
<_Tp
> atomic_load(const shared_ptr
<_Tp
>* __p
)
553 { return std::atomic_load
<_Tp
>(__p
); }
555 template<typename _Tp
>
557 atomic_load_explicit(const shared_ptr
<_Tp
>* __p
, memory_order __mo
)
558 { return std::atomic_load_explicit
<_Tp
>(__p
, __mo
); }
560 template<typename _Tp
>
561 void atomic_store(shared_ptr
<_Tp
>* __p
, shared_ptr
<_Tp
> __r
)
562 { return std::atomic_store
<_Tp
>(__p
, __r
); }
564 template<typename _Tp
>
566 atomic_store_explicit(const shared_ptr
<_Tp
>* __p
,
569 { return std::atomic_store_explicit
<_Tp
>(__p
, __r
, __mo
); }
571 template<typename _Tp
>
572 void atomic_exchange(shared_ptr
<_Tp
>* __p
, shared_ptr
<_Tp
> __r
)
573 { return std::atomic_exchange
<_Tp
>(__p
, __r
); }
575 template<typename _Tp
>
577 atomic_exchange_explicit(const shared_ptr
<_Tp
>* __p
,
580 { return std::atomic_exchange_explicit
<_Tp
>(__p
, __r
, __mo
); }
582 template<typename _Tp
>
583 bool atomic_compare_exchange_weak(shared_ptr
<_Tp
>* __p
,
584 shared_ptr
<_Tp
>* __v
,
586 { return std::atomic_compare_exchange_weak
<_Tp
>(__p
, __v
, __w
); }
588 template<typename _Tp
>
589 bool atomic_compare_exchange_strong(shared_ptr
<_Tp
>* __p
,
590 shared_ptr
<_Tp
>* __v
,
592 { return std::atomic_compare_exchange_strong
<_Tp
>(__p
, __v
, __w
); }
594 template<typename _Tp
>
595 bool atomic_compare_exchange_weak_explicit(shared_ptr
<_Tp
>* __p
,
596 shared_ptr
<_Tp
>* __v
,
598 memory_order __success
,
599 memory_order __failure
)
600 { return std::atomic_compare_exchange_weak_explicit
<_Tp
>(__p
, __v
, __w
,
604 template<typename _Tp
>
605 bool atomic_compare_exchange_strong_explicit(shared_ptr
<_Tp
>* __p
,
606 shared_ptr
<_Tp
>* __v
,
608 memory_order __success
,
609 memory_order __failure
)
610 { return std::atomic_compare_exchange_strong_explicit
<_Tp
>(__p
, __v
, __w
,
614 //enable_shared_from_this
615 template<typename _Tp
>
616 class enable_shared_from_this
619 constexpr enable_shared_from_this() noexcept
{ }
621 enable_shared_from_this(const enable_shared_from_this
&) noexcept
{ }
623 enable_shared_from_this
&
624 operator=(const enable_shared_from_this
&) noexcept
627 ~enable_shared_from_this() { }
632 { return shared_ptr
<_Tp
>(this->_M_weak_this
); }
634 shared_ptr
<const _Tp
>
635 shared_from_this() const
636 { return shared_ptr
<const _Tp
>(this->_M_weak_this
); }
639 weak_from_this() noexcept
640 { return _M_weak_this
; }
643 weak_from_this() const noexcept
644 { return _M_weak_this
; }
647 template<typename _Tp1
>
649 _M_weak_assign(_Tp1
* __p
, const __shared_count
<>& __n
) const noexcept
650 { _M_weak_this
._M_assign(__p
, __n
); }
652 // Found by ADL when this is an associated class.
653 friend const enable_shared_from_this
*
654 __expt_enable_shared_from_this_base(const enable_shared_from_this
* __p
)
658 friend class shared_ptr
;
660 mutable weak_ptr
<_Tp
> _M_weak_this
;
662 } // namespace fundamentals_v2
663 } // namespace experimental
665 /// std::hash specialization for shared_ptr.
666 template<typename _Tp
>
667 struct hash
<experimental::shared_ptr
<_Tp
>>
668 : public __hash_base
<size_t, experimental::shared_ptr
<_Tp
>>
671 operator()(const experimental::shared_ptr
<_Tp
>& __s
) const noexcept
672 { return std::hash
<_Tp
*>()(__s
.get()); }
675 _GLIBCXX_END_NAMESPACE_VERSION
678 #endif // __cplusplus <= 201103L
680 #endif // _GLIBCXX_EXPERIMENTAL_SHARED_PTR_H