1f9a78e0eSmrg // Experimental shared_ptr with array support -*- C++ -*-
2f9a78e0eSmrg
3*b1e83836Smrg // Copyright (C) 2015-2022 Free Software Foundation, Inc.
4f9a78e0eSmrg //
5f9a78e0eSmrg // This file is part of the GNU ISO C++ Library. This library is free
6f9a78e0eSmrg // software; you can redistribute it and/or modify it under the
7f9a78e0eSmrg // terms of the GNU General Public License as published by the
8f9a78e0eSmrg // Free Software Foundation; either version 3, or (at your option)
9f9a78e0eSmrg // any later version.
10f9a78e0eSmrg
11f9a78e0eSmrg // This library is distributed in the hope that it will be useful,
12f9a78e0eSmrg // but WITHOUT ANY WARRANTY; without even the implied warranty of
13f9a78e0eSmrg // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14f9a78e0eSmrg // GNU General Public License for more details.
15f9a78e0eSmrg
16f9a78e0eSmrg // Under Section 7 of GPL version 3, you are granted additional
17f9a78e0eSmrg // permissions described in the GCC Runtime Library Exception, version
18f9a78e0eSmrg // 3.1, as published by the Free Software Foundation.
19f9a78e0eSmrg
20f9a78e0eSmrg // You should have received a copy of the GNU General Public License and
21f9a78e0eSmrg // a copy of the GCC Runtime Library Exception along with this program;
22f9a78e0eSmrg // see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
23f9a78e0eSmrg // <http://www.gnu.org/licenses/>.
24f9a78e0eSmrg
25f9a78e0eSmrg /** @file experimental/bits/shared_ptr.h
26f9a78e0eSmrg * This is an internal header file, included by other library headers.
27f9a78e0eSmrg * Do not attempt to use it directly. @headername{experimental/memory}
28f9a78e0eSmrg */
29f9a78e0eSmrg
30f9a78e0eSmrg #ifndef _GLIBCXX_EXPERIMENTAL_SHARED_PTR_H
31f9a78e0eSmrg #define _GLIBCXX_EXPERIMENTAL_SHARED_PTR_H 1
32f9a78e0eSmrg
33f9a78e0eSmrg #pragma GCC system_header
34f9a78e0eSmrg
35b17d1066Smrg #if __cplusplus >= 201402L
36f9a78e0eSmrg
37f9a78e0eSmrg #include <memory>
38f9a78e0eSmrg #include <experimental/type_traits>
39f9a78e0eSmrg
_GLIBCXX_VISIBILITY(default)40f9a78e0eSmrg namespace std _GLIBCXX_VISIBILITY(default)
41f9a78e0eSmrg {
42a3e9eb18Smrg _GLIBCXX_BEGIN_NAMESPACE_VERSION
43a3e9eb18Smrg
44f9a78e0eSmrg namespace experimental
45f9a78e0eSmrg {
46f9a78e0eSmrg inline namespace fundamentals_v2
47f9a78e0eSmrg {
48f9a78e0eSmrg // 8.2.1
49f9a78e0eSmrg
50f9a78e0eSmrg template<typename _Tp> class shared_ptr;
51f9a78e0eSmrg template<typename _Tp> class weak_ptr;
52b17d1066Smrg template<typename _Tp> class enable_shared_from_this;
53f9a78e0eSmrg
54b17d1066Smrg template<typename _Yp, typename _Tp>
55b17d1066Smrg constexpr bool __sp_compatible_v
56b17d1066Smrg = std::__sp_compatible_with<_Yp*, _Tp*>::value;
57f9a78e0eSmrg
58b17d1066Smrg template<typename _Tp, typename _Yp>
59b17d1066Smrg constexpr bool __sp_is_constructible_v
60b17d1066Smrg = std::__sp_is_constructible<_Tp, _Yp>::value;
61f9a78e0eSmrg
62f9a78e0eSmrg template<typename _Tp>
63f9a78e0eSmrg class shared_ptr : public __shared_ptr<_Tp>
64f9a78e0eSmrg {
65f9a78e0eSmrg using _Base_type = __shared_ptr<_Tp>;
66f9a78e0eSmrg
67f9a78e0eSmrg public:
68f9a78e0eSmrg using element_type = typename _Base_type::element_type;
69f9a78e0eSmrg
70f9a78e0eSmrg private:
71f9a78e0eSmrg // Constraint for construction from a pointer of type _Yp*:
72f9a78e0eSmrg template<typename _Yp>
73f9a78e0eSmrg using _SafeConv = enable_if_t<__sp_is_constructible_v<_Tp, _Yp>>;
74f9a78e0eSmrg
75f9a78e0eSmrg template<typename _Tp1, typename _Res = void>
76f9a78e0eSmrg using _Compatible
77f9a78e0eSmrg = enable_if_t<__sp_compatible_v<_Tp1, _Tp>, _Res>;
78f9a78e0eSmrg
79f9a78e0eSmrg template<typename _Tp1, typename _Del,
80f9a78e0eSmrg typename _Ptr = typename unique_ptr<_Tp1, _Del>::pointer,
81f9a78e0eSmrg typename _Res = void>
82f9a78e0eSmrg using _UniqCompatible = enable_if_t<
83f9a78e0eSmrg __sp_compatible_v<_Tp1, _Tp>
84f9a78e0eSmrg && experimental::is_convertible_v<_Ptr, element_type*>,
85f9a78e0eSmrg _Res>;
86f9a78e0eSmrg
87f9a78e0eSmrg public:
88f9a78e0eSmrg
89f9a78e0eSmrg // 8.2.1.1, shared_ptr constructors
90f9a78e0eSmrg constexpr shared_ptr() noexcept = default;
91f9a78e0eSmrg
92f9a78e0eSmrg template<typename _Tp1, typename = _SafeConv<_Tp1>>
93f9a78e0eSmrg explicit
94f9a78e0eSmrg shared_ptr(_Tp1* __p) : _Base_type(__p)
95f9a78e0eSmrg { _M_enable_shared_from_this_with(__p); }
96f9a78e0eSmrg
97f9a78e0eSmrg template<typename _Tp1, typename _Deleter, typename = _SafeConv<_Tp1>>
98f9a78e0eSmrg shared_ptr(_Tp1* __p, _Deleter __d)
99f9a78e0eSmrg : _Base_type(__p, __d)
100f9a78e0eSmrg { _M_enable_shared_from_this_with(__p); }
101f9a78e0eSmrg
102f9a78e0eSmrg template<typename _Tp1, typename _Deleter, typename _Alloc,
103f9a78e0eSmrg typename = _SafeConv<_Tp1>>
104f9a78e0eSmrg shared_ptr(_Tp1* __p, _Deleter __d, _Alloc __a)
105f9a78e0eSmrg : _Base_type(__p, __d, __a)
106f9a78e0eSmrg { _M_enable_shared_from_this_with(__p); }
107f9a78e0eSmrg
108f9a78e0eSmrg template<typename _Deleter>
109f9a78e0eSmrg shared_ptr(nullptr_t __p, _Deleter __d)
110f9a78e0eSmrg : _Base_type(__p, __d) { }
111f9a78e0eSmrg
112f9a78e0eSmrg template<typename _Deleter, typename _Alloc>
113f9a78e0eSmrg shared_ptr(nullptr_t __p, _Deleter __d, _Alloc __a)
114f9a78e0eSmrg : _Base_type(__p, __d, __a) { }
115f9a78e0eSmrg
116f9a78e0eSmrg template<typename _Tp1>
117f9a78e0eSmrg shared_ptr(const shared_ptr<_Tp1>& __r, element_type* __p) noexcept
118f9a78e0eSmrg : _Base_type(__r, __p) { }
119f9a78e0eSmrg
120f9a78e0eSmrg shared_ptr(const shared_ptr& __r) noexcept
121f9a78e0eSmrg : _Base_type(__r) { }
122f9a78e0eSmrg
123f9a78e0eSmrg template<typename _Tp1, typename = _Compatible<_Tp1>>
124f9a78e0eSmrg shared_ptr(const shared_ptr<_Tp1>& __r) noexcept
125f9a78e0eSmrg : _Base_type(__r) { }
126f9a78e0eSmrg
127f9a78e0eSmrg shared_ptr(shared_ptr&& __r) noexcept
128f9a78e0eSmrg : _Base_type(std::move(__r)) { }
129f9a78e0eSmrg
130f9a78e0eSmrg template<typename _Tp1, typename = _Compatible<_Tp1>>
131f9a78e0eSmrg shared_ptr(shared_ptr<_Tp1>&& __r) noexcept
132f9a78e0eSmrg : _Base_type(std::move(__r)) { }
133f9a78e0eSmrg
134f9a78e0eSmrg template<typename _Tp1, typename = _Compatible<_Tp1>>
135f9a78e0eSmrg explicit
136f9a78e0eSmrg shared_ptr(const weak_ptr<_Tp1>& __r)
137f9a78e0eSmrg : _Base_type(__r) { }
138f9a78e0eSmrg
139f9a78e0eSmrg #if _GLIBCXX_USE_DEPRECATED
140fb8a8121Smrg #pragma GCC diagnostic push
141fb8a8121Smrg #pragma GCC diagnostic ignored "-Wdeprecated-declarations"
142f9a78e0eSmrg template<typename _Tp1, typename = _Compatible<_Tp1>>
143f9a78e0eSmrg shared_ptr(std::auto_ptr<_Tp1>&& __r)
144f9a78e0eSmrg : _Base_type(std::move(__r))
145f9a78e0eSmrg { _M_enable_shared_from_this_with(static_cast<_Tp1*>(this->get())); }
146fb8a8121Smrg #pragma GCC diagnostic pop
147f9a78e0eSmrg #endif
148f9a78e0eSmrg
149f9a78e0eSmrg template<typename _Tp1, typename _Del,
150f9a78e0eSmrg typename = _UniqCompatible<_Tp1, _Del>>
151f9a78e0eSmrg shared_ptr(unique_ptr<_Tp1, _Del>&& __r)
152f9a78e0eSmrg : _Base_type(std::move(__r))
153f9a78e0eSmrg {
154f9a78e0eSmrg // XXX assume conversion from __r.get() to this->get() to __elem_t*
155f9a78e0eSmrg // is a round trip, which might not be true in all cases.
156f9a78e0eSmrg using __elem_t = typename unique_ptr<_Tp1, _Del>::element_type;
157f9a78e0eSmrg _M_enable_shared_from_this_with(static_cast<__elem_t*>(this->get()));
158f9a78e0eSmrg }
159f9a78e0eSmrg
160f9a78e0eSmrg constexpr shared_ptr(nullptr_t __p)
161f9a78e0eSmrg : _Base_type(__p) { }
162f9a78e0eSmrg
163181254a7Smrg // C++14 20.8.2.2
164f9a78e0eSmrg ~shared_ptr() = default;
165f9a78e0eSmrg
166181254a7Smrg // C++14 20.8.2.3
167f9a78e0eSmrg shared_ptr& operator=(const shared_ptr&) noexcept = default;
168f9a78e0eSmrg
169f9a78e0eSmrg template <typename _Tp1>
170f9a78e0eSmrg _Compatible<_Tp1, shared_ptr&>
171f9a78e0eSmrg operator=(const shared_ptr<_Tp1>& __r) noexcept
172f9a78e0eSmrg {
173f9a78e0eSmrg _Base_type::operator=(__r);
174f9a78e0eSmrg return *this;
175f9a78e0eSmrg }
176f9a78e0eSmrg
177f9a78e0eSmrg shared_ptr&
178f9a78e0eSmrg operator=(shared_ptr&& __r) noexcept
179f9a78e0eSmrg {
180f9a78e0eSmrg _Base_type::operator=(std::move(__r));
181f9a78e0eSmrg return *this;
182f9a78e0eSmrg }
183f9a78e0eSmrg
184f9a78e0eSmrg template <typename _Tp1>
185f9a78e0eSmrg _Compatible<_Tp1, shared_ptr&>
186f9a78e0eSmrg operator=(shared_ptr<_Tp1>&& __r) noexcept
187f9a78e0eSmrg {
188f9a78e0eSmrg _Base_type::operator=(std::move(__r));
189f9a78e0eSmrg return *this;
190f9a78e0eSmrg }
191f9a78e0eSmrg
192f9a78e0eSmrg #if _GLIBCXX_USE_DEPRECATED
193fb8a8121Smrg #pragma GCC diagnostic push
194fb8a8121Smrg #pragma GCC diagnostic ignored "-Wdeprecated-declarations"
195f9a78e0eSmrg template<typename _Tp1>
196f9a78e0eSmrg _Compatible<_Tp1, shared_ptr&>
197f9a78e0eSmrg operator=(std::auto_ptr<_Tp1>&& __r)
198f9a78e0eSmrg {
199f9a78e0eSmrg __shared_ptr<_Tp>::operator=(std::move(__r));
200f9a78e0eSmrg return *this;
201f9a78e0eSmrg }
202fb8a8121Smrg #pragma GCC diagnostic pop
203f9a78e0eSmrg #endif
204f9a78e0eSmrg
205f9a78e0eSmrg template <typename _Tp1, typename _Del>
206f9a78e0eSmrg _UniqCompatible<_Tp1, _Del, shared_ptr&>
207f9a78e0eSmrg operator=(unique_ptr<_Tp1, _Del>&& __r)
208f9a78e0eSmrg {
209f9a78e0eSmrg _Base_type::operator=(std::move(__r));
210f9a78e0eSmrg return *this;
211f9a78e0eSmrg }
212f9a78e0eSmrg
213181254a7Smrg // C++14 20.8.2.2.4
214f9a78e0eSmrg // swap & reset
215f9a78e0eSmrg // 8.2.1.2 shared_ptr observers
216f9a78e0eSmrg // in __shared_ptr
217f9a78e0eSmrg
218f9a78e0eSmrg private:
219f9a78e0eSmrg template<typename _Alloc, typename... _Args>
220f9a78e0eSmrg shared_ptr(_Sp_make_shared_tag __tag, const _Alloc& __a,
221f9a78e0eSmrg _Args&&... __args)
222f9a78e0eSmrg : _Base_type(__tag, __a, std::forward<_Args>(__args)...)
223f9a78e0eSmrg { _M_enable_shared_from_this_with(this->get()); }
224f9a78e0eSmrg
225f9a78e0eSmrg template<typename _Tp1, typename _Alloc, typename... _Args>
226f9a78e0eSmrg friend shared_ptr<_Tp1>
227f9a78e0eSmrg allocate_shared(const _Alloc& __a, _Args&&... __args);
228f9a78e0eSmrg
229f9a78e0eSmrg shared_ptr(const weak_ptr<_Tp>& __r, std::nothrow_t)
230f9a78e0eSmrg : _Base_type(__r, std::nothrow) { }
231f9a78e0eSmrg
232f9a78e0eSmrg friend class weak_ptr<_Tp>;
233f9a78e0eSmrg
234f9a78e0eSmrg template<typename _Yp>
235f9a78e0eSmrg using __esft_base_t =
236f9a78e0eSmrg decltype(__expt_enable_shared_from_this_base(std::declval<_Yp*>()));
237f9a78e0eSmrg
238f9a78e0eSmrg // Detect an accessible and unambiguous enable_shared_from_this base.
239f9a78e0eSmrg template<typename _Yp, typename = void>
240f9a78e0eSmrg struct __has_esft_base
241f9a78e0eSmrg : false_type { };
242f9a78e0eSmrg
243f9a78e0eSmrg template<typename _Yp>
244f9a78e0eSmrg struct __has_esft_base<_Yp, __void_t<__esft_base_t<_Yp>>>
245f9a78e0eSmrg : __bool_constant<!is_array_v<_Tp>> { }; // ignore base for arrays
246f9a78e0eSmrg
247f9a78e0eSmrg template<typename _Yp>
248f9a78e0eSmrg typename enable_if<__has_esft_base<_Yp>::value>::type
249f9a78e0eSmrg _M_enable_shared_from_this_with(const _Yp* __p) noexcept
250f9a78e0eSmrg {
251f9a78e0eSmrg if (auto __base = __expt_enable_shared_from_this_base(__p))
252f9a78e0eSmrg {
253f9a78e0eSmrg __base->_M_weak_this
254f9a78e0eSmrg = shared_ptr<_Yp>(*this, const_cast<_Yp*>(__p));
255f9a78e0eSmrg }
256f9a78e0eSmrg }
257f9a78e0eSmrg
258f9a78e0eSmrg template<typename _Yp>
259f9a78e0eSmrg typename enable_if<!__has_esft_base<_Yp>::value>::type
260f9a78e0eSmrg _M_enable_shared_from_this_with(const _Yp*) noexcept
261f9a78e0eSmrg { }
262f9a78e0eSmrg };
263f9a78e0eSmrg
264181254a7Smrg // C++14 20.8.2.2.7
265f9a78e0eSmrg template<typename _Tp1, typename _Tp2>
266f9a78e0eSmrg bool operator==(const shared_ptr<_Tp1>& __a,
267f9a78e0eSmrg const shared_ptr<_Tp2>& __b) noexcept
268f9a78e0eSmrg { return __a.get() == __b.get(); }
269f9a78e0eSmrg
270f9a78e0eSmrg template<typename _Tp>
271f9a78e0eSmrg inline bool
272f9a78e0eSmrg operator==(const shared_ptr<_Tp>& __a, nullptr_t) noexcept
273f9a78e0eSmrg { return !__a; }
274f9a78e0eSmrg
275f9a78e0eSmrg template<typename _Tp>
276f9a78e0eSmrg inline bool
277f9a78e0eSmrg operator==(nullptr_t, const shared_ptr<_Tp>& __a) noexcept
278f9a78e0eSmrg { return !__a; }
279f9a78e0eSmrg
280f9a78e0eSmrg template<typename _Tp1, typename _Tp2>
281f9a78e0eSmrg inline bool
282f9a78e0eSmrg operator!=(const shared_ptr<_Tp1>& __a,
283f9a78e0eSmrg const shared_ptr<_Tp2>& __b) noexcept
284f9a78e0eSmrg { return __a.get() != __b.get(); }
285f9a78e0eSmrg
286f9a78e0eSmrg template<typename _Tp>
287f9a78e0eSmrg inline bool
288f9a78e0eSmrg operator!=(const shared_ptr<_Tp>& __a, nullptr_t) noexcept
289f9a78e0eSmrg { return (bool)__a; }
290f9a78e0eSmrg
291f9a78e0eSmrg template<typename _Tp>
292f9a78e0eSmrg inline bool
293f9a78e0eSmrg operator!=(nullptr_t, const shared_ptr<_Tp>& __a) noexcept
294f9a78e0eSmrg { return (bool)__a; }
295f9a78e0eSmrg
296f9a78e0eSmrg template<typename _Tp1, typename _Tp2>
297f9a78e0eSmrg inline bool
298f9a78e0eSmrg operator<(const shared_ptr<_Tp1>& __a,
299f9a78e0eSmrg const shared_ptr<_Tp2>& __b) noexcept
300f9a78e0eSmrg {
301f9a78e0eSmrg using __elem_t1 = typename shared_ptr<_Tp1>::element_type;
302f9a78e0eSmrg using __elem_t2 = typename shared_ptr<_Tp2>::element_type;
303f9a78e0eSmrg using _CT = common_type_t<__elem_t1*, __elem_t2*>;
304f9a78e0eSmrg return std::less<_CT>()(__a.get(), __b.get());
305f9a78e0eSmrg }
306f9a78e0eSmrg
307f9a78e0eSmrg template<typename _Tp>
308f9a78e0eSmrg inline bool
309f9a78e0eSmrg operator<(const shared_ptr<_Tp>& __a, nullptr_t) noexcept
310f9a78e0eSmrg {
311f9a78e0eSmrg using __elem_t = typename shared_ptr<_Tp>::element_type;
312f9a78e0eSmrg return std::less<__elem_t*>()(__a.get(), nullptr);
313f9a78e0eSmrg }
314f9a78e0eSmrg
315f9a78e0eSmrg template<typename _Tp>
316f9a78e0eSmrg inline bool
317f9a78e0eSmrg operator<(nullptr_t, const shared_ptr<_Tp>& __a) noexcept
318f9a78e0eSmrg {
319f9a78e0eSmrg using __elem_t = typename shared_ptr<_Tp>::element_type;
320f9a78e0eSmrg return std::less<__elem_t*>()(nullptr, __a.get());
321f9a78e0eSmrg }
322f9a78e0eSmrg
323f9a78e0eSmrg template<typename _Tp1, typename _Tp2>
324f9a78e0eSmrg inline bool
325f9a78e0eSmrg operator<=(const shared_ptr<_Tp1>& __a,
326f9a78e0eSmrg const shared_ptr<_Tp2>& __b) noexcept
327f9a78e0eSmrg { return !(__b < __a); }
328f9a78e0eSmrg
329f9a78e0eSmrg template<typename _Tp>
330f9a78e0eSmrg inline bool
331f9a78e0eSmrg operator<=(const shared_ptr<_Tp>& __a, nullptr_t) noexcept
332f9a78e0eSmrg { return !(nullptr < __a); }
333f9a78e0eSmrg
334f9a78e0eSmrg template<typename _Tp>
335f9a78e0eSmrg inline bool
336f9a78e0eSmrg operator<=(nullptr_t, const shared_ptr<_Tp>& __a) noexcept
337f9a78e0eSmrg { return !(__a < nullptr); }
338f9a78e0eSmrg
339f9a78e0eSmrg template<typename _Tp1, typename _Tp2>
340f9a78e0eSmrg inline bool
341f9a78e0eSmrg operator>(const shared_ptr<_Tp1>& __a,
342f9a78e0eSmrg const shared_ptr<_Tp2>& __b) noexcept
343f9a78e0eSmrg { return (__b < __a); }
344f9a78e0eSmrg
345f9a78e0eSmrg template<typename _Tp>
346f9a78e0eSmrg inline bool
347f9a78e0eSmrg operator>(const shared_ptr<_Tp>& __a, nullptr_t) noexcept
348f9a78e0eSmrg {
349f9a78e0eSmrg using __elem_t = typename shared_ptr<_Tp>::element_type;
350f9a78e0eSmrg return std::less<__elem_t*>()(nullptr, __a.get());
351f9a78e0eSmrg }
352f9a78e0eSmrg
353f9a78e0eSmrg template<typename _Tp>
354f9a78e0eSmrg inline bool
355f9a78e0eSmrg operator>(nullptr_t, const shared_ptr<_Tp>& __a) noexcept
356f9a78e0eSmrg {
357f9a78e0eSmrg using __elem_t = typename shared_ptr<_Tp>::element_type;
358f9a78e0eSmrg return std::less<__elem_t*>()(__a.get(), nullptr);
359f9a78e0eSmrg }
360f9a78e0eSmrg
361f9a78e0eSmrg template<typename _Tp1, typename _Tp2>
362f9a78e0eSmrg inline bool
363f9a78e0eSmrg operator>=(const shared_ptr<_Tp1>& __a,
364f9a78e0eSmrg const shared_ptr<_Tp2>& __b) noexcept
365f9a78e0eSmrg { return !(__a < __b); }
366f9a78e0eSmrg
367f9a78e0eSmrg template<typename _Tp>
368f9a78e0eSmrg inline bool
369f9a78e0eSmrg operator>=(const shared_ptr<_Tp>& __a, nullptr_t) noexcept
370f9a78e0eSmrg { return !(__a < nullptr); }
371f9a78e0eSmrg
372f9a78e0eSmrg template<typename _Tp>
373f9a78e0eSmrg inline bool
374f9a78e0eSmrg operator>=(nullptr_t, const shared_ptr<_Tp>& __a) noexcept
375f9a78e0eSmrg { return !(nullptr < __a); }
376f9a78e0eSmrg
377181254a7Smrg // C++14 20.8.2.2.8
378f9a78e0eSmrg template<typename _Tp>
379f9a78e0eSmrg inline void
380f9a78e0eSmrg swap(shared_ptr<_Tp>& __a, shared_ptr<_Tp>& __b) noexcept
381f9a78e0eSmrg { __a.swap(__b); }
382f9a78e0eSmrg
383f9a78e0eSmrg // 8.2.1.3, shared_ptr casts
384f9a78e0eSmrg template<typename _Tp, typename _Tp1>
385f9a78e0eSmrg inline shared_ptr<_Tp>
386f9a78e0eSmrg static_pointer_cast(const shared_ptr<_Tp1>& __r) noexcept
387f9a78e0eSmrg {
388f9a78e0eSmrg using __elem_t = typename shared_ptr<_Tp>::element_type;
389f9a78e0eSmrg return shared_ptr<_Tp>(__r, static_cast<__elem_t*>(__r.get()));
390f9a78e0eSmrg }
391f9a78e0eSmrg
392f9a78e0eSmrg template<typename _Tp, typename _Tp1>
393f9a78e0eSmrg inline shared_ptr<_Tp>
394f9a78e0eSmrg dynamic_pointer_cast(const shared_ptr<_Tp1>& __r) noexcept
395f9a78e0eSmrg {
396f9a78e0eSmrg using __elem_t = typename shared_ptr<_Tp>::element_type;
397f9a78e0eSmrg if (_Tp* __p = dynamic_cast<__elem_t*>(__r.get()))
398f9a78e0eSmrg return shared_ptr<_Tp>(__r, __p);
399f9a78e0eSmrg return shared_ptr<_Tp>();
400f9a78e0eSmrg }
401f9a78e0eSmrg
402f9a78e0eSmrg template<typename _Tp, typename _Tp1>
403f9a78e0eSmrg inline shared_ptr<_Tp>
404f9a78e0eSmrg const_pointer_cast(const shared_ptr<_Tp1>& __r) noexcept
405f9a78e0eSmrg {
406f9a78e0eSmrg using __elem_t = typename shared_ptr<_Tp>::element_type;
407f9a78e0eSmrg return shared_ptr<_Tp>(__r, const_cast<__elem_t*>(__r.get()));
408f9a78e0eSmrg }
409f9a78e0eSmrg
410f9a78e0eSmrg template<typename _Tp, typename _Tp1>
411f9a78e0eSmrg inline shared_ptr<_Tp>
412f9a78e0eSmrg reinterpret_pointer_cast(const shared_ptr<_Tp1>& __r) noexcept
413f9a78e0eSmrg {
414f9a78e0eSmrg using __elem_t = typename shared_ptr<_Tp>::element_type;
415f9a78e0eSmrg return shared_ptr<_Tp>(__r, reinterpret_cast<__elem_t*>(__r.get()));
416f9a78e0eSmrg }
417f9a78e0eSmrg
418181254a7Smrg // C++14 20.8.2.3
419f9a78e0eSmrg template<typename _Tp>
420f9a78e0eSmrg class weak_ptr : public __weak_ptr<_Tp>
421f9a78e0eSmrg {
422f9a78e0eSmrg template<typename _Tp1, typename _Res = void>
423f9a78e0eSmrg using _Compatible = enable_if_t<__sp_compatible_v<_Tp1, _Tp>, _Res>;
424f9a78e0eSmrg
425f9a78e0eSmrg using _Base_type = __weak_ptr<_Tp>;
426f9a78e0eSmrg
427f9a78e0eSmrg public:
428f9a78e0eSmrg constexpr weak_ptr() noexcept = default;
429f9a78e0eSmrg
430f9a78e0eSmrg template<typename _Tp1, typename = _Compatible<_Tp1>>
431f9a78e0eSmrg weak_ptr(const shared_ptr<_Tp1>& __r) noexcept
432f9a78e0eSmrg : _Base_type(__r) { }
433f9a78e0eSmrg
434f9a78e0eSmrg weak_ptr(const weak_ptr&) noexcept = default;
435f9a78e0eSmrg
436f9a78e0eSmrg template<typename _Tp1, typename = _Compatible<_Tp1>>
437f9a78e0eSmrg weak_ptr(const weak_ptr<_Tp1>& __r) noexcept
438f9a78e0eSmrg : _Base_type(__r) { }
439f9a78e0eSmrg
440f9a78e0eSmrg weak_ptr(weak_ptr&&) noexcept = default;
441f9a78e0eSmrg
442f9a78e0eSmrg template<typename _Tp1, typename = _Compatible<_Tp1>>
443f9a78e0eSmrg weak_ptr(weak_ptr<_Tp1>&& __r) noexcept
444f9a78e0eSmrg : _Base_type(std::move(__r)) { }
445f9a78e0eSmrg
446f9a78e0eSmrg weak_ptr&
447f9a78e0eSmrg operator=(const weak_ptr& __r) noexcept = default;
448f9a78e0eSmrg
449f9a78e0eSmrg template<typename _Tp1>
450f9a78e0eSmrg _Compatible<_Tp1, weak_ptr&>
451f9a78e0eSmrg operator=(const weak_ptr<_Tp1>& __r) noexcept
452f9a78e0eSmrg {
453f9a78e0eSmrg this->_Base_type::operator=(__r);
454f9a78e0eSmrg return *this;
455f9a78e0eSmrg }
456f9a78e0eSmrg
457f9a78e0eSmrg template<typename _Tp1>
458f9a78e0eSmrg _Compatible<_Tp1, weak_ptr&>
459f9a78e0eSmrg operator=(const shared_ptr<_Tp1>& __r) noexcept
460f9a78e0eSmrg {
461f9a78e0eSmrg this->_Base_type::operator=(__r);
462f9a78e0eSmrg return *this;
463f9a78e0eSmrg }
464f9a78e0eSmrg
465f9a78e0eSmrg weak_ptr&
466f9a78e0eSmrg operator=(weak_ptr&& __r) noexcept = default;
467f9a78e0eSmrg
468f9a78e0eSmrg template<typename _Tp1>
469f9a78e0eSmrg _Compatible<_Tp1, weak_ptr&>
470f9a78e0eSmrg operator=(weak_ptr<_Tp1>&& __r) noexcept
471f9a78e0eSmrg {
472f9a78e0eSmrg this->_Base_type::operator=(std::move(__r));
473f9a78e0eSmrg return *this;
474f9a78e0eSmrg }
475f9a78e0eSmrg
476f9a78e0eSmrg shared_ptr<_Tp>
477f9a78e0eSmrg lock() const noexcept
478f9a78e0eSmrg { return shared_ptr<_Tp>(*this, std::nothrow); }
479f9a78e0eSmrg
480f9a78e0eSmrg friend class enable_shared_from_this<_Tp>;
481f9a78e0eSmrg };
482f9a78e0eSmrg
483181254a7Smrg // C++14 20.8.2.3.6
484f9a78e0eSmrg template<typename _Tp>
485f9a78e0eSmrg inline void
486f9a78e0eSmrg swap(weak_ptr<_Tp>& __a, weak_ptr<_Tp>& __b) noexcept
487f9a78e0eSmrg { __a.swap(__b); }
488f9a78e0eSmrg
489181254a7Smrg /// C++14 20.8.2.2.10
490b17d1066Smrg template<typename _Del, typename _Tp>
491f9a78e0eSmrg inline _Del*
492b17d1066Smrg get_deleter(const shared_ptr<_Tp>& __p) noexcept
493f9a78e0eSmrg { return std::get_deleter<_Del>(__p); }
494f9a78e0eSmrg
495181254a7Smrg // C++14 20.8.2.2.11
496b17d1066Smrg template<typename _Ch, typename _Tr, typename _Tp>
497f9a78e0eSmrg inline std::basic_ostream<_Ch, _Tr>&
498b17d1066Smrg operator<<(std::basic_ostream<_Ch, _Tr>& __os, const shared_ptr<_Tp>& __p)
499f9a78e0eSmrg {
500f9a78e0eSmrg __os << __p.get();
501f9a78e0eSmrg return __os;
502f9a78e0eSmrg }
503f9a78e0eSmrg
504181254a7Smrg // C++14 20.8.2.4
505f9a78e0eSmrg template<typename _Tp = void> class owner_less;
506f9a78e0eSmrg
507f9a78e0eSmrg /// Partial specialization of owner_less for shared_ptr.
508f9a78e0eSmrg template<typename _Tp>
509f9a78e0eSmrg struct owner_less<shared_ptr<_Tp>>
510f9a78e0eSmrg : public _Sp_owner_less<shared_ptr<_Tp>, weak_ptr<_Tp>>
511f9a78e0eSmrg { };
512f9a78e0eSmrg
513f9a78e0eSmrg /// Partial specialization of owner_less for weak_ptr.
514f9a78e0eSmrg template<typename _Tp>
515f9a78e0eSmrg struct owner_less<weak_ptr<_Tp>>
516f9a78e0eSmrg : public _Sp_owner_less<weak_ptr<_Tp>, shared_ptr<_Tp>>
517f9a78e0eSmrg { };
518f9a78e0eSmrg
519f9a78e0eSmrg template<>
520f9a78e0eSmrg class owner_less<void>
521f9a78e0eSmrg {
522f9a78e0eSmrg template<typename _Tp, typename _Up>
523f9a78e0eSmrg bool
524f9a78e0eSmrg operator()(shared_ptr<_Tp> const& __lhs,
525f9a78e0eSmrg shared_ptr<_Up> const& __rhs) const
526f9a78e0eSmrg { return __lhs.owner_before(__rhs); }
527f9a78e0eSmrg
528f9a78e0eSmrg template<typename _Tp, typename _Up>
529f9a78e0eSmrg bool
530f9a78e0eSmrg operator()(shared_ptr<_Tp> const& __lhs,
531f9a78e0eSmrg weak_ptr<_Up> const& __rhs) const
532f9a78e0eSmrg { return __lhs.owner_before(__rhs); }
533f9a78e0eSmrg
534f9a78e0eSmrg template<typename _Tp, typename _Up>
535f9a78e0eSmrg bool
536f9a78e0eSmrg operator()(weak_ptr<_Tp> const& __lhs,
537f9a78e0eSmrg shared_ptr<_Up> const& __rhs) const
538f9a78e0eSmrg { return __lhs.owner_before(__rhs); }
539f9a78e0eSmrg
540f9a78e0eSmrg template<typename _Tp, typename _Up>
541f9a78e0eSmrg bool
542f9a78e0eSmrg operator()(weak_ptr<_Tp> const& __lhs,
543f9a78e0eSmrg weak_ptr<_Up> const& __rhs) const
544f9a78e0eSmrg { return __lhs.owner_before(__rhs); }
545f9a78e0eSmrg
546f9a78e0eSmrg typedef void is_transparent;
547f9a78e0eSmrg };
548f9a78e0eSmrg
549181254a7Smrg // C++14 20.8.2.6
550f9a78e0eSmrg template<typename _Tp>
551f9a78e0eSmrg inline bool
552f9a78e0eSmrg atomic_is_lock_free(const shared_ptr<_Tp>* __p)
553f9a78e0eSmrg { return std::atomic_is_lock_free<_Tp, __default_lock_policy>(__p); }
554f9a78e0eSmrg
555f9a78e0eSmrg template<typename _Tp>
556f9a78e0eSmrg shared_ptr<_Tp> atomic_load(const shared_ptr<_Tp>* __p)
557f9a78e0eSmrg { return std::atomic_load<_Tp>(__p); }
558f9a78e0eSmrg
559f9a78e0eSmrg template<typename _Tp>
560f9a78e0eSmrg shared_ptr<_Tp>
561f9a78e0eSmrg atomic_load_explicit(const shared_ptr<_Tp>* __p, memory_order __mo)
562f9a78e0eSmrg { return std::atomic_load_explicit<_Tp>(__p, __mo); }
563f9a78e0eSmrg
564f9a78e0eSmrg template<typename _Tp>
565f9a78e0eSmrg void atomic_store(shared_ptr<_Tp>* __p, shared_ptr<_Tp> __r)
566f9a78e0eSmrg { return std::atomic_store<_Tp>(__p, __r); }
567f9a78e0eSmrg
568f9a78e0eSmrg template<typename _Tp>
569f9a78e0eSmrg shared_ptr<_Tp>
570f9a78e0eSmrg atomic_store_explicit(const shared_ptr<_Tp>* __p,
571f9a78e0eSmrg shared_ptr<_Tp> __r,
572f9a78e0eSmrg memory_order __mo)
573f9a78e0eSmrg { return std::atomic_store_explicit<_Tp>(__p, __r, __mo); }
574f9a78e0eSmrg
575f9a78e0eSmrg template<typename _Tp>
576f9a78e0eSmrg void atomic_exchange(shared_ptr<_Tp>* __p, shared_ptr<_Tp> __r)
577f9a78e0eSmrg { return std::atomic_exchange<_Tp>(__p, __r); }
578f9a78e0eSmrg
579f9a78e0eSmrg template<typename _Tp>
580f9a78e0eSmrg shared_ptr<_Tp>
581f9a78e0eSmrg atomic_exchange_explicit(const shared_ptr<_Tp>* __p,
582f9a78e0eSmrg shared_ptr<_Tp> __r,
583f9a78e0eSmrg memory_order __mo)
584f9a78e0eSmrg { return std::atomic_exchange_explicit<_Tp>(__p, __r, __mo); }
585f9a78e0eSmrg
586f9a78e0eSmrg template<typename _Tp>
587f9a78e0eSmrg bool atomic_compare_exchange_weak(shared_ptr<_Tp>* __p,
588f9a78e0eSmrg shared_ptr<_Tp>* __v,
589f9a78e0eSmrg shared_ptr<_Tp> __w)
590f9a78e0eSmrg { return std::atomic_compare_exchange_weak<_Tp>(__p, __v, __w); }
591f9a78e0eSmrg
592f9a78e0eSmrg template<typename _Tp>
593f9a78e0eSmrg bool atomic_compare_exchange_strong(shared_ptr<_Tp>* __p,
594f9a78e0eSmrg shared_ptr<_Tp>* __v,
595f9a78e0eSmrg shared_ptr<_Tp> __w)
596f9a78e0eSmrg { return std::atomic_compare_exchange_strong<_Tp>(__p, __v, __w); }
597f9a78e0eSmrg
598f9a78e0eSmrg template<typename _Tp>
599f9a78e0eSmrg bool atomic_compare_exchange_weak_explicit(shared_ptr<_Tp>* __p,
600f9a78e0eSmrg shared_ptr<_Tp>* __v,
601f9a78e0eSmrg shared_ptr<_Tp> __w,
602f9a78e0eSmrg memory_order __success,
603f9a78e0eSmrg memory_order __failure)
604f9a78e0eSmrg { return std::atomic_compare_exchange_weak_explicit<_Tp>(__p, __v, __w,
605f9a78e0eSmrg __success,
606f9a78e0eSmrg __failure); }
607f9a78e0eSmrg
608f9a78e0eSmrg template<typename _Tp>
609f9a78e0eSmrg bool atomic_compare_exchange_strong_explicit(shared_ptr<_Tp>* __p,
610f9a78e0eSmrg shared_ptr<_Tp>* __v,
611f9a78e0eSmrg shared_ptr<_Tp> __w,
612f9a78e0eSmrg memory_order __success,
613f9a78e0eSmrg memory_order __failure)
614f9a78e0eSmrg { return std::atomic_compare_exchange_strong_explicit<_Tp>(__p, __v, __w,
615f9a78e0eSmrg __success,
616f9a78e0eSmrg __failure); }
617f9a78e0eSmrg
618f9a78e0eSmrg //enable_shared_from_this
619f9a78e0eSmrg template<typename _Tp>
620f9a78e0eSmrg class enable_shared_from_this
621f9a78e0eSmrg {
622f9a78e0eSmrg protected:
623f9a78e0eSmrg constexpr enable_shared_from_this() noexcept { }
624f9a78e0eSmrg
625f9a78e0eSmrg enable_shared_from_this(const enable_shared_from_this&) noexcept { }
626f9a78e0eSmrg
627f9a78e0eSmrg enable_shared_from_this&
628f9a78e0eSmrg operator=(const enable_shared_from_this&) noexcept
629f9a78e0eSmrg { return *this; }
630f9a78e0eSmrg
631f9a78e0eSmrg ~enable_shared_from_this() { }
632f9a78e0eSmrg
633f9a78e0eSmrg public:
634f9a78e0eSmrg shared_ptr<_Tp>
635f9a78e0eSmrg shared_from_this()
636f9a78e0eSmrg { return shared_ptr<_Tp>(this->_M_weak_this); }
637f9a78e0eSmrg
638f9a78e0eSmrg shared_ptr<const _Tp>
639f9a78e0eSmrg shared_from_this() const
640f9a78e0eSmrg { return shared_ptr<const _Tp>(this->_M_weak_this); }
641f9a78e0eSmrg
642f9a78e0eSmrg weak_ptr<_Tp>
643f9a78e0eSmrg weak_from_this() noexcept
644f9a78e0eSmrg { return _M_weak_this; }
645f9a78e0eSmrg
646f9a78e0eSmrg weak_ptr<const _Tp>
647f9a78e0eSmrg weak_from_this() const noexcept
648f9a78e0eSmrg { return _M_weak_this; }
649f9a78e0eSmrg
650f9a78e0eSmrg private:
651f9a78e0eSmrg template<typename _Tp1>
652f9a78e0eSmrg void
653f9a78e0eSmrg _M_weak_assign(_Tp1* __p, const __shared_count<>& __n) const noexcept
654f9a78e0eSmrg { _M_weak_this._M_assign(__p, __n); }
655f9a78e0eSmrg
656f9a78e0eSmrg // Found by ADL when this is an associated class.
657f9a78e0eSmrg friend const enable_shared_from_this*
658f9a78e0eSmrg __expt_enable_shared_from_this_base(const enable_shared_from_this* __p)
659f9a78e0eSmrg { return __p; }
660f9a78e0eSmrg
661f9a78e0eSmrg template<typename>
662f9a78e0eSmrg friend class shared_ptr;
663f9a78e0eSmrg
664f9a78e0eSmrg mutable weak_ptr<_Tp> _M_weak_this;
665f9a78e0eSmrg };
666f9a78e0eSmrg } // namespace fundamentals_v2
667f9a78e0eSmrg } // namespace experimental
668f9a78e0eSmrg
669f9a78e0eSmrg /// std::hash specialization for shared_ptr.
670f9a78e0eSmrg template<typename _Tp>
671f9a78e0eSmrg struct hash<experimental::shared_ptr<_Tp>>
672f9a78e0eSmrg : public __hash_base<size_t, experimental::shared_ptr<_Tp>>
673f9a78e0eSmrg {
674f9a78e0eSmrg size_t
675f9a78e0eSmrg operator()(const experimental::shared_ptr<_Tp>& __s) const noexcept
676f9a78e0eSmrg { return std::hash<_Tp*>()(__s.get()); }
677f9a78e0eSmrg };
678f9a78e0eSmrg
679f9a78e0eSmrg _GLIBCXX_END_NAMESPACE_VERSION
680f9a78e0eSmrg } // namespace std
681f9a78e0eSmrg
682f9a78e0eSmrg #endif // __cplusplus <= 201103L
683f9a78e0eSmrg
684f9a78e0eSmrg #endif // _GLIBCXX_EXPERIMENTAL_SHARED_PTR_H
685