1 | // shared_ptr and weak_ptr implementation -*- C++ -*-
|
---|
2 |
|
---|
3 | // Copyright (C) 2007-2021 Free Software Foundation, Inc.
|
---|
4 | //
|
---|
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)
|
---|
9 | // any later version.
|
---|
10 |
|
---|
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.
|
---|
15 |
|
---|
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.
|
---|
19 |
|
---|
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/>.
|
---|
24 |
|
---|
25 | // GCC Note: Based on files from version 1.32.0 of the Boost library.
|
---|
26 |
|
---|
27 | // shared_count.hpp
|
---|
28 | // Copyright (c) 2001, 2002, 2003 Peter Dimov and Multi Media Ltd.
|
---|
29 |
|
---|
30 | // shared_ptr.hpp
|
---|
31 | // Copyright (C) 1998, 1999 Greg Colvin and Beman Dawes.
|
---|
32 | // Copyright (C) 2001, 2002, 2003 Peter Dimov
|
---|
33 |
|
---|
34 | // weak_ptr.hpp
|
---|
35 | // Copyright (C) 2001, 2002, 2003 Peter Dimov
|
---|
36 |
|
---|
37 | // enable_shared_from_this.hpp
|
---|
38 | // Copyright (C) 2002 Peter Dimov
|
---|
39 |
|
---|
40 | // Distributed under the Boost Software License, Version 1.0. (See
|
---|
41 | // accompanying file LICENSE_1_0.txt or copy at
|
---|
42 | // http://www.boost.org/LICENSE_1_0.txt)
|
---|
43 |
|
---|
44 | /** @file
|
---|
45 | * This is an internal header file, included by other library headers.
|
---|
46 | * Do not attempt to use it directly. @headername{memory}
|
---|
47 | */
|
---|
48 |
|
---|
49 | #ifndef _SHARED_PTR_H
|
---|
50 | #define _SHARED_PTR_H 1
|
---|
51 |
|
---|
52 | #include <iosfwd> // std::basic_ostream
|
---|
53 | #include <bits/shared_ptr_base.h>
|
---|
54 |
|
---|
55 | namespace std _GLIBCXX_VISIBILITY(default)
|
---|
56 | {
|
---|
57 | _GLIBCXX_BEGIN_NAMESPACE_VERSION
|
---|
58 |
|
---|
59 | /**
|
---|
60 | * @addtogroup pointer_abstractions
|
---|
61 | * @{
|
---|
62 | */
|
---|
63 |
|
---|
64 | // 20.7.2.2.11 shared_ptr I/O
|
---|
65 |
|
---|
66 | /// Write the stored pointer to an ostream.
|
---|
67 | /// @relates shared_ptr
|
---|
68 | template<typename _Ch, typename _Tr, typename _Tp, _Lock_policy _Lp>
|
---|
69 | inline std::basic_ostream<_Ch, _Tr>&
|
---|
70 | operator<<(std::basic_ostream<_Ch, _Tr>& __os,
|
---|
71 | const __shared_ptr<_Tp, _Lp>& __p)
|
---|
72 | {
|
---|
73 | __os << __p.get();
|
---|
74 | return __os;
|
---|
75 | }
|
---|
76 |
|
---|
77 | template<typename _Del, typename _Tp, _Lock_policy _Lp>
|
---|
78 | inline _Del*
|
---|
79 | get_deleter(const __shared_ptr<_Tp, _Lp>& __p) noexcept
|
---|
80 | {
|
---|
81 | #if __cpp_rtti
|
---|
82 | return static_cast<_Del*>(__p._M_get_deleter(typeid(_Del)));
|
---|
83 | #else
|
---|
84 | return 0;
|
---|
85 | #endif
|
---|
86 | }
|
---|
87 |
|
---|
88 | /// 20.7.2.2.10 shared_ptr get_deleter
|
---|
89 |
|
---|
90 | /// If `__p` has a deleter of type `_Del`, return a pointer to it.
|
---|
91 | /// @relates shared_ptr
|
---|
92 | template<typename _Del, typename _Tp>
|
---|
93 | inline _Del*
|
---|
94 | get_deleter(const shared_ptr<_Tp>& __p) noexcept
|
---|
95 | {
|
---|
96 | #if __cpp_rtti
|
---|
97 | return static_cast<_Del*>(__p._M_get_deleter(typeid(_Del)));
|
---|
98 | #else
|
---|
99 | return 0;
|
---|
100 | #endif
|
---|
101 | }
|
---|
102 |
|
---|
103 | /**
|
---|
104 | * @brief A smart pointer with reference-counted copy semantics.
|
---|
105 | *
|
---|
106 | * A `shared_ptr` object is either empty or _owns_ a pointer passed
|
---|
107 | * to the constructor. Copies of a `shared_ptr` share ownership of
|
---|
108 | * the same pointer. When the last `shared_ptr` that owns the pointer
|
---|
109 | * is destroyed or reset, the owned pointer is freed (either by `delete`
|
---|
110 | * or by invoking a custom deleter that was passed to the constructor).
|
---|
111 | *
|
---|
112 | * A `shared_ptr` also stores another pointer, which is usually
|
---|
113 | * (but not always) the same pointer as it owns. The stored pointer
|
---|
114 | * can be retrieved by calling the `get()` member function.
|
---|
115 | *
|
---|
116 | * The equality and relational operators for `shared_ptr` only compare
|
---|
117 | * the stored pointer returned by `get()`, not the owned pointer.
|
---|
118 | * To test whether two `shared_ptr` objects share ownership of the same
|
---|
119 | * pointer see `std::shared_ptr::owner_before` and `std::owner_less`.
|
---|
120 | */
|
---|
121 | template<typename _Tp>
|
---|
122 | class shared_ptr : public __shared_ptr<_Tp>
|
---|
123 | {
|
---|
124 | template<typename... _Args>
|
---|
125 | using _Constructible = typename enable_if<
|
---|
126 | is_constructible<__shared_ptr<_Tp>, _Args...>::value
|
---|
127 | >::type;
|
---|
128 |
|
---|
129 | template<typename _Arg>
|
---|
130 | using _Assignable = typename enable_if<
|
---|
131 | is_assignable<__shared_ptr<_Tp>&, _Arg>::value, shared_ptr&
|
---|
132 | >::type;
|
---|
133 |
|
---|
134 | public:
|
---|
135 |
|
---|
136 | /// The type pointed to by the stored pointer, remove_extent_t<_Tp>
|
---|
137 | using element_type = typename __shared_ptr<_Tp>::element_type;
|
---|
138 |
|
---|
139 | #if __cplusplus >= 201703L
|
---|
140 | # define __cpp_lib_shared_ptr_weak_type 201606
|
---|
141 | /// The corresponding weak_ptr type for this shared_ptr
|
---|
142 | using weak_type = weak_ptr<_Tp>;
|
---|
143 | #endif
|
---|
144 | /**
|
---|
145 | * @brief Construct an empty %shared_ptr.
|
---|
146 | * @post use_count()==0 && get()==0
|
---|
147 | */
|
---|
148 | constexpr shared_ptr() noexcept : __shared_ptr<_Tp>() { }
|
---|
149 |
|
---|
150 | shared_ptr(const shared_ptr&) noexcept = default; ///< Copy constructor
|
---|
151 |
|
---|
152 | /**
|
---|
153 | * @brief Construct a %shared_ptr that owns the pointer @a __p.
|
---|
154 | * @param __p A pointer that is convertible to element_type*.
|
---|
155 | * @post use_count() == 1 && get() == __p
|
---|
156 | * @throw std::bad_alloc, in which case @c delete @a __p is called.
|
---|
157 | */
|
---|
158 | template<typename _Yp, typename = _Constructible<_Yp*>>
|
---|
159 | explicit
|
---|
160 | shared_ptr(_Yp* __p) : __shared_ptr<_Tp>(__p) { }
|
---|
161 |
|
---|
162 | /**
|
---|
163 | * @brief Construct a %shared_ptr that owns the pointer @a __p
|
---|
164 | * and the deleter @a __d.
|
---|
165 | * @param __p A pointer.
|
---|
166 | * @param __d A deleter.
|
---|
167 | * @post use_count() == 1 && get() == __p
|
---|
168 | * @throw std::bad_alloc, in which case @a __d(__p) is called.
|
---|
169 | *
|
---|
170 | * Requirements: _Deleter's copy constructor and destructor must
|
---|
171 | * not throw
|
---|
172 | *
|
---|
173 | * __shared_ptr will release __p by calling __d(__p)
|
---|
174 | */
|
---|
175 | template<typename _Yp, typename _Deleter,
|
---|
176 | typename = _Constructible<_Yp*, _Deleter>>
|
---|
177 | shared_ptr(_Yp* __p, _Deleter __d)
|
---|
178 | : __shared_ptr<_Tp>(__p, std::move(__d)) { }
|
---|
179 |
|
---|
180 | /**
|
---|
181 | * @brief Construct a %shared_ptr that owns a null pointer
|
---|
182 | * and the deleter @a __d.
|
---|
183 | * @param __p A null pointer constant.
|
---|
184 | * @param __d A deleter.
|
---|
185 | * @post use_count() == 1 && get() == __p
|
---|
186 | * @throw std::bad_alloc, in which case @a __d(__p) is called.
|
---|
187 | *
|
---|
188 | * Requirements: _Deleter's copy constructor and destructor must
|
---|
189 | * not throw
|
---|
190 | *
|
---|
191 | * The last owner will call __d(__p)
|
---|
192 | */
|
---|
193 | template<typename _Deleter>
|
---|
194 | shared_ptr(nullptr_t __p, _Deleter __d)
|
---|
195 | : __shared_ptr<_Tp>(__p, std::move(__d)) { }
|
---|
196 |
|
---|
197 | /**
|
---|
198 | * @brief Construct a %shared_ptr that owns the pointer @a __p
|
---|
199 | * and the deleter @a __d.
|
---|
200 | * @param __p A pointer.
|
---|
201 | * @param __d A deleter.
|
---|
202 | * @param __a An allocator.
|
---|
203 | * @post use_count() == 1 && get() == __p
|
---|
204 | * @throw std::bad_alloc, in which case @a __d(__p) is called.
|
---|
205 | *
|
---|
206 | * Requirements: _Deleter's copy constructor and destructor must
|
---|
207 | * not throw _Alloc's copy constructor and destructor must not
|
---|
208 | * throw.
|
---|
209 | *
|
---|
210 | * __shared_ptr will release __p by calling __d(__p)
|
---|
211 | */
|
---|
212 | template<typename _Yp, typename _Deleter, typename _Alloc,
|
---|
213 | typename = _Constructible<_Yp*, _Deleter, _Alloc>>
|
---|
214 | shared_ptr(_Yp* __p, _Deleter __d, _Alloc __a)
|
---|
215 | : __shared_ptr<_Tp>(__p, std::move(__d), std::move(__a)) { }
|
---|
216 |
|
---|
217 | /**
|
---|
218 | * @brief Construct a %shared_ptr that owns a null pointer
|
---|
219 | * and the deleter @a __d.
|
---|
220 | * @param __p A null pointer constant.
|
---|
221 | * @param __d A deleter.
|
---|
222 | * @param __a An allocator.
|
---|
223 | * @post use_count() == 1 && get() == __p
|
---|
224 | * @throw std::bad_alloc, in which case @a __d(__p) is called.
|
---|
225 | *
|
---|
226 | * Requirements: _Deleter's copy constructor and destructor must
|
---|
227 | * not throw _Alloc's copy constructor and destructor must not
|
---|
228 | * throw.
|
---|
229 | *
|
---|
230 | * The last owner will call __d(__p)
|
---|
231 | */
|
---|
232 | template<typename _Deleter, typename _Alloc>
|
---|
233 | shared_ptr(nullptr_t __p, _Deleter __d, _Alloc __a)
|
---|
234 | : __shared_ptr<_Tp>(__p, std::move(__d), std::move(__a)) { }
|
---|
235 |
|
---|
236 | // Aliasing constructor
|
---|
237 |
|
---|
238 | /**
|
---|
239 | * @brief Constructs a `shared_ptr` instance that stores `__p`
|
---|
240 | * and shares ownership with `__r`.
|
---|
241 | * @param __r A `shared_ptr`.
|
---|
242 | * @param __p A pointer that will remain valid while `*__r` is valid.
|
---|
243 | * @post `get() == __p && use_count() == __r.use_count()`
|
---|
244 | *
|
---|
245 | * This can be used to construct a `shared_ptr` to a sub-object
|
---|
246 | * of an object managed by an existing `shared_ptr`. The complete
|
---|
247 | * object will remain valid while any `shared_ptr` owns it, even
|
---|
248 | * if they don't store a pointer to the complete object.
|
---|
249 | *
|
---|
250 | * @code
|
---|
251 | * shared_ptr<pair<int,int>> pii(new pair<int,int>());
|
---|
252 | * shared_ptr<int> pi(pii, &pii->first);
|
---|
253 | * assert(pii.use_count() == 2);
|
---|
254 | * @endcode
|
---|
255 | */
|
---|
256 | template<typename _Yp>
|
---|
257 | shared_ptr(const shared_ptr<_Yp>& __r, element_type* __p) noexcept
|
---|
258 | : __shared_ptr<_Tp>(__r, __p) { }
|
---|
259 |
|
---|
260 | #if __cplusplus > 201703L
|
---|
261 | // _GLIBCXX_RESOLVE_LIB_DEFECTS
|
---|
262 | // 2996. Missing rvalue overloads for shared_ptr operations
|
---|
263 | /**
|
---|
264 | * @brief Constructs a `shared_ptr` instance that stores `__p`
|
---|
265 | * and shares ownership with `__r`.
|
---|
266 | * @param __r A `shared_ptr`.
|
---|
267 | * @param __p A pointer that will remain valid while `*__r` is valid.
|
---|
268 | * @post `get() == __p && !__r.use_count() && !__r.get()`
|
---|
269 | *
|
---|
270 | * This can be used to construct a `shared_ptr` to a sub-object
|
---|
271 | * of an object managed by an existing `shared_ptr`. The complete
|
---|
272 | * object will remain valid while any `shared_ptr` owns it, even
|
---|
273 | * if they don't store a pointer to the complete object.
|
---|
274 | *
|
---|
275 | * @code
|
---|
276 | * shared_ptr<pair<int,int>> pii(new pair<int,int>());
|
---|
277 | * shared_ptr<int> pi1(pii, &pii->first);
|
---|
278 | * assert(pii.use_count() == 2);
|
---|
279 | * shared_ptr<int> pi2(std::move(pii), &pii->second);
|
---|
280 | * assert(pii.use_count() == 0);
|
---|
281 | * @endcode
|
---|
282 | */
|
---|
283 | template<typename _Yp>
|
---|
284 | shared_ptr(shared_ptr<_Yp>&& __r, element_type* __p) noexcept
|
---|
285 | : __shared_ptr<_Tp>(std::move(__r), __p) { }
|
---|
286 | #endif
|
---|
287 | /**
|
---|
288 | * @brief If @a __r is empty, constructs an empty %shared_ptr;
|
---|
289 | * otherwise construct a %shared_ptr that shares ownership
|
---|
290 | * with @a __r.
|
---|
291 | * @param __r A %shared_ptr.
|
---|
292 | * @post get() == __r.get() && use_count() == __r.use_count()
|
---|
293 | */
|
---|
294 | template<typename _Yp,
|
---|
295 | typename = _Constructible<const shared_ptr<_Yp>&>>
|
---|
296 | shared_ptr(const shared_ptr<_Yp>& __r) noexcept
|
---|
297 | : __shared_ptr<_Tp>(__r) { }
|
---|
298 |
|
---|
299 | /**
|
---|
300 | * @brief Move-constructs a %shared_ptr instance from @a __r.
|
---|
301 | * @param __r A %shared_ptr rvalue.
|
---|
302 | * @post *this contains the old value of @a __r, @a __r is empty.
|
---|
303 | */
|
---|
304 | shared_ptr(shared_ptr&& __r) noexcept
|
---|
305 | : __shared_ptr<_Tp>(std::move(__r)) { }
|
---|
306 |
|
---|
307 | /**
|
---|
308 | * @brief Move-constructs a %shared_ptr instance from @a __r.
|
---|
309 | * @param __r A %shared_ptr rvalue.
|
---|
310 | * @post *this contains the old value of @a __r, @a __r is empty.
|
---|
311 | */
|
---|
312 | template<typename _Yp, typename = _Constructible<shared_ptr<_Yp>>>
|
---|
313 | shared_ptr(shared_ptr<_Yp>&& __r) noexcept
|
---|
314 | : __shared_ptr<_Tp>(std::move(__r)) { }
|
---|
315 |
|
---|
316 | /**
|
---|
317 | * @brief Constructs a %shared_ptr that shares ownership with @a __r
|
---|
318 | * and stores a copy of the pointer stored in @a __r.
|
---|
319 | * @param __r A weak_ptr.
|
---|
320 | * @post use_count() == __r.use_count()
|
---|
321 | * @throw bad_weak_ptr when __r.expired(),
|
---|
322 | * in which case the constructor has no effect.
|
---|
323 | */
|
---|
324 | template<typename _Yp, typename = _Constructible<const weak_ptr<_Yp>&>>
|
---|
325 | explicit shared_ptr(const weak_ptr<_Yp>& __r)
|
---|
326 | : __shared_ptr<_Tp>(__r) { }
|
---|
327 |
|
---|
328 | #if _GLIBCXX_USE_DEPRECATED
|
---|
329 | #pragma GCC diagnostic push
|
---|
330 | #pragma GCC diagnostic ignored "-Wdeprecated-declarations"
|
---|
331 | template<typename _Yp, typename = _Constructible<auto_ptr<_Yp>>>
|
---|
332 | shared_ptr(auto_ptr<_Yp>&& __r);
|
---|
333 | #pragma GCC diagnostic pop
|
---|
334 | #endif
|
---|
335 |
|
---|
336 | // _GLIBCXX_RESOLVE_LIB_DEFECTS
|
---|
337 | // 2399. shared_ptr's constructor from unique_ptr should be constrained
|
---|
338 | template<typename _Yp, typename _Del,
|
---|
339 | typename = _Constructible<unique_ptr<_Yp, _Del>>>
|
---|
340 | shared_ptr(unique_ptr<_Yp, _Del>&& __r)
|
---|
341 | : __shared_ptr<_Tp>(std::move(__r)) { }
|
---|
342 |
|
---|
343 | #if __cplusplus <= 201402L && _GLIBCXX_USE_DEPRECATED
|
---|
344 | // This non-standard constructor exists to support conversions that
|
---|
345 | // were possible in C++11 and C++14 but are ill-formed in C++17.
|
---|
346 | // If an exception is thrown this constructor has no effect.
|
---|
347 | template<typename _Yp, typename _Del,
|
---|
348 | _Constructible<unique_ptr<_Yp, _Del>, __sp_array_delete>* = 0>
|
---|
349 | shared_ptr(unique_ptr<_Yp, _Del>&& __r)
|
---|
350 | : __shared_ptr<_Tp>(std::move(__r), __sp_array_delete()) { }
|
---|
351 | #endif
|
---|
352 |
|
---|
353 | /**
|
---|
354 | * @brief Construct an empty %shared_ptr.
|
---|
355 | * @post use_count() == 0 && get() == nullptr
|
---|
356 | */
|
---|
357 | constexpr shared_ptr(nullptr_t) noexcept : shared_ptr() { }
|
---|
358 |
|
---|
359 | shared_ptr& operator=(const shared_ptr&) noexcept = default;
|
---|
360 |
|
---|
361 | template<typename _Yp>
|
---|
362 | _Assignable<const shared_ptr<_Yp>&>
|
---|
363 | operator=(const shared_ptr<_Yp>& __r) noexcept
|
---|
364 | {
|
---|
365 | this->__shared_ptr<_Tp>::operator=(__r);
|
---|
366 | return *this;
|
---|
367 | }
|
---|
368 |
|
---|
369 | #if _GLIBCXX_USE_DEPRECATED
|
---|
370 | #pragma GCC diagnostic push
|
---|
371 | #pragma GCC diagnostic ignored "-Wdeprecated-declarations"
|
---|
372 | template<typename _Yp>
|
---|
373 | _Assignable<auto_ptr<_Yp>>
|
---|
374 | operator=(auto_ptr<_Yp>&& __r)
|
---|
375 | {
|
---|
376 | this->__shared_ptr<_Tp>::operator=(std::move(__r));
|
---|
377 | return *this;
|
---|
378 | }
|
---|
379 | #pragma GCC diagnostic pop
|
---|
380 | #endif
|
---|
381 |
|
---|
382 | shared_ptr&
|
---|
383 | operator=(shared_ptr&& __r) noexcept
|
---|
384 | {
|
---|
385 | this->__shared_ptr<_Tp>::operator=(std::move(__r));
|
---|
386 | return *this;
|
---|
387 | }
|
---|
388 |
|
---|
389 | template<class _Yp>
|
---|
390 | _Assignable<shared_ptr<_Yp>>
|
---|
391 | operator=(shared_ptr<_Yp>&& __r) noexcept
|
---|
392 | {
|
---|
393 | this->__shared_ptr<_Tp>::operator=(std::move(__r));
|
---|
394 | return *this;
|
---|
395 | }
|
---|
396 |
|
---|
397 | template<typename _Yp, typename _Del>
|
---|
398 | _Assignable<unique_ptr<_Yp, _Del>>
|
---|
399 | operator=(unique_ptr<_Yp, _Del>&& __r)
|
---|
400 | {
|
---|
401 | this->__shared_ptr<_Tp>::operator=(std::move(__r));
|
---|
402 | return *this;
|
---|
403 | }
|
---|
404 |
|
---|
405 | private:
|
---|
406 | // This constructor is non-standard, it is used by allocate_shared.
|
---|
407 | template<typename _Alloc, typename... _Args>
|
---|
408 | shared_ptr(_Sp_alloc_shared_tag<_Alloc> __tag, _Args&&... __args)
|
---|
409 | : __shared_ptr<_Tp>(__tag, std::forward<_Args>(__args)...)
|
---|
410 | { }
|
---|
411 |
|
---|
412 | template<typename _Yp, typename _Alloc, typename... _Args>
|
---|
413 | friend shared_ptr<_Yp>
|
---|
414 | allocate_shared(const _Alloc& __a, _Args&&... __args);
|
---|
415 |
|
---|
416 | // This constructor is non-standard, it is used by weak_ptr::lock().
|
---|
417 | shared_ptr(const weak_ptr<_Tp>& __r, std::nothrow_t) noexcept
|
---|
418 | : __shared_ptr<_Tp>(__r, std::nothrow) { }
|
---|
419 |
|
---|
420 | friend class weak_ptr<_Tp>;
|
---|
421 | };
|
---|
422 |
|
---|
423 | #if __cpp_deduction_guides >= 201606
|
---|
424 | template<typename _Tp>
|
---|
425 | shared_ptr(weak_ptr<_Tp>) -> shared_ptr<_Tp>;
|
---|
426 | template<typename _Tp, typename _Del>
|
---|
427 | shared_ptr(unique_ptr<_Tp, _Del>) -> shared_ptr<_Tp>;
|
---|
428 | #endif
|
---|
429 |
|
---|
430 | // 20.7.2.2.7 shared_ptr comparisons
|
---|
431 |
|
---|
432 | /// @relates shared_ptr @{
|
---|
433 |
|
---|
434 | /// Equality operator for shared_ptr objects, compares the stored pointers
|
---|
435 | template<typename _Tp, typename _Up>
|
---|
436 | _GLIBCXX_NODISCARD inline bool
|
---|
437 | operator==(const shared_ptr<_Tp>& __a, const shared_ptr<_Up>& __b) noexcept
|
---|
438 | { return __a.get() == __b.get(); }
|
---|
439 |
|
---|
440 | /// shared_ptr comparison with nullptr
|
---|
441 | template<typename _Tp>
|
---|
442 | _GLIBCXX_NODISCARD inline bool
|
---|
443 | operator==(const shared_ptr<_Tp>& __a, nullptr_t) noexcept
|
---|
444 | { return !__a; }
|
---|
445 |
|
---|
446 | #ifdef __cpp_lib_three_way_comparison
|
---|
447 | template<typename _Tp, typename _Up>
|
---|
448 | inline strong_ordering
|
---|
449 | operator<=>(const shared_ptr<_Tp>& __a,
|
---|
450 | const shared_ptr<_Up>& __b) noexcept
|
---|
451 | { return compare_three_way()(__a.get(), __b.get()); }
|
---|
452 |
|
---|
453 | template<typename _Tp>
|
---|
454 | inline strong_ordering
|
---|
455 | operator<=>(const shared_ptr<_Tp>& __a, nullptr_t) noexcept
|
---|
456 | {
|
---|
457 | using pointer = typename shared_ptr<_Tp>::element_type*;
|
---|
458 | return compare_three_way()(__a.get(), static_cast<pointer>(nullptr));
|
---|
459 | }
|
---|
460 | #else
|
---|
461 | /// shared_ptr comparison with nullptr
|
---|
462 | template<typename _Tp>
|
---|
463 | _GLIBCXX_NODISCARD inline bool
|
---|
464 | operator==(nullptr_t, const shared_ptr<_Tp>& __a) noexcept
|
---|
465 | { return !__a; }
|
---|
466 |
|
---|
467 | /// Inequality operator for shared_ptr objects, compares the stored pointers
|
---|
468 | template<typename _Tp, typename _Up>
|
---|
469 | _GLIBCXX_NODISCARD inline bool
|
---|
470 | operator!=(const shared_ptr<_Tp>& __a, const shared_ptr<_Up>& __b) noexcept
|
---|
471 | { return __a.get() != __b.get(); }
|
---|
472 |
|
---|
473 | /// shared_ptr comparison with nullptr
|
---|
474 | template<typename _Tp>
|
---|
475 | _GLIBCXX_NODISCARD inline bool
|
---|
476 | operator!=(const shared_ptr<_Tp>& __a, nullptr_t) noexcept
|
---|
477 | { return (bool)__a; }
|
---|
478 |
|
---|
479 | /// shared_ptr comparison with nullptr
|
---|
480 | template<typename _Tp>
|
---|
481 | _GLIBCXX_NODISCARD inline bool
|
---|
482 | operator!=(nullptr_t, const shared_ptr<_Tp>& __a) noexcept
|
---|
483 | { return (bool)__a; }
|
---|
484 |
|
---|
485 | /// Relational operator for shared_ptr objects, compares the stored pointers
|
---|
486 | template<typename _Tp, typename _Up>
|
---|
487 | _GLIBCXX_NODISCARD inline bool
|
---|
488 | operator<(const shared_ptr<_Tp>& __a, const shared_ptr<_Up>& __b) noexcept
|
---|
489 | {
|
---|
490 | using _Tp_elt = typename shared_ptr<_Tp>::element_type;
|
---|
491 | using _Up_elt = typename shared_ptr<_Up>::element_type;
|
---|
492 | using _Vp = typename common_type<_Tp_elt*, _Up_elt*>::type;
|
---|
493 | return less<_Vp>()(__a.get(), __b.get());
|
---|
494 | }
|
---|
495 |
|
---|
496 | /// shared_ptr comparison with nullptr
|
---|
497 | template<typename _Tp>
|
---|
498 | _GLIBCXX_NODISCARD inline bool
|
---|
499 | operator<(const shared_ptr<_Tp>& __a, nullptr_t) noexcept
|
---|
500 | {
|
---|
501 | using _Tp_elt = typename shared_ptr<_Tp>::element_type;
|
---|
502 | return less<_Tp_elt*>()(__a.get(), nullptr);
|
---|
503 | }
|
---|
504 |
|
---|
505 | /// shared_ptr comparison with nullptr
|
---|
506 | template<typename _Tp>
|
---|
507 | _GLIBCXX_NODISCARD inline bool
|
---|
508 | operator<(nullptr_t, const shared_ptr<_Tp>& __a) noexcept
|
---|
509 | {
|
---|
510 | using _Tp_elt = typename shared_ptr<_Tp>::element_type;
|
---|
511 | return less<_Tp_elt*>()(nullptr, __a.get());
|
---|
512 | }
|
---|
513 |
|
---|
514 | /// Relational operator for shared_ptr objects, compares the stored pointers
|
---|
515 | template<typename _Tp, typename _Up>
|
---|
516 | _GLIBCXX_NODISCARD inline bool
|
---|
517 | operator<=(const shared_ptr<_Tp>& __a, const shared_ptr<_Up>& __b) noexcept
|
---|
518 | { return !(__b < __a); }
|
---|
519 |
|
---|
520 | /// shared_ptr comparison with nullptr
|
---|
521 | template<typename _Tp>
|
---|
522 | _GLIBCXX_NODISCARD inline bool
|
---|
523 | operator<=(const shared_ptr<_Tp>& __a, nullptr_t) noexcept
|
---|
524 | { return !(nullptr < __a); }
|
---|
525 |
|
---|
526 | /// shared_ptr comparison with nullptr
|
---|
527 | template<typename _Tp>
|
---|
528 | _GLIBCXX_NODISCARD inline bool
|
---|
529 | operator<=(nullptr_t, const shared_ptr<_Tp>& __a) noexcept
|
---|
530 | { return !(__a < nullptr); }
|
---|
531 |
|
---|
532 | /// Relational operator for shared_ptr objects, compares the stored pointers
|
---|
533 | template<typename _Tp, typename _Up>
|
---|
534 | _GLIBCXX_NODISCARD inline bool
|
---|
535 | operator>(const shared_ptr<_Tp>& __a, const shared_ptr<_Up>& __b) noexcept
|
---|
536 | { return (__b < __a); }
|
---|
537 |
|
---|
538 | /// shared_ptr comparison with nullptr
|
---|
539 | template<typename _Tp>
|
---|
540 | _GLIBCXX_NODISCARD inline bool
|
---|
541 | operator>(const shared_ptr<_Tp>& __a, nullptr_t) noexcept
|
---|
542 | { return nullptr < __a; }
|
---|
543 |
|
---|
544 | /// shared_ptr comparison with nullptr
|
---|
545 | template<typename _Tp>
|
---|
546 | _GLIBCXX_NODISCARD inline bool
|
---|
547 | operator>(nullptr_t, const shared_ptr<_Tp>& __a) noexcept
|
---|
548 | { return __a < nullptr; }
|
---|
549 |
|
---|
550 | /// Relational operator for shared_ptr objects, compares the stored pointers
|
---|
551 | template<typename _Tp, typename _Up>
|
---|
552 | _GLIBCXX_NODISCARD inline bool
|
---|
553 | operator>=(const shared_ptr<_Tp>& __a, const shared_ptr<_Up>& __b) noexcept
|
---|
554 | { return !(__a < __b); }
|
---|
555 |
|
---|
556 | /// shared_ptr comparison with nullptr
|
---|
557 | template<typename _Tp>
|
---|
558 | _GLIBCXX_NODISCARD inline bool
|
---|
559 | operator>=(const shared_ptr<_Tp>& __a, nullptr_t) noexcept
|
---|
560 | { return !(__a < nullptr); }
|
---|
561 |
|
---|
562 | /// shared_ptr comparison with nullptr
|
---|
563 | template<typename _Tp>
|
---|
564 | _GLIBCXX_NODISCARD inline bool
|
---|
565 | operator>=(nullptr_t, const shared_ptr<_Tp>& __a) noexcept
|
---|
566 | { return !(nullptr < __a); }
|
---|
567 | #endif
|
---|
568 |
|
---|
569 | // 20.7.2.2.8 shared_ptr specialized algorithms.
|
---|
570 |
|
---|
571 | /// Swap overload for shared_ptr
|
---|
572 | template<typename _Tp>
|
---|
573 | inline void
|
---|
574 | swap(shared_ptr<_Tp>& __a, shared_ptr<_Tp>& __b) noexcept
|
---|
575 | { __a.swap(__b); }
|
---|
576 |
|
---|
577 | // 20.7.2.2.9 shared_ptr casts.
|
---|
578 |
|
---|
579 | /// Convert type of `shared_ptr`, via `static_cast`
|
---|
580 | template<typename _Tp, typename _Up>
|
---|
581 | inline shared_ptr<_Tp>
|
---|
582 | static_pointer_cast(const shared_ptr<_Up>& __r) noexcept
|
---|
583 | {
|
---|
584 | using _Sp = shared_ptr<_Tp>;
|
---|
585 | return _Sp(__r, static_cast<typename _Sp::element_type*>(__r.get()));
|
---|
586 | }
|
---|
587 |
|
---|
588 | /// Convert type of `shared_ptr`, via `const_cast`
|
---|
589 | template<typename _Tp, typename _Up>
|
---|
590 | inline shared_ptr<_Tp>
|
---|
591 | const_pointer_cast(const shared_ptr<_Up>& __r) noexcept
|
---|
592 | {
|
---|
593 | using _Sp = shared_ptr<_Tp>;
|
---|
594 | return _Sp(__r, const_cast<typename _Sp::element_type*>(__r.get()));
|
---|
595 | }
|
---|
596 |
|
---|
597 | /// Convert type of `shared_ptr`, via `dynamic_cast`
|
---|
598 | template<typename _Tp, typename _Up>
|
---|
599 | inline shared_ptr<_Tp>
|
---|
600 | dynamic_pointer_cast(const shared_ptr<_Up>& __r) noexcept
|
---|
601 | {
|
---|
602 | using _Sp = shared_ptr<_Tp>;
|
---|
603 | if (auto* __p = dynamic_cast<typename _Sp::element_type*>(__r.get()))
|
---|
604 | return _Sp(__r, __p);
|
---|
605 | return _Sp();
|
---|
606 | }
|
---|
607 |
|
---|
608 | #if __cplusplus >= 201703L
|
---|
609 | /// Convert type of `shared_ptr`, via `reinterpret_cast`
|
---|
610 | template<typename _Tp, typename _Up>
|
---|
611 | inline shared_ptr<_Tp>
|
---|
612 | reinterpret_pointer_cast(const shared_ptr<_Up>& __r) noexcept
|
---|
613 | {
|
---|
614 | using _Sp = shared_ptr<_Tp>;
|
---|
615 | return _Sp(__r, reinterpret_cast<typename _Sp::element_type*>(__r.get()));
|
---|
616 | }
|
---|
617 |
|
---|
618 | #if __cplusplus > 201703L
|
---|
619 | // _GLIBCXX_RESOLVE_LIB_DEFECTS
|
---|
620 | // 2996. Missing rvalue overloads for shared_ptr operations
|
---|
621 |
|
---|
622 | /// Convert type of `shared_ptr` rvalue, via `static_cast`
|
---|
623 | template<typename _Tp, typename _Up>
|
---|
624 | inline shared_ptr<_Tp>
|
---|
625 | static_pointer_cast(shared_ptr<_Up>&& __r) noexcept
|
---|
626 | {
|
---|
627 | using _Sp = shared_ptr<_Tp>;
|
---|
628 | return _Sp(std::move(__r),
|
---|
629 | static_cast<typename _Sp::element_type*>(__r.get()));
|
---|
630 | }
|
---|
631 |
|
---|
632 | /// Convert type of `shared_ptr` rvalue, via `const_cast`
|
---|
633 | template<typename _Tp, typename _Up>
|
---|
634 | inline shared_ptr<_Tp>
|
---|
635 | const_pointer_cast(shared_ptr<_Up>&& __r) noexcept
|
---|
636 | {
|
---|
637 | using _Sp = shared_ptr<_Tp>;
|
---|
638 | return _Sp(std::move(__r),
|
---|
639 | const_cast<typename _Sp::element_type*>(__r.get()));
|
---|
640 | }
|
---|
641 |
|
---|
642 | /// Convert type of `shared_ptr` rvalue, via `dynamic_cast`
|
---|
643 | template<typename _Tp, typename _Up>
|
---|
644 | inline shared_ptr<_Tp>
|
---|
645 | dynamic_pointer_cast(shared_ptr<_Up>&& __r) noexcept
|
---|
646 | {
|
---|
647 | using _Sp = shared_ptr<_Tp>;
|
---|
648 | if (auto* __p = dynamic_cast<typename _Sp::element_type*>(__r.get()))
|
---|
649 | return _Sp(std::move(__r), __p);
|
---|
650 | return _Sp();
|
---|
651 | }
|
---|
652 |
|
---|
653 | /// Convert type of `shared_ptr` rvalue, via `reinterpret_cast`
|
---|
654 | template<typename _Tp, typename _Up>
|
---|
655 | inline shared_ptr<_Tp>
|
---|
656 | reinterpret_pointer_cast(shared_ptr<_Up>&& __r) noexcept
|
---|
657 | {
|
---|
658 | using _Sp = shared_ptr<_Tp>;
|
---|
659 | return _Sp(std::move(__r),
|
---|
660 | reinterpret_cast<typename _Sp::element_type*>(__r.get()));
|
---|
661 | }
|
---|
662 | #endif // C++20
|
---|
663 | #endif // C++17
|
---|
664 |
|
---|
665 | /// @}
|
---|
666 |
|
---|
667 | /**
|
---|
668 | * @brief A non-owning observer for a pointer owned by a shared_ptr
|
---|
669 | *
|
---|
670 | * A weak_ptr provides a safe alternative to a raw pointer when you want
|
---|
671 | * a non-owning reference to an object that is managed by a shared_ptr.
|
---|
672 | *
|
---|
673 | * Unlike a raw pointer, a weak_ptr can be converted to a new shared_ptr
|
---|
674 | * that shares ownership with every other shared_ptr that already owns
|
---|
675 | * the pointer. In other words you can upgrade from a non-owning "weak"
|
---|
676 | * reference to an owning shared_ptr, without having access to any of
|
---|
677 | * the existing shared_ptr objects.
|
---|
678 | *
|
---|
679 | * Also unlike a raw pointer, a weak_ptr does not become "dangling" after
|
---|
680 | * the object it points to has been destroyed. Instead, a weak_ptr
|
---|
681 | * becomes _expired_ and can no longer be converted to a shared_ptr that
|
---|
682 | * owns the freed pointer, so you cannot accidentally access the pointed-to
|
---|
683 | * object after it has been destroyed.
|
---|
684 | */
|
---|
685 | template<typename _Tp>
|
---|
686 | class weak_ptr : public __weak_ptr<_Tp>
|
---|
687 | {
|
---|
688 | template<typename _Arg>
|
---|
689 | using _Constructible = typename enable_if<
|
---|
690 | is_constructible<__weak_ptr<_Tp>, _Arg>::value
|
---|
691 | >::type;
|
---|
692 |
|
---|
693 | template<typename _Arg>
|
---|
694 | using _Assignable = typename enable_if<
|
---|
695 | is_assignable<__weak_ptr<_Tp>&, _Arg>::value, weak_ptr&
|
---|
696 | >::type;
|
---|
697 |
|
---|
698 | public:
|
---|
699 | constexpr weak_ptr() noexcept = default;
|
---|
700 |
|
---|
701 | template<typename _Yp,
|
---|
702 | typename = _Constructible<const shared_ptr<_Yp>&>>
|
---|
703 | weak_ptr(const shared_ptr<_Yp>& __r) noexcept
|
---|
704 | : __weak_ptr<_Tp>(__r) { }
|
---|
705 |
|
---|
706 | weak_ptr(const weak_ptr&) noexcept = default;
|
---|
707 |
|
---|
708 | template<typename _Yp, typename = _Constructible<const weak_ptr<_Yp>&>>
|
---|
709 | weak_ptr(const weak_ptr<_Yp>& __r) noexcept
|
---|
710 | : __weak_ptr<_Tp>(__r) { }
|
---|
711 |
|
---|
712 | weak_ptr(weak_ptr&&) noexcept = default;
|
---|
713 |
|
---|
714 | template<typename _Yp, typename = _Constructible<weak_ptr<_Yp>>>
|
---|
715 | weak_ptr(weak_ptr<_Yp>&& __r) noexcept
|
---|
716 | : __weak_ptr<_Tp>(std::move(__r)) { }
|
---|
717 |
|
---|
718 | weak_ptr&
|
---|
719 | operator=(const weak_ptr& __r) noexcept = default;
|
---|
720 |
|
---|
721 | template<typename _Yp>
|
---|
722 | _Assignable<const weak_ptr<_Yp>&>
|
---|
723 | operator=(const weak_ptr<_Yp>& __r) noexcept
|
---|
724 | {
|
---|
725 | this->__weak_ptr<_Tp>::operator=(__r);
|
---|
726 | return *this;
|
---|
727 | }
|
---|
728 |
|
---|
729 | template<typename _Yp>
|
---|
730 | _Assignable<const shared_ptr<_Yp>&>
|
---|
731 | operator=(const shared_ptr<_Yp>& __r) noexcept
|
---|
732 | {
|
---|
733 | this->__weak_ptr<_Tp>::operator=(__r);
|
---|
734 | return *this;
|
---|
735 | }
|
---|
736 |
|
---|
737 | weak_ptr&
|
---|
738 | operator=(weak_ptr&& __r) noexcept = default;
|
---|
739 |
|
---|
740 | template<typename _Yp>
|
---|
741 | _Assignable<weak_ptr<_Yp>>
|
---|
742 | operator=(weak_ptr<_Yp>&& __r) noexcept
|
---|
743 | {
|
---|
744 | this->__weak_ptr<_Tp>::operator=(std::move(__r));
|
---|
745 | return *this;
|
---|
746 | }
|
---|
747 |
|
---|
748 | shared_ptr<_Tp>
|
---|
749 | lock() const noexcept
|
---|
750 | { return shared_ptr<_Tp>(*this, std::nothrow); }
|
---|
751 | };
|
---|
752 |
|
---|
753 | #if __cpp_deduction_guides >= 201606
|
---|
754 | template<typename _Tp>
|
---|
755 | weak_ptr(shared_ptr<_Tp>) -> weak_ptr<_Tp>;
|
---|
756 | #endif
|
---|
757 |
|
---|
758 | // 20.7.2.3.6 weak_ptr specialized algorithms.
|
---|
759 | /// Swap overload for weak_ptr
|
---|
760 | /// @relates weak_ptr
|
---|
761 | template<typename _Tp>
|
---|
762 | inline void
|
---|
763 | swap(weak_ptr<_Tp>& __a, weak_ptr<_Tp>& __b) noexcept
|
---|
764 | { __a.swap(__b); }
|
---|
765 |
|
---|
766 |
|
---|
767 | /// Primary template owner_less
|
---|
768 | template<typename _Tp = void>
|
---|
769 | struct owner_less;
|
---|
770 |
|
---|
771 | /// Void specialization of owner_less compares either shared_ptr or weak_ptr
|
---|
772 | template<>
|
---|
773 | struct owner_less<void> : _Sp_owner_less<void, void>
|
---|
774 | { };
|
---|
775 |
|
---|
776 | /// Partial specialization of owner_less for shared_ptr.
|
---|
777 | template<typename _Tp>
|
---|
778 | struct owner_less<shared_ptr<_Tp>>
|
---|
779 | : public _Sp_owner_less<shared_ptr<_Tp>, weak_ptr<_Tp>>
|
---|
780 | { };
|
---|
781 |
|
---|
782 | /// Partial specialization of owner_less for weak_ptr.
|
---|
783 | template<typename _Tp>
|
---|
784 | struct owner_less<weak_ptr<_Tp>>
|
---|
785 | : public _Sp_owner_less<weak_ptr<_Tp>, shared_ptr<_Tp>>
|
---|
786 | { };
|
---|
787 |
|
---|
788 | /**
|
---|
789 | * @brief Base class allowing use of member function shared_from_this.
|
---|
790 | */
|
---|
791 | template<typename _Tp>
|
---|
792 | class enable_shared_from_this
|
---|
793 | {
|
---|
794 | protected:
|
---|
795 | constexpr enable_shared_from_this() noexcept { }
|
---|
796 |
|
---|
797 | enable_shared_from_this(const enable_shared_from_this&) noexcept { }
|
---|
798 |
|
---|
799 | enable_shared_from_this&
|
---|
800 | operator=(const enable_shared_from_this&) noexcept
|
---|
801 | { return *this; }
|
---|
802 |
|
---|
803 | ~enable_shared_from_this() { }
|
---|
804 |
|
---|
805 | public:
|
---|
806 | shared_ptr<_Tp>
|
---|
807 | shared_from_this()
|
---|
808 | { return shared_ptr<_Tp>(this->_M_weak_this); }
|
---|
809 |
|
---|
810 | shared_ptr<const _Tp>
|
---|
811 | shared_from_this() const
|
---|
812 | { return shared_ptr<const _Tp>(this->_M_weak_this); }
|
---|
813 |
|
---|
814 | #if __cplusplus > 201402L || !defined(__STRICT_ANSI__) // c++1z or gnu++11
|
---|
815 | #define __cpp_lib_enable_shared_from_this 201603
|
---|
816 | weak_ptr<_Tp>
|
---|
817 | weak_from_this() noexcept
|
---|
818 | { return this->_M_weak_this; }
|
---|
819 |
|
---|
820 | weak_ptr<const _Tp>
|
---|
821 | weak_from_this() const noexcept
|
---|
822 | { return this->_M_weak_this; }
|
---|
823 | #endif
|
---|
824 |
|
---|
825 | private:
|
---|
826 | template<typename _Tp1>
|
---|
827 | void
|
---|
828 | _M_weak_assign(_Tp1* __p, const __shared_count<>& __n) const noexcept
|
---|
829 | { _M_weak_this._M_assign(__p, __n); }
|
---|
830 |
|
---|
831 | // Found by ADL when this is an associated class.
|
---|
832 | friend const enable_shared_from_this*
|
---|
833 | __enable_shared_from_this_base(const __shared_count<>&,
|
---|
834 | const enable_shared_from_this* __p)
|
---|
835 | { return __p; }
|
---|
836 |
|
---|
837 | template<typename, _Lock_policy>
|
---|
838 | friend class __shared_ptr;
|
---|
839 |
|
---|
840 | mutable weak_ptr<_Tp> _M_weak_this;
|
---|
841 | };
|
---|
842 |
|
---|
843 | /// @relates shared_ptr @{
|
---|
844 |
|
---|
845 | /**
|
---|
846 | * @brief Create an object that is owned by a shared_ptr.
|
---|
847 | * @param __a An allocator.
|
---|
848 | * @param __args Arguments for the @a _Tp object's constructor.
|
---|
849 | * @return A shared_ptr that owns the newly created object.
|
---|
850 | * @throw An exception thrown from @a _Alloc::allocate or from the
|
---|
851 | * constructor of @a _Tp.
|
---|
852 | *
|
---|
853 | * A copy of @a __a will be used to allocate memory for the shared_ptr
|
---|
854 | * and the new object.
|
---|
855 | */
|
---|
856 | template<typename _Tp, typename _Alloc, typename... _Args>
|
---|
857 | inline shared_ptr<_Tp>
|
---|
858 | allocate_shared(const _Alloc& __a, _Args&&... __args)
|
---|
859 | {
|
---|
860 | static_assert(!is_array<_Tp>::value, "make_shared<T[]> not supported");
|
---|
861 |
|
---|
862 | return shared_ptr<_Tp>(_Sp_alloc_shared_tag<_Alloc>{__a},
|
---|
863 | std::forward<_Args>(__args)...);
|
---|
864 | }
|
---|
865 |
|
---|
866 | /**
|
---|
867 | * @brief Create an object that is owned by a shared_ptr.
|
---|
868 | * @param __args Arguments for the @a _Tp object's constructor.
|
---|
869 | * @return A shared_ptr that owns the newly created object.
|
---|
870 | * @throw std::bad_alloc, or an exception thrown from the
|
---|
871 | * constructor of @a _Tp.
|
---|
872 | */
|
---|
873 | template<typename _Tp, typename... _Args>
|
---|
874 | inline shared_ptr<_Tp>
|
---|
875 | make_shared(_Args&&... __args)
|
---|
876 | {
|
---|
877 | typedef typename std::remove_cv<_Tp>::type _Tp_nc;
|
---|
878 | return std::allocate_shared<_Tp>(std::allocator<_Tp_nc>(),
|
---|
879 | std::forward<_Args>(__args)...);
|
---|
880 | }
|
---|
881 |
|
---|
882 | /// std::hash specialization for shared_ptr.
|
---|
883 | template<typename _Tp>
|
---|
884 | struct hash<shared_ptr<_Tp>>
|
---|
885 | : public __hash_base<size_t, shared_ptr<_Tp>>
|
---|
886 | {
|
---|
887 | size_t
|
---|
888 | operator()(const shared_ptr<_Tp>& __s) const noexcept
|
---|
889 | {
|
---|
890 | return std::hash<typename shared_ptr<_Tp>::element_type*>()(__s.get());
|
---|
891 | }
|
---|
892 | };
|
---|
893 |
|
---|
894 | /// @} relates shared_ptr
|
---|
895 | /// @} group pointer_abstractions
|
---|
896 |
|
---|
897 | #if __cplusplus >= 201703L
|
---|
898 | namespace __detail::__variant
|
---|
899 | {
|
---|
900 | template<typename> struct _Never_valueless_alt; // see <variant>
|
---|
901 |
|
---|
902 | // Provide the strong exception-safety guarantee when emplacing a
|
---|
903 | // shared_ptr into a variant.
|
---|
904 | template<typename _Tp>
|
---|
905 | struct _Never_valueless_alt<std::shared_ptr<_Tp>>
|
---|
906 | : std::true_type
|
---|
907 | { };
|
---|
908 |
|
---|
909 | // Provide the strong exception-safety guarantee when emplacing a
|
---|
910 | // weak_ptr into a variant.
|
---|
911 | template<typename _Tp>
|
---|
912 | struct _Never_valueless_alt<std::weak_ptr<_Tp>>
|
---|
913 | : std::true_type
|
---|
914 | { };
|
---|
915 | } // namespace __detail::__variant
|
---|
916 | #endif // C++17
|
---|
917 |
|
---|
918 | _GLIBCXX_END_NAMESPACE_VERSION
|
---|
919 | } // namespace
|
---|
920 |
|
---|
921 | #endif // _SHARED_PTR_H
|
---|