xref: /netbsd-src/external/gpl3/gcc/dist/libstdc++-v3/include/experimental/bits/shared_ptr.h (revision bdc22b2e01993381dcefeff2bc9b56ca75a4235c)
1 // Experimental shared_ptr with array support -*- C++ -*-
2 
3 // Copyright (C) 2015-2016 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 /** @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}
28  */
29 
30 #ifndef _GLIBCXX_EXPERIMENTAL_SHARED_PTR_H
31 #define _GLIBCXX_EXPERIMENTAL_SHARED_PTR_H 1
32 
33 #pragma GCC system_header
34 
35 #if __cplusplus <= 201103L
36 # include <bits/c++14_warning.h>
37 #else
38 
39 #include <memory>
40 #include <experimental/type_traits>
41 
42 namespace std _GLIBCXX_VISIBILITY(default)
43 {
44 namespace experimental
45 {
46 inline namespace fundamentals_v2
47 {
48 _GLIBCXX_BEGIN_NAMESPACE_VERSION
49   template<typename _Tp> class enable_shared_from_this;
50 _GLIBCXX_END_NAMESPACE_VERSION
51 } // namespace fundamentals_v2
52 } // namespace experimental
53 
54 #define __cpp_lib_experimental_shared_ptr_arrays 201406
55 
56 _GLIBCXX_BEGIN_NAMESPACE_VERSION
57 
58   /*
59    * The specification of std::experimental::shared_ptr is slightly different
60    * to std::shared_ptr (specifically in terms of "compatible" pointers) so
61    * to implement std::experimental::shared_ptr without too much duplication
62    * we make it derive from a partial specialization of std::__shared_ptr
63    * using a special tag type, __libfund_v1.
64    *
65    * There are two partial specializations for the tag type, supporting the
66    * different interfaces of the array and non-array forms.
67   */
68 
69   template <typename _Tp, bool = is_array<_Tp>::value>
70     struct __libfund_v1 { using type = _Tp; };
71 
72   // Partial specialization for base class of experimental::shared_ptr<T>
73   // (i.e. the non-array form of experimental::shared_ptr)
74   template<typename _Tp, _Lock_policy _Lp>
75     class __shared_ptr<__libfund_v1<_Tp, false>, _Lp>
76     : private __shared_ptr<_Tp, _Lp>
77     {
78       // For non-arrays, Y* is compatible with T* if Y* is convertible to T*.
79       template<typename _Yp, typename _Res = void>
80 	using _Compatible
81 	  = enable_if_t<experimental::is_convertible_v<_Yp*, _Tp*>, _Res>;
82 
83       template<typename _Yp, typename _Del,
84 	       typename _Ptr = typename unique_ptr<_Yp, _Del>::pointer,
85 	       typename _Res = void>
86 	using _UniqCompatible = enable_if_t<
87 	  experimental::is_convertible_v<_Yp*, _Tp*>
88 	  && experimental::is_convertible_v<_Ptr, _Tp*>,
89 	  _Res>;
90 
91       using _Base_type = __shared_ptr<_Tp>;
92 
93       _Base_type&  _M_get_base() { return *this; }
94       const _Base_type&  _M_get_base() const { return *this; }
95 
96     public:
97       using element_type = _Tp;
98 
99       constexpr __shared_ptr() noexcept = default;
100 
101       template<typename _Tp1, typename = _Compatible<_Tp1>>
102 	explicit
103 	__shared_ptr(_Tp1* __p)
104 	: _Base_type(__p)
105 	{ }
106 
107       template<typename _Tp1, typename _Deleter, typename = _Compatible<_Tp1>>
108 	__shared_ptr(_Tp1* __p, _Deleter __d)
109 	: _Base_type(__p, __d)
110 	{ }
111 
112       template<typename _Tp1, typename _Deleter, typename _Alloc,
113 	       typename = _Compatible<_Tp1>>
114 	__shared_ptr(_Tp1* __p, _Deleter __d, _Alloc __a)
115 	: _Base_type(__p, __d, __a)
116 	{ }
117 
118       template<typename _Deleter>
119 	__shared_ptr(nullptr_t __p, _Deleter __d)
120 	: _Base_type(__p, __d)
121 	{ }
122 
123       template<typename _Deleter, typename _Alloc>
124 	__shared_ptr(nullptr_t __p, _Deleter __d, _Alloc __a)
125 	: _Base_type(__p, __d, __a)
126 	{ }
127 
128       template<typename _Tp1>
129 	__shared_ptr(const __shared_ptr<__libfund_v1<_Tp1>, _Lp>& __r,
130 		     element_type* __p) noexcept
131 	: _Base_type(__r._M_get_base(), __p)
132 	{ }
133 
134       __shared_ptr(const __shared_ptr&) noexcept = default;
135       __shared_ptr(__shared_ptr&&) noexcept = default;
136       __shared_ptr& operator=(const __shared_ptr&) noexcept = default;
137       __shared_ptr& operator=(__shared_ptr&&) noexcept = default;
138       ~__shared_ptr() = default;
139 
140       template<typename _Tp1, typename = _Compatible<_Tp1>>
141 	__shared_ptr(const __shared_ptr<__libfund_v1<_Tp1>, _Lp>& __r) noexcept
142 	: _Base_type(__r._M_get_base())
143 	{ }
144 
145       template<typename _Tp1, typename = _Compatible<_Tp1>>
146 	__shared_ptr(__shared_ptr<__libfund_v1<_Tp1>, _Lp>&& __r) noexcept
147 	: _Base_type(std::move((__r._M_get_base())))
148 	{ }
149 
150       template<typename _Tp1, typename = _Compatible<_Tp1>>
151 	explicit
152 	__shared_ptr(const __weak_ptr<__libfund_v1<_Tp1>, _Lp>& __r)
153 	: _Base_type(__r._M_get_base())
154 	{ }
155 
156       template<typename _Tp1, typename _Del,
157 	       typename = _UniqCompatible<_Tp1, _Del>>
158 	__shared_ptr(unique_ptr<_Tp1, _Del>&& __r)
159 	: _Base_type(std::move(__r))
160 	{ }
161 
162 #if _GLIBCXX_USE_DEPRECATED
163       // Postcondition: use_count() == 1 and __r.get() == 0
164       template<typename _Tp1, typename = _Compatible<_Tp1>>
165 	__shared_ptr(std::auto_ptr<_Tp1>&& __r)
166         : _Base_type(std::move(__r))
167 	{ }
168 #endif
169 
170       constexpr __shared_ptr(nullptr_t) noexcept : __shared_ptr() { }
171 
172       // reset
173       void
174       reset() noexcept
175       { __shared_ptr(nullptr).swap(*this); }
176 
177       template<typename _Tp1>
178 	_Compatible<_Tp1>
179 	reset(_Tp1* __p)
180 	{
181 	  _GLIBCXX_DEBUG_ASSERT(__p == 0 || __p != get());
182 	  __shared_ptr(__p).swap(*this);
183 	}
184 
185       template<typename _Tp1, typename _Deleter>
186 	_Compatible<_Tp1>
187 	reset(_Tp1* __p, _Deleter __d)
188 	{ __shared_ptr(__p, __d).swap(*this); }
189 
190       template<typename _Tp1, typename _Deleter, typename _Alloc>
191 	_Compatible<_Tp1>
192 	reset(_Tp1* __p, _Deleter __d, _Alloc __a)
193 	{ __shared_ptr(__p, __d, std::move(__a)).swap(*this); }
194 
195       using _Base_type::operator*;
196       using _Base_type::operator->;
197 
198       template<typename _Tp1>
199 	_Compatible<_Tp1, __shared_ptr&>
200 	operator=(const __shared_ptr<__libfund_v1<_Tp1>, _Lp>& __r) noexcept
201 	{
202 	  _Base_type::operator=(__r._M_get_base());
203 	  return *this;
204 	}
205 
206       template<class _Tp1>
207 	_Compatible<_Tp1, __shared_ptr&>
208 	operator=(__shared_ptr<__libfund_v1<_Tp1>, _Lp>&& __r) noexcept
209 	{
210 	  _Base_type::operator=(std::move(__r._M_get_base()));
211 	  return *this;
212 	}
213 
214       template<typename _Tp1, typename _Del>
215 	_UniqCompatible<_Tp1, _Del, __shared_ptr&>
216 	operator=(unique_ptr<_Tp1, _Del>&& __r)
217 	{
218 	  _Base_type::operator=(std::move(__r));
219 	  return *this;
220 	}
221 
222 #if _GLIBCXX_USE_DEPRECATED
223       template<typename _Tp1>
224 	_Compatible<_Tp1, __shared_ptr&>
225 	operator=(std::auto_ptr<_Tp1>&& __r)
226 	{
227 	  _Base_type::operator=(std::move(__r));
228 	  return *this;
229 	}
230 #endif
231 
232       void
233       swap(__shared_ptr& __other) noexcept
234       { _Base_type::swap(__other); }
235 
236       template<typename _Tp1>
237 	bool
238 	owner_before(__shared_ptr<__libfund_v1<_Tp1>, _Lp> const& __rhs) const
239 	{ return _Base_type::owner_before(__rhs._M_get_base()); }
240 
241       template<typename _Tp1>
242 	bool
243 	owner_before(__weak_ptr<__libfund_v1<_Tp1>, _Lp> const& __rhs) const
244 	{ return _Base_type::owner_before(__rhs._M_get_base()); }
245 
246       using _Base_type::operator bool;
247       using _Base_type::get;
248       using _Base_type::unique;
249       using _Base_type::use_count;
250 
251     protected:
252 
253       // make_shared not yet support for shared_ptr_arrays
254       //template<typename _Alloc, typename... _Args>
255       //  __shared_ptr(_Sp_make_shared_tag __tag, const _Alloc& __a,
256       //	             _Args&&... __args)
257       //	: _M_ptr(), _M_refcount(__tag, (_Tp*)0, __a,
258       //	                        std::forward<_Args>(__args)...)
259       //	{
260       //	  void* __p = _M_refcount._M_get_deleter(typeid(__tag));
261       //	  _M_ptr = static_cast<_Tp*>(__p);
262       //	}
263 
264       // __weak_ptr::lock()
265       __shared_ptr(const __weak_ptr<__libfund_v1<_Tp>, _Lp>& __r,
266 		   std::nothrow_t)
267       : _Base_type(__r._M_get_base(), std::nothrow)
268       { }
269 
270     private:
271       template<typename _Tp1, _Lock_policy _Lp1> friend class __weak_ptr;
272       template<typename _Tp1, _Lock_policy _Lp1> friend class __shared_ptr;
273 
274       // TODO
275       template<typename _Del, typename _Tp1, _Lock_policy _Lp1>
276 	friend _Del* get_deleter(const __shared_ptr<_Tp1, _Lp1>&) noexcept;
277     };
278 
279   // Helper traits for shared_ptr of array:
280 
281   // Trait that tests if Y* is compatible with T*, for shared_ptr purposes.
282   template<typename _Yp, typename _Tp>
283     struct __sp_compatible
284     : is_convertible<_Yp*, _Tp*>::type
285     { };
286 
287   template<size_t _Nm, typename _Tp>
288     struct __sp_compatible<_Tp[_Nm], _Tp[]>
289     : true_type
290     { };
291 
292   template<size_t _Nm, typename _Tp>
293     struct __sp_compatible<_Tp[_Nm], const _Tp[]>
294     : true_type
295     { };
296 
297   template<typename _Yp, typename _Tp>
298     constexpr bool __sp_compatible_v
299       = __sp_compatible<_Yp, _Tp>::value;
300 
301   // Test conversion from Y(*)[N] to U(*)[N] without forming invalid type Y[N].
302   template<typename _Up, size_t _Nm, typename _Yp, typename = void>
303     struct __sp_is_constructible_arrN
304     : false_type
305     { };
306 
307   template<typename _Up, size_t _Nm, typename _Yp>
308     struct __sp_is_constructible_arrN<_Up, _Nm, _Yp, __void_t<_Yp[_Nm]>>
309     : is_convertible<_Yp(*)[_Nm], _Up(*)[_Nm]>::type
310     { };
311 
312   // Test conversion from Y(*)[] to U(*)[] without forming invalid type Y[].
313   template<typename _Up, typename _Yp, typename = void>
314     struct __sp_is_constructible_arr
315     : false_type
316     { };
317 
318   template<typename _Up, typename _Yp>
319     struct __sp_is_constructible_arr<_Up, _Yp, __void_t<_Yp[]>>
320     : is_convertible<_Yp(*)[], _Up(*)[]>::type
321     { };
322 
323   // Trait to check if shared_ptr<T> can be constructed from Y*.
324   template<typename _Tp, typename _Yp>
325     struct __sp_is_constructible;
326 
327   // When T is U[N], Y(*)[N] shall be convertible to T*;
328   template<typename _Up, size_t _Nm, typename _Yp>
329     struct __sp_is_constructible<_Up[_Nm], _Yp>
330     : __sp_is_constructible_arrN<_Up, _Nm, _Yp>::type
331     { };
332 
333   // when T is U[], Y(*)[] shall be convertible to T*;
334   template<typename _Up, typename _Yp>
335     struct __sp_is_constructible<_Up[], _Yp>
336     : __sp_is_constructible_arr<_Up, _Yp>::type
337     { };
338 
339   // otherwise, Y* shall be convertible to T*.
340   template<typename _Tp, typename _Yp>
341     struct __sp_is_constructible
342     : is_convertible<_Yp*, _Tp*>::type
343     { };
344 
345   template<typename _Tp, typename _Yp>
346     constexpr bool __sp_is_constructible_v
347       = __sp_is_constructible<_Tp, _Yp>::value;
348 
349 
350   // Partial specialization for base class of experimental::shared_ptr<T[N]>
351   // and experimental::shared_ptr<T[]> (i.e. the array forms).
352   template<typename _Tp, _Lock_policy _Lp>
353     class __shared_ptr<__libfund_v1<_Tp, true>, _Lp>
354     : private __shared_ptr<remove_extent_t<_Tp>, _Lp>
355     {
356     public:
357       using element_type = remove_extent_t<_Tp>;
358 
359     private:
360       struct _Array_deleter
361       {
362 	void
363 	operator()(element_type const *__p) const
364 	{ delete [] __p; }
365       };
366 
367       // Constraint for constructing/resetting with a pointer of type _Yp*:
368       template<typename _Yp>
369 	using _SafeConv = enable_if_t<__sp_is_constructible_v<_Tp, _Yp>>;
370 
371       // Constraint for constructing/assigning from smart_pointer<_Tp1>:
372       template<typename _Tp1, typename _Res = void>
373 	using _Compatible = enable_if_t<__sp_compatible_v<_Tp1, _Tp>, _Res>;
374 
375       // Constraint for constructing/assigning from unique_ptr<_Tp1, _Del>:
376       template<typename _Tp1, typename _Del,
377 	       typename _Ptr = typename unique_ptr<_Tp1, _Del>::pointer,
378 	       typename _Res = void>
379 	using _UniqCompatible = enable_if_t<
380 	  __sp_compatible_v<_Tp1, _Tp>
381 	  && experimental::is_convertible_v<_Ptr, element_type*>,
382 	  _Res>;
383 
384       using _Base_type = __shared_ptr<element_type>;
385 
386       _Base_type&  _M_get_base() { return *this; }
387       const _Base_type&  _M_get_base() const { return *this; }
388 
389     public:
390       constexpr __shared_ptr() noexcept
391       : _Base_type()
392       { }
393 
394       template<typename _Tp1, typename = _SafeConv<_Tp1>>
395 	explicit
396 	__shared_ptr(_Tp1* __p)
397 	: _Base_type(__p, _Array_deleter())
398 	{ }
399 
400       template<typename _Tp1, typename _Deleter, typename = _SafeConv<_Tp1>>
401 	__shared_ptr(_Tp1* __p, _Deleter __d)
402 	: _Base_type(__p, __d)
403 	{ }
404 
405       template<typename _Tp1, typename _Deleter, typename _Alloc,
406 	       typename = _SafeConv<_Tp1>>
407 	__shared_ptr(_Tp1* __p, _Deleter __d, _Alloc __a)
408 	: _Base_type(__p, __d, __a)
409 	{ }
410 
411       template<typename _Deleter>
412 	__shared_ptr(nullptr_t __p, _Deleter __d)
413 	: _Base_type(__p, __d)
414 	{ }
415 
416       template<typename _Deleter, typename _Alloc>
417 	__shared_ptr(nullptr_t __p, _Deleter __d, _Alloc __a)
418 	: _Base_type(__p, __d, __a)
419 	{ }
420 
421       template<typename _Tp1>
422 	__shared_ptr(const __shared_ptr<__libfund_v1<_Tp1>, _Lp>& __r,
423 		     element_type* __p) noexcept
424 	: _Base_type(__r._M_get_base(), __p)
425 	{ }
426 
427       __shared_ptr(const __shared_ptr&) noexcept = default;
428       __shared_ptr(__shared_ptr&&) noexcept = default;
429       __shared_ptr& operator=(const __shared_ptr&) noexcept = default;
430       __shared_ptr& operator=(__shared_ptr&&) noexcept = default;
431       ~__shared_ptr() = default;
432 
433       template<typename _Tp1, typename = _Compatible<_Tp1>>
434 	__shared_ptr(const __shared_ptr<__libfund_v1<_Tp1>, _Lp>& __r) noexcept
435 	: _Base_type(__r._M_get_base())
436 	{ }
437 
438       template<typename _Tp1, typename = _Compatible<_Tp1>>
439 	__shared_ptr(__shared_ptr<__libfund_v1<_Tp1>, _Lp>&& __r) noexcept
440 	: _Base_type(std::move((__r._M_get_base())))
441 	{ }
442 
443       template<typename _Tp1, typename = _Compatible<_Tp1>>
444 	explicit
445 	__shared_ptr(const __weak_ptr<__libfund_v1<_Tp1>, _Lp>& __r)
446 	: _Base_type(__r._M_get_base())
447 	{ }
448 
449       template<typename _Tp1, typename _Del,
450 	       typename = _UniqCompatible<_Tp1, _Del>>
451 	__shared_ptr(unique_ptr<_Tp1, _Del>&& __r)
452 	: _Base_type(std::move(__r))
453 	{ }
454 
455 #if _GLIBCXX_USE_DEPRECATED
456       // Postcondition: use_count() == 1 and __r.get() == 0
457       template<typename _Tp1, typename = _Compatible<_Tp1>>
458 	__shared_ptr(auto_ptr<_Tp1>&& __r)
459         : _Base_type(std::move(__r))
460 	{ }
461 #endif
462 
463       constexpr __shared_ptr(nullptr_t) noexcept : __shared_ptr() { }
464 
465       // reset
466       void
467       reset() noexcept
468       { __shared_ptr(nullptr).swap(*this); }
469 
470       template<typename _Tp1>
471 	_SafeConv<_Tp1>
472 	reset(_Tp1* __p)
473 	{
474 	  _GLIBCXX_DEBUG_ASSERT(__p == 0 || __p != get());
475 	  __shared_ptr(__p, _Array_deleter()).swap(*this);
476 	}
477 
478       template<typename _Tp1, typename _Deleter>
479 	_SafeConv<_Tp1>
480 	reset(_Tp1* __p, _Deleter __d)
481 	{ __shared_ptr(__p, __d).swap(*this); }
482 
483       template<typename _Tp1, typename _Deleter, typename _Alloc>
484 	_SafeConv<_Tp1>
485 	reset(_Tp1* __p, _Deleter __d, _Alloc __a)
486 	{ __shared_ptr(__p, __d, std::move(__a)).swap(*this); }
487 
488       element_type&
489       operator[](ptrdiff_t i) const noexcept
490       {
491 	_GLIBCXX_DEBUG_ASSERT(get() != 0 && i >= 0);
492 	return get()[i];
493       }
494 
495       template<typename _Tp1>
496 	_Compatible<_Tp1, __shared_ptr&>
497 	operator=(const __shared_ptr<__libfund_v1<_Tp1>, _Lp>& __r) noexcept
498 	{
499 	  _Base_type::operator=(__r._M_get_base());
500 	  return *this;
501 	}
502 
503       template<class _Tp1>
504 	_Compatible<_Tp1, __shared_ptr&>
505 	operator=(__shared_ptr<__libfund_v1<_Tp1>, _Lp>&& __r) noexcept
506 	{
507 	  _Base_type::operator=(std::move(__r._M_get_base()));
508 	  return *this;
509 	}
510 
511       template<typename _Tp1, typename _Del>
512 	_UniqCompatible<_Tp1, _Del, __shared_ptr&>
513 	operator=(unique_ptr<_Tp1, _Del>&& __r)
514 	{
515 	  _Base_type::operator=(std::move(__r));
516 	  return *this;
517 	}
518 
519 #if _GLIBCXX_USE_DEPRECATED
520       template<typename _Tp1>
521 	_Compatible<_Tp1, __shared_ptr&>
522 	operator=(auto_ptr<_Tp1>&& __r)
523 	{
524 	  _Base_type::operator=(std::move(__r));
525 	  return *this;
526 	}
527 #endif
528 
529       void
530       swap(__shared_ptr& __other) noexcept
531       { _Base_type::swap(__other); }
532 
533       template<typename _Tp1>
534 	bool
535 	owner_before(__shared_ptr<__libfund_v1<_Tp1>, _Lp> const& __rhs) const
536 	{ return _Base_type::owner_before(__rhs._M_get_base()); }
537 
538       template<typename _Tp1>
539 	bool
540 	owner_before(__weak_ptr<__libfund_v1<_Tp1>, _Lp> const& __rhs) const
541 	{ return _Base_type::owner_before(__rhs._M_get_base()); }
542 
543       using _Base_type::operator bool;
544       using _Base_type::get;
545       using _Base_type::unique;
546       using _Base_type::use_count;
547 
548     protected:
549 
550       // make_shared not yet support for shared_ptr_arrays
551       //template<typename _Alloc, typename... _Args>
552       //  __shared_ptr(_Sp_make_shared_tag __tag, const _Alloc& __a,
553       //	             _Args&&... __args)
554       //	: _M_ptr(), _M_refcount(__tag, (_Tp*)0, __a,
555       //	                        std::forward<_Args>(__args)...)
556       //	{
557       //	  void* __p = _M_refcount._M_get_deleter(typeid(__tag));
558       //	  _M_ptr = static_cast<_Tp*>(__p);
559       //	}
560 
561       // __weak_ptr::lock()
562       __shared_ptr(const __weak_ptr<__libfund_v1<_Tp>, _Lp>& __r,
563 		   std::nothrow_t)
564       : _Base_type(__r._M_get_base(), std::nothrow)
565       { }
566 
567     private:
568       template<typename _Tp1, _Lock_policy _Lp1> friend class __weak_ptr;
569       template<typename _Tp1, _Lock_policy _Lp1> friend class __shared_ptr;
570 
571       // TODO
572       template<typename _Del, typename _Tp1, _Lock_policy _Lp1>
573 	friend _Del* get_deleter(const __shared_ptr<_Tp1, _Lp1>&) noexcept;
574     };
575 
576   // weak_ptr specialization for __shared_ptr array
577   template<typename _Tp, _Lock_policy _Lp>
578     class __weak_ptr<__libfund_v1<_Tp>, _Lp>
579     : __weak_ptr<remove_extent_t<_Tp>, _Lp>
580     {
581       template<typename _Tp1, typename _Res = void>
582 	using _Compatible
583 	  = enable_if_t<__sp_compatible_v<_Tp1, _Tp>, _Res>;
584 
585       using _Base_type = __weak_ptr<remove_extent_t<_Tp>>;
586 
587       _Base_type&  _M_get_base() { return *this; }
588       const _Base_type&  _M_get_base() const { return *this; }
589 
590     public:
591       using element_type = remove_extent_t<_Tp>;
592 
593       constexpr __weak_ptr() noexcept
594       : _Base_type()
595       { }
596 
597       __weak_ptr(const __weak_ptr&) noexcept = default;
598 
599       ~__weak_ptr() = default;
600 
601       template<typename _Tp1, typename = _Compatible<_Tp1>>
602 	__weak_ptr(const __weak_ptr<__libfund_v1<_Tp1>, _Lp>& __r) noexcept
603 	: _Base_type(__r._M_get_base())
604 	{ }
605 
606       template<typename _Tp1, typename = _Compatible<_Tp1>>
607 	__weak_ptr(const __shared_ptr<__libfund_v1<_Tp1>, _Lp>& __r) noexcept
608 	: _Base_type(__r._M_get_base())
609 	{ }
610 
611       __weak_ptr(__weak_ptr&& __r) noexcept
612       : _Base_type(std::move(__r))
613       { }
614 
615       template<typename _Tp1, typename = _Compatible<_Tp1>>
616 	__weak_ptr(__weak_ptr<__libfund_v1<_Tp1>, _Lp>&& __r) noexcept
617 	: _Base_type(std::move(__r._M_get_base()))
618 	{ }
619 
620       __weak_ptr&
621       operator=(const __weak_ptr& __r) noexcept = default;
622 
623       template<typename _Tp1>
624 	_Compatible<_Tp1, __weak_ptr&>
625 	operator=(const __weak_ptr<__libfund_v1<_Tp1>, _Lp>& __r) noexcept
626 	{
627 	  this->_Base_type::operator=(__r._M_get_base());
628 	  return *this;
629 	}
630 
631       template<typename _Tp1>
632 	_Compatible<_Tp1, __weak_ptr&>
633 	operator=(const __shared_ptr<_Tp1, _Lp>& __r) noexcept
634 	{
635 	  this->_Base_type::operator=(__r._M_get_base());
636 	  return *this;
637 	}
638 
639       __weak_ptr&
640       operator=(__weak_ptr&& __r) noexcept
641       {
642 	this->_Base_type::operator=(std::move(__r));
643 	return *this;
644       }
645 
646       template<typename _Tp1>
647 	_Compatible<_Tp1, __weak_ptr&>
648 	operator=(__weak_ptr<_Tp1, _Lp>&& __r) noexcept
649 	{
650 	  this->_Base_type::operator=(std::move(__r._M_get_base()));
651 	  return *this;
652 	}
653 
654       void
655       swap(__weak_ptr& __other) noexcept
656       { this->_Base_type::swap(__other); }
657 
658       template<typename _Tp1>
659 	bool
660 	owner_before(const __shared_ptr<__libfund_v1<_Tp1>, _Lp>& __rhs) const
661 	{ return _Base_type::owner_before(__rhs._M_get_base()); }
662 
663       template<typename _Tp1>
664 	bool
665 	owner_before(const __weak_ptr<__libfund_v1<_Tp1>, _Lp>& __rhs) const
666 	{ return _Base_type::owner_before(__rhs._M_get_base()); }
667 
668       __shared_ptr<__libfund_v1<_Tp>, _Lp>
669       lock() const noexcept  // should not be element_type
670       { return __shared_ptr<__libfund_v1<_Tp>, _Lp>(*this, std::nothrow); }
671 
672       using _Base_type::use_count;
673       using _Base_type::expired;
674       using _Base_type::reset;
675 
676     private:
677       // Used by __enable_shared_from_this.
678       void
679       _M_assign(element_type* __ptr,
680 		const __shared_count<_Lp>& __refcount) noexcept
681       { this->_Base_type::_M_assign(__ptr, __refcount); }
682 
683       template<typename _Tp1, _Lock_policy _Lp1> friend class __shared_ptr;
684       template<typename _Tp1, _Lock_policy _Lp1> friend class __weak_ptr;
685       friend class __enable_shared_from_this<_Tp, _Lp>;
686       friend class experimental::enable_shared_from_this<_Tp>;
687       friend class enable_shared_from_this<_Tp>;
688     };
689 
690 _GLIBCXX_END_NAMESPACE_VERSION
691 
692 namespace experimental
693 {
694 inline namespace fundamentals_v2
695 {
696 _GLIBCXX_BEGIN_NAMESPACE_VERSION
697 
698     // 8.2.1
699 
700   template<typename _Tp> class shared_ptr;
701   template<typename _Tp> class weak_ptr;
702 
703   template<typename _Tp, _Lock_policy _Lp = __default_lock_policy>
704     using __shared_ptr = std::__shared_ptr<__libfund_v1<_Tp>, _Lp>;
705 
706   template<typename _Tp, _Lock_policy _Lp = __default_lock_policy>
707     using __weak_ptr = std::__weak_ptr<__libfund_v1<_Tp>, _Lp>;
708 
709   template<typename _Tp>
710     class shared_ptr : public __shared_ptr<_Tp>
711     {
712       using _Base_type = __shared_ptr<_Tp>;
713 
714     public:
715       using element_type = typename _Base_type::element_type;
716 
717     private:
718       // Constraint for construction from a pointer of type _Yp*:
719       template<typename _Yp>
720 	using _SafeConv = enable_if_t<__sp_is_constructible_v<_Tp, _Yp>>;
721 
722       template<typename _Tp1, typename _Res = void>
723 	using _Compatible
724 	  = enable_if_t<__sp_compatible_v<_Tp1, _Tp>, _Res>;
725 
726       template<typename _Tp1, typename _Del,
727 	       typename _Ptr = typename unique_ptr<_Tp1, _Del>::pointer,
728 	       typename _Res = void>
729 	using _UniqCompatible = enable_if_t<
730 	  __sp_compatible_v<_Tp1, _Tp>
731 	  && experimental::is_convertible_v<_Ptr, element_type*>,
732 	  _Res>;
733 
734     public:
735 
736       // 8.2.1.1, shared_ptr constructors
737       constexpr shared_ptr() noexcept = default;
738 
739       template<typename _Tp1, typename = _SafeConv<_Tp1>>
740 	explicit
741 	shared_ptr(_Tp1* __p) : _Base_type(__p)
742 	{ _M_enable_shared_from_this_with(__p); }
743 
744       template<typename _Tp1, typename _Deleter, typename = _SafeConv<_Tp1>>
745 	shared_ptr(_Tp1* __p, _Deleter __d)
746 	: _Base_type(__p, __d)
747 	{ _M_enable_shared_from_this_with(__p); }
748 
749       template<typename _Tp1, typename _Deleter, typename _Alloc,
750 	       typename = _SafeConv<_Tp1>>
751 	shared_ptr(_Tp1* __p, _Deleter __d, _Alloc __a)
752 	: _Base_type(__p, __d, __a)
753 	{ _M_enable_shared_from_this_with(__p); }
754 
755       template<typename _Deleter>
756 	shared_ptr(nullptr_t __p, _Deleter __d)
757 	: _Base_type(__p, __d) { }
758 
759       template<typename _Deleter, typename _Alloc>
760 	shared_ptr(nullptr_t __p, _Deleter __d, _Alloc __a)
761 	: _Base_type(__p, __d, __a) { }
762 
763       template<typename _Tp1>
764 	shared_ptr(const shared_ptr<_Tp1>& __r, element_type* __p) noexcept
765 	: _Base_type(__r, __p) { }
766 
767       shared_ptr(const shared_ptr& __r) noexcept
768 	: _Base_type(__r) { }
769 
770       template<typename _Tp1, typename = _Compatible<_Tp1>>
771 	shared_ptr(const shared_ptr<_Tp1>& __r) noexcept
772 	: _Base_type(__r) { }
773 
774       shared_ptr(shared_ptr&& __r) noexcept
775       : _Base_type(std::move(__r)) { }
776 
777       template<typename _Tp1, typename = _Compatible<_Tp1>>
778 	shared_ptr(shared_ptr<_Tp1>&& __r) noexcept
779 	: _Base_type(std::move(__r)) { }
780 
781       template<typename _Tp1, typename = _Compatible<_Tp1>>
782 	explicit
783 	shared_ptr(const weak_ptr<_Tp1>& __r)
784 	: _Base_type(__r) { }
785 
786 #if _GLIBCXX_USE_DEPRECATED
787       template<typename _Tp1, typename = _Compatible<_Tp1>>
788 	shared_ptr(std::auto_ptr<_Tp1>&& __r)
789 	: _Base_type(std::move(__r))
790 	{ _M_enable_shared_from_this_with(static_cast<_Tp1*>(this->get())); }
791 #endif
792 
793       template<typename _Tp1, typename _Del,
794 	       typename = _UniqCompatible<_Tp1, _Del>>
795 	shared_ptr(unique_ptr<_Tp1, _Del>&& __r)
796 	: _Base_type(std::move(__r))
797 	{
798 	  // XXX assume conversion from __r.get() to this->get() to __elem_t*
799 	  // is a round trip, which might not be true in all cases.
800 	  using __elem_t = typename unique_ptr<_Tp1, _Del>::element_type;
801 	  _M_enable_shared_from_this_with(static_cast<__elem_t*>(this->get()));
802 	}
803 
804       constexpr shared_ptr(nullptr_t __p)
805       : _Base_type(__p) { }
806 
807       // C++14 §20.8.2.2
808       ~shared_ptr() = default;
809 
810       // C++14 §20.8.2.3
811       shared_ptr& operator=(const shared_ptr&) noexcept = default;
812 
813       template <typename _Tp1>
814 	_Compatible<_Tp1, shared_ptr&>
815 	operator=(const shared_ptr<_Tp1>& __r) noexcept
816 	{
817 	  _Base_type::operator=(__r);
818 	  return *this;
819 	}
820 
821       shared_ptr&
822       operator=(shared_ptr&& __r) noexcept
823       {
824 	_Base_type::operator=(std::move(__r));
825 	return *this;
826       }
827 
828       template <typename _Tp1>
829 	_Compatible<_Tp1, shared_ptr&>
830 	operator=(shared_ptr<_Tp1>&& __r) noexcept
831 	{
832 	  _Base_type::operator=(std::move(__r));
833 	  return *this;
834 	}
835 
836 #if _GLIBCXX_USE_DEPRECATED
837       template<typename _Tp1>
838 	_Compatible<_Tp1, shared_ptr&>
839 	operator=(std::auto_ptr<_Tp1>&& __r)
840 	{
841 	  __shared_ptr<_Tp>::operator=(std::move(__r));
842 	  return *this;
843 	}
844 #endif
845 
846       template <typename _Tp1, typename _Del>
847 	_UniqCompatible<_Tp1, _Del, shared_ptr&>
848 	operator=(unique_ptr<_Tp1, _Del>&& __r)
849 	{
850 	  _Base_type::operator=(std::move(__r));
851 	  return *this;
852 	}
853 
854       // C++14 §20.8.2.2.4
855       // swap & reset
856       // 8.2.1.2 shared_ptr observers
857       // in __shared_ptr
858 
859     private:
860       template<typename _Alloc, typename... _Args>
861 	shared_ptr(_Sp_make_shared_tag __tag, const _Alloc& __a,
862 		   _Args&&... __args)
863 	: _Base_type(__tag, __a, std::forward<_Args>(__args)...)
864 	{ _M_enable_shared_from_this_with(this->get()); }
865 
866       template<typename _Tp1, typename _Alloc, typename... _Args>
867 	friend shared_ptr<_Tp1>
868 	allocate_shared(const _Alloc& __a, _Args&&...  __args);
869 
870       shared_ptr(const weak_ptr<_Tp>& __r, std::nothrow_t)
871       : _Base_type(__r, std::nothrow) { }
872 
873       friend class weak_ptr<_Tp>;
874 
875       template<typename _Yp>
876 	using __esft_base_t =
877 	  decltype(__expt_enable_shared_from_this_base(std::declval<_Yp*>()));
878 
879       // Detect an accessible and unambiguous enable_shared_from_this base.
880       template<typename _Yp, typename = void>
881 	struct __has_esft_base
882 	: false_type { };
883 
884       template<typename _Yp>
885 	struct __has_esft_base<_Yp, __void_t<__esft_base_t<_Yp>>>
886 	: __bool_constant<!is_array_v<_Tp>> { };  // ignore base for arrays
887 
888       template<typename _Yp>
889 	typename enable_if<__has_esft_base<_Yp>::value>::type
890 	_M_enable_shared_from_this_with(const _Yp* __p) noexcept
891 	{
892 	  if (auto __base = __expt_enable_shared_from_this_base(__p))
893 	    {
894 	      __base->_M_weak_this
895 		= shared_ptr<_Yp>(*this, const_cast<_Yp*>(__p));
896 	    }
897 	}
898 
899       template<typename _Yp>
900 	typename enable_if<!__has_esft_base<_Yp>::value>::type
901 	_M_enable_shared_from_this_with(const _Yp*) noexcept
902 	{ }
903     };
904 
905   // C++14 §20.8.2.2.7 //DOING
906   template<typename _Tp1, typename _Tp2>
907     bool operator==(const shared_ptr<_Tp1>& __a,
908 		    const shared_ptr<_Tp2>& __b) noexcept
909     { return __a.get() == __b.get(); }
910 
911   template<typename _Tp>
912     inline bool
913     operator==(const shared_ptr<_Tp>& __a, nullptr_t) noexcept
914     { return !__a; }
915 
916   template<typename _Tp>
917     inline bool
918     operator==(nullptr_t, const shared_ptr<_Tp>& __a) noexcept
919     { return !__a; }
920 
921   template<typename _Tp1, typename _Tp2>
922     inline bool
923     operator!=(const shared_ptr<_Tp1>& __a,
924 	       const shared_ptr<_Tp2>& __b) noexcept
925     { return __a.get() != __b.get(); }
926 
927   template<typename _Tp>
928     inline bool
929     operator!=(const shared_ptr<_Tp>& __a, nullptr_t) noexcept
930     { return (bool)__a; }
931 
932   template<typename _Tp>
933     inline bool
934     operator!=(nullptr_t, const shared_ptr<_Tp>& __a) noexcept
935     { return (bool)__a; }
936 
937   template<typename _Tp1, typename _Tp2>
938     inline bool
939     operator<(const shared_ptr<_Tp1>& __a,
940 	      const shared_ptr<_Tp2>& __b) noexcept
941     {
942       using __elem_t1 = typename shared_ptr<_Tp1>::element_type;
943       using __elem_t2 = typename shared_ptr<_Tp2>::element_type;
944       using _CT = common_type_t<__elem_t1*, __elem_t2*>;
945       return std::less<_CT>()(__a.get(), __b.get());
946     }
947 
948   template<typename _Tp>
949     inline bool
950     operator<(const shared_ptr<_Tp>& __a, nullptr_t) noexcept
951     {
952       using __elem_t = typename shared_ptr<_Tp>::element_type;
953       return std::less<__elem_t*>()(__a.get(), nullptr);
954     }
955 
956   template<typename _Tp>
957     inline bool
958     operator<(nullptr_t, const shared_ptr<_Tp>& __a) noexcept
959     {
960       using __elem_t = typename shared_ptr<_Tp>::element_type;
961       return std::less<__elem_t*>()(nullptr, __a.get());
962     }
963 
964   template<typename _Tp1, typename _Tp2>
965     inline bool
966     operator<=(const shared_ptr<_Tp1>& __a,
967 	       const shared_ptr<_Tp2>& __b) noexcept
968     { return !(__b < __a); }
969 
970   template<typename _Tp>
971     inline bool
972     operator<=(const shared_ptr<_Tp>& __a, nullptr_t) noexcept
973     { return !(nullptr < __a); }
974 
975   template<typename _Tp>
976     inline bool
977     operator<=(nullptr_t, const shared_ptr<_Tp>& __a) noexcept
978     { return !(__a < nullptr); }
979 
980   template<typename _Tp1, typename _Tp2>
981     inline bool
982     operator>(const shared_ptr<_Tp1>& __a,
983 	      const shared_ptr<_Tp2>& __b) noexcept
984     { return (__b < __a); }
985 
986   template<typename _Tp>
987     inline bool
988     operator>(const shared_ptr<_Tp>& __a, nullptr_t) noexcept
989     {
990       using __elem_t = typename shared_ptr<_Tp>::element_type;
991       return std::less<__elem_t*>()(nullptr, __a.get());
992     }
993 
994   template<typename _Tp>
995     inline bool
996     operator>(nullptr_t, const shared_ptr<_Tp>& __a) noexcept
997     {
998       using __elem_t = typename shared_ptr<_Tp>::element_type;
999       return std::less<__elem_t*>()(__a.get(), nullptr);
1000     }
1001 
1002   template<typename _Tp1, typename _Tp2>
1003     inline bool
1004     operator>=(const shared_ptr<_Tp1>& __a,
1005 	       const shared_ptr<_Tp2>& __b) noexcept
1006     { return !(__a < __b); }
1007 
1008   template<typename _Tp>
1009     inline bool
1010     operator>=(const shared_ptr<_Tp>& __a, nullptr_t) noexcept
1011     { return !(__a < nullptr); }
1012 
1013   template<typename _Tp>
1014     inline bool
1015     operator>=(nullptr_t, const shared_ptr<_Tp>& __a) noexcept
1016     { return !(nullptr < __a); }
1017 
1018   // C++14 §20.8.2.2.8
1019   template<typename _Tp>
1020     inline void
1021     swap(shared_ptr<_Tp>& __a, shared_ptr<_Tp>& __b) noexcept
1022     { __a.swap(__b); }
1023 
1024   // 8.2.1.3, shared_ptr casts
1025   template<typename _Tp, typename _Tp1>
1026     inline shared_ptr<_Tp>
1027     static_pointer_cast(const shared_ptr<_Tp1>& __r) noexcept
1028     {
1029       using __elem_t = typename shared_ptr<_Tp>::element_type;
1030       return shared_ptr<_Tp>(__r, static_cast<__elem_t*>(__r.get()));
1031     }
1032 
1033   template<typename _Tp, typename _Tp1>
1034     inline shared_ptr<_Tp>
1035     dynamic_pointer_cast(const shared_ptr<_Tp1>& __r) noexcept
1036     {
1037       using __elem_t = typename shared_ptr<_Tp>::element_type;
1038       if (_Tp* __p = dynamic_cast<__elem_t*>(__r.get()))
1039 	return shared_ptr<_Tp>(__r, __p);
1040       return shared_ptr<_Tp>();
1041     }
1042 
1043   template<typename _Tp, typename _Tp1>
1044     inline shared_ptr<_Tp>
1045     const_pointer_cast(const shared_ptr<_Tp1>& __r) noexcept
1046     {
1047       using __elem_t = typename shared_ptr<_Tp>::element_type;
1048       return shared_ptr<_Tp>(__r, const_cast<__elem_t*>(__r.get()));
1049     }
1050 
1051   template<typename _Tp, typename _Tp1>
1052     inline shared_ptr<_Tp>
1053     reinterpret_pointer_cast(const shared_ptr<_Tp1>& __r) noexcept
1054     {
1055       using __elem_t = typename shared_ptr<_Tp>::element_type;
1056       return shared_ptr<_Tp>(__r, reinterpret_cast<__elem_t*>(__r.get()));
1057     }
1058 
1059   // C++14 §20.8.2.3
1060   template<typename _Tp>
1061     class weak_ptr : public __weak_ptr<_Tp>
1062     {
1063       template<typename _Tp1, typename _Res = void>
1064 	using _Compatible = enable_if_t<__sp_compatible_v<_Tp1, _Tp>, _Res>;
1065 
1066       using _Base_type = __weak_ptr<_Tp>;
1067 
1068      public:
1069        constexpr weak_ptr() noexcept = default;
1070 
1071        template<typename _Tp1, typename = _Compatible<_Tp1>>
1072 	 weak_ptr(const shared_ptr<_Tp1>& __r) noexcept
1073 	 : _Base_type(__r) { }
1074 
1075        weak_ptr(const weak_ptr&) noexcept = default;
1076 
1077        template<typename _Tp1, typename = _Compatible<_Tp1>>
1078 	 weak_ptr(const weak_ptr<_Tp1>& __r) noexcept
1079 	 : _Base_type(__r) { }
1080 
1081        weak_ptr(weak_ptr&&) noexcept = default;
1082 
1083        template<typename _Tp1, typename = _Compatible<_Tp1>>
1084 	 weak_ptr(weak_ptr<_Tp1>&& __r) noexcept
1085 	 : _Base_type(std::move(__r)) { }
1086 
1087        weak_ptr&
1088        operator=(const weak_ptr& __r) noexcept = default;
1089 
1090        template<typename _Tp1>
1091 	 _Compatible<_Tp1, weak_ptr&>
1092 	 operator=(const weak_ptr<_Tp1>& __r) noexcept
1093 	 {
1094 	   this->_Base_type::operator=(__r);
1095 	   return *this;
1096 	 }
1097 
1098        template<typename _Tp1>
1099 	 _Compatible<_Tp1, weak_ptr&>
1100 	 operator=(const shared_ptr<_Tp1>& __r) noexcept
1101 	 {
1102 	   this->_Base_type::operator=(__r);
1103 	   return *this;
1104 	 }
1105 
1106        weak_ptr&
1107        operator=(weak_ptr&& __r) noexcept = default;
1108 
1109        template<typename _Tp1>
1110 	 _Compatible<_Tp1, weak_ptr&>
1111 	 operator=(weak_ptr<_Tp1>&& __r) noexcept
1112 	 {
1113 	   this->_Base_type::operator=(std::move(__r));
1114 	   return *this;
1115 	 }
1116 
1117        shared_ptr<_Tp>
1118        lock() const noexcept
1119        { return shared_ptr<_Tp>(*this, std::nothrow); }
1120 
1121        friend class enable_shared_from_this<_Tp>;
1122     };
1123 
1124   // C++14 §20.8.2.3.6
1125   template<typename _Tp>
1126     inline void
1127     swap(weak_ptr<_Tp>& __a, weak_ptr<_Tp>& __b) noexcept
1128     { __a.swap(__b); }
1129 
1130   /// C++14 §20.8.2.2.10
1131   template<typename _Del, typename _Tp, _Lock_policy _Lp>
1132     inline _Del*
1133     get_deleter(const __shared_ptr<_Tp, _Lp>& __p) noexcept
1134     { return std::get_deleter<_Del>(__p); }
1135 
1136   // C++14 §20.8.2.2.11
1137   template<typename _Ch, typename _Tr, typename _Tp, _Lock_policy _Lp>
1138     inline std::basic_ostream<_Ch, _Tr>&
1139     operator<<(std::basic_ostream<_Ch, _Tr>& __os,
1140 	       const __shared_ptr<_Tp, _Lp>& __p)
1141     {
1142       __os << __p.get();
1143       return __os;
1144     }
1145 
1146   // C++14 §20.8.2.4
1147   template<typename _Tp = void> class owner_less;
1148 
1149    /// Partial specialization of owner_less for shared_ptr.
1150   template<typename _Tp>
1151     struct owner_less<shared_ptr<_Tp>>
1152     : public _Sp_owner_less<shared_ptr<_Tp>, weak_ptr<_Tp>>
1153     { };
1154 
1155   /// Partial specialization of owner_less for weak_ptr.
1156   template<typename _Tp>
1157     struct owner_less<weak_ptr<_Tp>>
1158     : public _Sp_owner_less<weak_ptr<_Tp>, shared_ptr<_Tp>>
1159     { };
1160 
1161   template<>
1162     class owner_less<void>
1163     {
1164       template<typename _Tp, typename _Up>
1165         bool
1166         operator()(shared_ptr<_Tp> const& __lhs,
1167                    shared_ptr<_Up> const& __rhs) const
1168         { return __lhs.owner_before(__rhs); }
1169 
1170       template<typename _Tp, typename _Up>
1171         bool
1172         operator()(shared_ptr<_Tp> const& __lhs,
1173                    weak_ptr<_Up> const& __rhs) const
1174         { return __lhs.owner_before(__rhs); }
1175 
1176       template<typename _Tp, typename _Up>
1177         bool
1178         operator()(weak_ptr<_Tp> const& __lhs,
1179                    shared_ptr<_Up> const& __rhs) const
1180         { return __lhs.owner_before(__rhs); }
1181 
1182       template<typename _Tp, typename _Up>
1183         bool
1184         operator()(weak_ptr<_Tp> const& __lhs,
1185                    weak_ptr<_Up> const& __rhs) const
1186         { return __lhs.owner_before(__rhs); }
1187 
1188       typedef void is_transparent;
1189     };
1190 
1191    // C++14 §20.8.2.6
1192    template<typename _Tp>
1193      inline bool
1194      atomic_is_lock_free(const shared_ptr<_Tp>* __p)
1195      { return std::atomic_is_lock_free<_Tp, __default_lock_policy>(__p); }
1196 
1197    template<typename _Tp>
1198      shared_ptr<_Tp> atomic_load(const shared_ptr<_Tp>* __p)
1199      { return std::atomic_load<_Tp>(__p); }
1200 
1201    template<typename _Tp>
1202      shared_ptr<_Tp>
1203      atomic_load_explicit(const shared_ptr<_Tp>* __p, memory_order __mo)
1204      { return std::atomic_load_explicit<_Tp>(__p, __mo); }
1205 
1206    template<typename _Tp>
1207      void atomic_store(shared_ptr<_Tp>* __p, shared_ptr<_Tp> __r)
1208      { return std::atomic_store<_Tp>(__p, __r); }
1209 
1210    template<typename _Tp>
1211      shared_ptr<_Tp>
1212      atomic_store_explicit(const shared_ptr<_Tp>* __p,
1213 			   shared_ptr<_Tp> __r,
1214 			   memory_order __mo)
1215      { return std::atomic_store_explicit<_Tp>(__p, __r, __mo); }
1216 
1217    template<typename _Tp>
1218      void atomic_exchange(shared_ptr<_Tp>* __p, shared_ptr<_Tp> __r)
1219      { return std::atomic_exchange<_Tp>(__p, __r); }
1220 
1221    template<typename _Tp>
1222      shared_ptr<_Tp>
1223      atomic_exchange_explicit(const shared_ptr<_Tp>* __p,
1224 			      shared_ptr<_Tp> __r,
1225 			      memory_order __mo)
1226      { return std::atomic_exchange_explicit<_Tp>(__p, __r, __mo); }
1227 
1228    template<typename _Tp>
1229      bool atomic_compare_exchange_weak(shared_ptr<_Tp>* __p,
1230 				       shared_ptr<_Tp>* __v,
1231 				       shared_ptr<_Tp> __w)
1232      { return std::atomic_compare_exchange_weak<_Tp>(__p, __v, __w); }
1233 
1234    template<typename _Tp>
1235      bool atomic_compare_exchange_strong(shared_ptr<_Tp>* __p,
1236 					 shared_ptr<_Tp>* __v,
1237 					 shared_ptr<_Tp> __w)
1238      { return std::atomic_compare_exchange_strong<_Tp>(__p, __v, __w); }
1239 
1240    template<typename _Tp>
1241      bool atomic_compare_exchange_weak_explicit(shared_ptr<_Tp>* __p,
1242 						shared_ptr<_Tp>* __v,
1243 						shared_ptr<_Tp> __w,
1244 						memory_order __success,
1245 						memory_order __failure)
1246      { return std::atomic_compare_exchange_weak_explicit<_Tp>(__p, __v, __w,
1247 							      __success,
1248 							      __failure); }
1249 
1250    template<typename _Tp>
1251      bool atomic_compare_exchange_strong_explicit(shared_ptr<_Tp>* __p,
1252 						  shared_ptr<_Tp>* __v,
1253 						  shared_ptr<_Tp> __w,
1254 						  memory_order __success,
1255 						  memory_order __failure)
1256      { return std::atomic_compare_exchange_strong_explicit<_Tp>(__p, __v, __w,
1257 								__success,
1258 								__failure); }
1259 
1260   //enable_shared_from_this
1261   template<typename _Tp>
1262     class enable_shared_from_this
1263     {
1264     protected:
1265       constexpr enable_shared_from_this() noexcept { }
1266 
1267       enable_shared_from_this(const enable_shared_from_this&) noexcept { }
1268 
1269       enable_shared_from_this&
1270       operator=(const enable_shared_from_this&) noexcept
1271       { return *this; }
1272 
1273       ~enable_shared_from_this() { }
1274 
1275     public:
1276       shared_ptr<_Tp>
1277       shared_from_this()
1278       { return shared_ptr<_Tp>(this->_M_weak_this); }
1279 
1280       shared_ptr<const _Tp>
1281       shared_from_this() const
1282       { return shared_ptr<const _Tp>(this->_M_weak_this); }
1283 
1284       weak_ptr<_Tp>
1285       weak_from_this() noexcept
1286       { return _M_weak_this; }
1287 
1288       weak_ptr<const _Tp>
1289       weak_from_this() const noexcept
1290       { return _M_weak_this; }
1291 
1292     private:
1293       template<typename _Tp1>
1294 	void
1295 	_M_weak_assign(_Tp1* __p, const __shared_count<>& __n) const noexcept
1296 	{ _M_weak_this._M_assign(__p, __n); }
1297 
1298       // Found by ADL when this is an associated class.
1299       friend const enable_shared_from_this*
1300       __expt_enable_shared_from_this_base(const enable_shared_from_this* __p)
1301       { return __p; }
1302 
1303       template<typename>
1304 	friend class shared_ptr;
1305 
1306       mutable weak_ptr<_Tp> _M_weak_this;
1307     };
1308 
1309 _GLIBCXX_END_NAMESPACE_VERSION
1310 } // namespace fundamentals_v2
1311 } // namespace experimental
1312 
1313 _GLIBCXX_BEGIN_NAMESPACE_VERSION
1314 
1315   /// std::hash specialization for shared_ptr.
1316   template<typename _Tp>
1317     struct hash<experimental::shared_ptr<_Tp>>
1318     : public __hash_base<size_t, experimental::shared_ptr<_Tp>>
1319     {
1320       size_t
1321       operator()(const experimental::shared_ptr<_Tp>& __s) const noexcept
1322       { return std::hash<_Tp*>()(__s.get()); }
1323     };
1324 
1325 _GLIBCXX_END_NAMESPACE_VERSION
1326 } // namespace std
1327 
1328 #endif // __cplusplus <= 201103L
1329 
1330 #endif // _GLIBCXX_EXPERIMENTAL_SHARED_PTR_H
1331