libstdc++
experimental/bits/shared_ptr.h
Go to the documentation of this file.
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  // helper for _Compatible
73  template<typename _From_type, typename _To_type>
74  struct __sp_compatible
75  : is_convertible<_From_type*, _To_type*>::type
76  { };
77 
78  template<size_t _Nm, typename _Tp>
79  struct __sp_compatible<_Tp[_Nm], _Tp[]>
80  : true_type
81  { };
82 
83  template<size_t _Nm, typename _Tp>
84  struct __sp_compatible<_Tp[_Nm], const _Tp[]>
85  : true_type
86  { };
87 
88  // Partial specialization for base class of experimental::shared_ptr<T>
89  // (i.e. the non-array form of experimental::shared_ptr)
90  template<typename _Tp, _Lock_policy _Lp>
91  class __shared_ptr<__libfund_v1<_Tp, false>, _Lp>
92  : private __shared_ptr<_Tp, _Lp>
93  {
94  template<typename _Tp1, typename _Res = void>
95  using _Compatible
96  = enable_if_t<__sp_compatible<_Tp1, _Tp>::value, _Res>;
97 
98  using _Base_type = __shared_ptr<_Tp>;
99 
100  _Base_type& _M_get_base() { return *this;}
101  const _Base_type& _M_get_base() const { return *this;}
102 
103  public:
104  using element_type = _Tp;
105 
106  constexpr __shared_ptr() noexcept = default;
107 
108  template<typename _Tp1>
109  explicit __shared_ptr(_Tp1* __p)
110  : _Base_type(__p)
111  { }
112 
113  template<typename _Tp1, typename _Deleter>
114  __shared_ptr(_Tp1* __p, _Deleter __d)
115  : _Base_type(__p, __d)
116  { }
117 
118  template<typename _Tp1, typename _Deleter, typename _Alloc>
119  __shared_ptr(_Tp1* __p, _Deleter __d, _Alloc __a)
120  : _Base_type(__p, __d, __a)
121  { }
122 
123  template<typename _Deleter>
124  __shared_ptr(nullptr_t __p, _Deleter __d)
125  : _Base_type(__p, __d)
126  { }
127 
128  template<typename _Deleter, typename _Alloc>
129  __shared_ptr(nullptr_t __p, _Deleter __d, _Alloc __a)
130  : _Base_type(__p, __d, __a)
131  { }
132 
133  template<typename _Tp1>
134  __shared_ptr(const __shared_ptr<__libfund_v1<_Tp1>, _Lp>& __r,
135  element_type* __p) noexcept
136  : _Base_type(__r._M_get_base(), __p)
137  { }
138 
139  __shared_ptr(const __shared_ptr&) noexcept = default;
140  __shared_ptr(__shared_ptr&&) noexcept = default;
141  __shared_ptr& operator=(const __shared_ptr&) noexcept = default;
142  __shared_ptr& operator=(__shared_ptr&&) noexcept = default;
143  ~__shared_ptr() = default;
144 
145  template<typename _Tp1, typename = _Compatible<_Tp1>>
146  __shared_ptr(const __shared_ptr<__libfund_v1<_Tp1>, _Lp>& __r) noexcept
147  : _Base_type(__r._M_get_base())
148  { }
149 
150  template<typename _Tp1, typename = _Compatible<_Tp1>>
151  __shared_ptr(__shared_ptr<__libfund_v1<_Tp1>, _Lp>&& __r) noexcept
152  : _Base_type(std::move((__r._M_get_base())))
153  { }
154 
155  template<typename _Tp1>
156  explicit __shared_ptr(const __weak_ptr<__libfund_v1<_Tp1>, _Lp>& __r)
157  : _Base_type(__r._M_get_base())
158  { }
159 
160  template<typename _Tp1, typename _Del, typename
161  = _Compatible<remove_pointer_t<
162  typename unique_ptr<_Tp1, _Del>::pointer>>>
163  __shared_ptr(std::unique_ptr<_Tp1, _Del>&& __r)
164  : _Base_type(std::move(__r))
165  { }
166 
167 #if _GLIBCXX_USE_DEPRECATED
168  // Postcondition: use_count() == 1 and __r.get() == 0
169  template<typename _Tp1>
170  __shared_ptr(std::auto_ptr<_Tp1>&& __r)
171  : _Base_type(std::move(__r))
172  { }
173 #endif
174 
175  constexpr __shared_ptr(nullptr_t) noexcept : __shared_ptr() { }
176 
177  // reset
178  void
179  reset() noexcept
180  { __shared_ptr(nullptr).swap(*this); }
181 
182  template<typename _Tp1>
183  void
184  reset(_Tp1* __p)
185  {
186  _GLIBCXX_DEBUG_ASSERT(__p == 0 || __p != get());
187  __shared_ptr(__p).swap(*this);
188  }
189 
190  template<typename _Tp1, typename _Deleter>
191  void
192  reset(_Tp1* __p, _Deleter __d)
193  { __shared_ptr(__p, __d).swap(*this); }
194 
195  template<typename _Tp1, typename _Deleter, typename _Alloc>
196  void
197  reset(_Tp1* __p, _Deleter __d, _Alloc __a)
198  { __shared_ptr(__p, __d, std::move(__a)).swap(*this); }
199 
200  using _Base_type::operator*;
201  using _Base_type::operator->;
202 
203  template<typename _Tp1>
204  _Compatible<_Tp1, __shared_ptr&>
205  operator=(const __shared_ptr<__libfund_v1<_Tp1>, _Lp>& __r) noexcept
206  {
207  _Base_type::operator=(__r._M_get_base());
208  return *this;
209  }
210 
211  template<class _Tp1>
212  _Compatible<_Tp1, __shared_ptr&>
213  operator=(__shared_ptr<__libfund_v1<_Tp1>, _Lp>&& __r) noexcept
214  {
215  _Base_type::operator=(std::move(__r._M_get_base()));
216  return *this;
217  }
218 
219  template<typename _Tp1>
220  _Compatible<_Tp1, __shared_ptr&>
221  operator=(std::unique_ptr<_Tp1>&& __r)
222  {
223  _Base_type::operator=(std::move(__r));
224  return *this;
225  }
226 
227 #if _GLIBCXX_USE_DEPRECATED
228  template<typename _Tp1>
229  _Compatible<_Tp1, __shared_ptr&>
230  operator=(std::auto_ptr<_Tp1>&& __r)
231  {
232  _Base_type::operator=(std::move(__r));
233  return *this;
234  }
235 #endif
236 
237  void
238  swap(__shared_ptr& __other) noexcept
239  { _Base_type::swap(__other); }
240 
241  template<typename _Tp1>
242  bool
243  owner_before(__shared_ptr<__libfund_v1<_Tp1>, _Lp> const& __rhs) const
244  { return _Base_type::owner_before(__rhs._M_get_base()); }
245 
246  template<typename _Tp1>
247  bool
248  owner_before(__weak_ptr<__libfund_v1<_Tp1>, _Lp> const& __rhs) const
249  { return _Base_type::owner_before(__rhs._M_get_base()); }
250 
251  using _Base_type::operator bool;
252  using _Base_type::get;
253  using _Base_type::unique;
254  using _Base_type::use_count;
255 
256  protected:
257 
258  // make_shared not yet support for shared_ptr_arrays
259  //template<typename _Alloc, typename... _Args>
260  // __shared_ptr(_Sp_make_shared_tag __tag, const _Alloc& __a,
261  // _Args&&... __args)
262  // : _M_ptr(), _M_refcount(__tag, (_Tp*)0, __a,
263  // std::forward<_Args>(__args)...)
264  // {
265  // void* __p = _M_refcount._M_get_deleter(typeid(__tag));
266  // _M_ptr = static_cast<_Tp*>(__p);
267  // __enable_shared_from_this_helper(_M_refcount, _M_ptr, _M_ptr);
268  // }
269 
270  // __weak_ptr::lock()
271  __shared_ptr(const __weak_ptr<__libfund_v1<_Tp>, _Lp>& __r,
272  std::nothrow_t)
273  : _Base_type(__r._M_get_base(), std::nothrow)
274  { }
275 
276  private:
277  template<typename _Tp1, _Lock_policy _Lp1> friend class __weak_ptr;
278  template<typename _Tp1, _Lock_policy _Lp1> friend class __shared_ptr;
279 
280  // TODO
281  template<typename _Del, typename _Tp1, _Lock_policy _Lp1>
282  friend _Del* get_deleter(const __shared_ptr<_Tp1, _Lp1>&) noexcept;
283  };
284 
285  // Partial specialization for base class of experimental::shared_ptr<T[N]>
286  // and experimental::shared_ptr<T[]> (i.e. the array forms).
287  template<typename _Tp, _Lock_policy _Lp>
288  class __shared_ptr<__libfund_v1<_Tp, true>, _Lp>
289  : private __shared_ptr<remove_extent_t<_Tp>, _Lp>
290  {
291  public:
292  using element_type = remove_extent_t<_Tp>;
293 
294  private:
295  struct _Array_deleter
296  {
297  void
298  operator()(element_type const *__p) const
299  { delete [] __p; }
300  };
301 
302  template<typename _Tp1, typename _Res = void>
303  using _Compatible
304  = enable_if_t<__sp_compatible<_Tp1, _Tp>::value, _Res>;
305 
306  using _Base_type = __shared_ptr<element_type>;
307 
308  _Base_type& _M_get_base() { return *this;}
309  const _Base_type& _M_get_base() const { return *this;}
310 
311  public:
312  constexpr __shared_ptr() noexcept
313  : _Base_type()
314  { }
315 
316  template<typename _Tp1>
317  explicit __shared_ptr(_Tp1* __p)
318  : _Base_type(__p, _Array_deleter())
319  { }
320 
321  template<typename _Tp1, typename _Deleter>
322  __shared_ptr(_Tp1* __p, _Deleter __d)
323  : _Base_type(__p, __d)
324  { }
325 
326  template<typename _Tp1, typename _Deleter, typename _Alloc>
327  __shared_ptr(_Tp1* __p, _Deleter __d, _Alloc __a)
328  : _Base_type(__p, __d, __a)
329  { }
330 
331  template<typename _Deleter>
332  __shared_ptr(nullptr_t __p, _Deleter __d)
333  : _Base_type(__p, __d)
334  { }
335 
336  template<typename _Deleter, typename _Alloc>
337  __shared_ptr(nullptr_t __p, _Deleter __d, _Alloc __a)
338  : _Base_type(__p, __d, __a)
339  { }
340 
341  template<typename _Tp1>
342  __shared_ptr(const __shared_ptr<__libfund_v1<_Tp1>, _Lp>& __r,
343  element_type* __p) noexcept
344  : _Base_type(__r._M_get_base(), __p)
345  { }
346 
347  __shared_ptr(const __shared_ptr&) noexcept = default;
348  __shared_ptr(__shared_ptr&&) noexcept = default;
349  __shared_ptr& operator=(const __shared_ptr&) noexcept = default;
350  __shared_ptr& operator=(__shared_ptr&&) noexcept = default;
351  ~__shared_ptr() = default;
352 
353  template<typename _Tp1, typename = _Compatible<_Tp1>>
354  __shared_ptr(const __shared_ptr<__libfund_v1<_Tp1>, _Lp>& __r) noexcept
355  : _Base_type(__r._M_get_base())
356  { }
357 
358  template<typename _Tp1, typename = _Compatible<_Tp1>>
359  __shared_ptr(__shared_ptr<__libfund_v1<_Tp1>, _Lp>&& __r) noexcept
360  : _Base_type(std::move((__r._M_get_base())))
361  { }
362 
363  template<typename _Tp1>
364  explicit __shared_ptr(const __weak_ptr<__libfund_v1<_Tp1>, _Lp>& __r)
365  : _Base_type(__r._M_get_base())
366  { }
367 
368  template<typename _Tp1, typename _Del, typename
369  = _Compatible<remove_pointer_t<
370  typename unique_ptr<_Tp1, _Del>::pointer>>>
371  __shared_ptr(std::unique_ptr<_Tp1, _Del>&& __r)
372  : _Base_type(std::move(__r))
373  { }
374 
375 #if _GLIBCXX_USE_DEPRECATED
376  // Postcondition: use_count() == 1 and __r.get() == 0
377  template<typename _Tp1>
378  __shared_ptr(std::auto_ptr<_Tp1>&& __r)
379  : _Base_type(std::move(__r))
380  { }
381 #endif
382 
383  constexpr __shared_ptr(nullptr_t) noexcept : __shared_ptr() { }
384 
385  // reset
386  void
387  reset() noexcept
388  { __shared_ptr(nullptr).swap(*this); }
389 
390  template<typename _Tp1>
391  void
392  reset(_Tp1* __p)
393  {
394  _GLIBCXX_DEBUG_ASSERT(__p == 0 || __p != get());
395  __shared_ptr(__p, _Array_deleter()).swap(*this);
396  }
397 
398  template<typename _Tp1, typename _Deleter>
399  void
400  reset(_Tp1* __p, _Deleter __d)
401  { __shared_ptr(__p, __d).swap(*this); }
402 
403  template<typename _Tp1, typename _Deleter, typename _Alloc>
404  void
405  reset(_Tp1* __p, _Deleter __d, _Alloc __a)
406  { __shared_ptr(__p, __d, std::move(__a)).swap(*this); }
407 
408  element_type&
409  operator[](ptrdiff_t i) const noexcept
410  {
411  _GLIBCXX_DEBUG_ASSERT(get() != 0 && i >= 0);
412  return get()[i];
413  }
414 
415  template<typename _Tp1>
416  _Compatible<_Tp1, __shared_ptr&>
417  operator=(const __shared_ptr<__libfund_v1<_Tp1>, _Lp>& __r) noexcept
418  {
419  _Base_type::operator=(__r._M_get_base());
420  return *this;
421  }
422 
423  template<class _Tp1>
424  _Compatible<_Tp1, __shared_ptr&>
425  operator=(__shared_ptr<__libfund_v1<_Tp1>, _Lp>&& __r) noexcept
426  {
427  _Base_type::operator=(std::move(__r._M_get_base()));
428  return *this;
429  }
430 
431  template<typename _Tp1>
432  _Compatible<_Tp1, __shared_ptr&>
433  operator=(std::unique_ptr<_Tp1>&& __r)
434  {
435  _Base_type::operator=(std::move(__r));
436  return *this;
437  }
438 
439 #if _GLIBCXX_USE_DEPRECATED
440  template<typename _Tp1>
441  _Compatible<_Tp1, __shared_ptr&>
442  operator=(std::auto_ptr<_Tp1>&& __r)
443  {
444  _Base_type::operator=(std::move(__r));
445  return *this;
446  }
447 #endif
448 
449  void
450  swap(__shared_ptr& __other) noexcept
451  { _Base_type::swap(__other); }
452 
453  template<typename _Tp1>
454  bool
455  owner_before(__shared_ptr<__libfund_v1<_Tp1>, _Lp> const& __rhs) const
456  { return _Base_type::owner_before(__rhs._M_get_base()); }
457 
458  template<typename _Tp1>
459  bool
460  owner_before(__weak_ptr<__libfund_v1<_Tp1>, _Lp> const& __rhs) const
461  { return _Base_type::owner_before(__rhs._M_get_base()); }
462 
463  using _Base_type::operator bool;
464  using _Base_type::get;
465  using _Base_type::unique;
466  using _Base_type::use_count;
467 
468  protected:
469 
470  // make_shared not yet support for shared_ptr_arrays
471  //template<typename _Alloc, typename... _Args>
472  // __shared_ptr(_Sp_make_shared_tag __tag, const _Alloc& __a,
473  // _Args&&... __args)
474  // : _M_ptr(), _M_refcount(__tag, (_Tp*)0, __a,
475  // std::forward<_Args>(__args)...)
476  // {
477  // void* __p = _M_refcount._M_get_deleter(typeid(__tag));
478  // _M_ptr = static_cast<_Tp*>(__p);
479  // __enable_shared_from_this_helper(_M_refcount, _M_ptr, _M_ptr);
480  // }
481 
482  // __weak_ptr::lock()
483  __shared_ptr(const __weak_ptr<__libfund_v1<_Tp>, _Lp>& __r,
484  std::nothrow_t)
485  : _Base_type(__r._M_get_base(), std::nothrow)
486  { }
487 
488  private:
489  template<typename _Tp1, _Lock_policy _Lp1> friend class __weak_ptr;
490  template<typename _Tp1, _Lock_policy _Lp1> friend class __shared_ptr;
491 
492  // TODO
493  template<typename _Del, typename _Tp1, _Lock_policy _Lp1>
494  friend _Del* get_deleter(const __shared_ptr<_Tp1, _Lp1>&) noexcept;
495  };
496 
497  // weak_ptr specialization for __shared_ptr array
498  template<typename _Tp, _Lock_policy _Lp>
499  class __weak_ptr<__libfund_v1<_Tp>, _Lp>
500  : __weak_ptr<remove_extent_t<_Tp>, _Lp>
501  {
502  template<typename _Tp1, typename _Res = void>
503  using _Compatible
504  = enable_if_t<__sp_compatible<_Tp1, _Tp>::value, _Res>;
505 
506  using _Base_type = __weak_ptr<remove_extent_t<_Tp>>;
507 
508  _Base_type& _M_get_base() { return *this;}
509  const _Base_type& _M_get_base() const { return *this; }
510 
511  public:
512  using element_type = remove_extent_t<_Tp>;
513 
514  constexpr __weak_ptr() noexcept
515  : _Base_type()
516  { }
517 
518  __weak_ptr(const __weak_ptr&) noexcept = default;
519 
520  ~__weak_ptr() = default;
521 
522  template<typename _Tp1, typename = _Compatible<_Tp1>>
523  __weak_ptr(const __weak_ptr<__libfund_v1<_Tp1>, _Lp>& __r) noexcept
524  : _Base_type(__r._M_get_base())
525  { }
526 
527  template<typename _Tp1, typename = _Compatible<_Tp1>>
528  __weak_ptr(const __shared_ptr<__libfund_v1<_Tp1>, _Lp>& __r) noexcept
529  : _Base_type(__r._M_get_base())
530  { }
531 
532  __weak_ptr(__weak_ptr&& __r) noexcept
533  : _Base_type(std::move(__r))
534  { }
535 
536  template<typename _Tp1, typename = _Compatible<_Tp1>>
537  __weak_ptr(__weak_ptr<__libfund_v1<_Tp1>, _Lp>&& __r) noexcept
538  : _Base_type(std::move(__r._M_get_base()))
539  { }
540 
541  __weak_ptr&
542  operator=(const __weak_ptr& __r) noexcept = default;
543 
544  template<typename _Tp1>
545  _Compatible<_Tp1, __weak_ptr&>
546  operator=(const __weak_ptr<__libfund_v1<_Tp1>, _Lp>& __r) noexcept
547  {
548  this->_Base_type::operator=(__r._M_get_base());
549  return *this;
550  }
551 
552  template<typename _Tp1>
553  _Compatible<_Tp1, __weak_ptr&>
554  operator=(const __shared_ptr<_Tp1, _Lp>& __r) noexcept
555  {
556  this->_Base_type::operator=(__r._M_get_base());
557  return *this;
558  }
559 
560  __weak_ptr&
561  operator=(__weak_ptr&& __r) noexcept
562  {
563  this->_Base_type::operator=(std::move(__r));
564  return *this;
565  }
566 
567  template<typename _Tp1>
568  _Compatible<_Tp1, __weak_ptr&>
569  operator=(__weak_ptr<_Tp1, _Lp>&& __r) noexcept
570  {
571  this->_Base_type::operator=(std::move(__r._M_get_base()));
572  return *this;
573  }
574 
575  void
576  swap(__weak_ptr& __other) noexcept
577  { this->_Base_type::swap(__other); }
578 
579  template<typename _Tp1>
580  bool
581  owner_before(const __shared_ptr<__libfund_v1<_Tp1>, _Lp>& __rhs) const
582  { return _Base_type::owner_before(__rhs._M_get_base()); }
583 
584  template<typename _Tp1>
585  bool
586  owner_before(const __weak_ptr<__libfund_v1<_Tp1>, _Lp>& __rhs) const
587  { return _Base_type::owner_before(__rhs._M_get_base()); }
588 
589  __shared_ptr<__libfund_v1<_Tp>, _Lp>
590  lock() const noexcept // should not be element_type
591  { return __shared_ptr<__libfund_v1<_Tp>, _Lp>(*this, std::nothrow); }
592 
593  using _Base_type::use_count;
594  using _Base_type::expired;
595  using _Base_type::reset;
596 
597  private:
598  // Used by __enable_shared_from_this.
599  void
600  _M_assign(element_type* __ptr,
601  const __shared_count<_Lp>& __refcount) noexcept
602  { this->_Base_type::_M_assign(__ptr, __refcount); }
603 
604  template<typename _Tp1, _Lock_policy _Lp1> friend class __shared_ptr;
605  template<typename _Tp1, _Lock_policy _Lp1> friend class __weak_ptr;
606  friend class __enable_shared_from_this<_Tp, _Lp>;
607  friend class experimental::enable_shared_from_this<_Tp>;
608  friend class enable_shared_from_this<_Tp>;
609  };
610 
611 _GLIBCXX_END_NAMESPACE_VERSION
612 
613 namespace experimental
614 {
615 inline namespace fundamentals_v2
616 {
617 _GLIBCXX_BEGIN_NAMESPACE_VERSION
618 
619  // 8.2.1
620 
621  template<typename _Tp> class shared_ptr;
622  template<typename _Tp> class weak_ptr;
623 
624  template<typename _Tp, _Lock_policy _Lp = __default_lock_policy>
625  using __shared_ptr = std::__shared_ptr<__libfund_v1<_Tp>, _Lp>;
626 
627  template<typename _Tp, _Lock_policy _Lp = __default_lock_policy>
628  using __weak_ptr = std::__weak_ptr<__libfund_v1<_Tp>, _Lp>;
629 
630  template<typename _Tp>
631  class shared_ptr : public __shared_ptr<_Tp>
632  {
633  template<typename _Tp1, typename _Res = void>
634  using _Compatible
635  = enable_if_t<__sp_compatible<_Tp1, _Tp>::value, _Res>;
636 
637  using _Base_type = __shared_ptr<_Tp>;
638 
639  public:
640  using element_type = typename _Base_type::element_type;
641 
642  // 8.2.1.1, shared_ptr constructors
643  constexpr shared_ptr() noexcept = default;
644 
645  template<typename _Tp1>
646  explicit shared_ptr(_Tp1* __p) : _Base_type(__p) { }
647 
648  template<typename _Tp1, typename _Deleter>
649  shared_ptr(_Tp1* __p, _Deleter __d)
650  : _Base_type(__p, __d) { }
651 
652  template<typename _Tp1, typename _Deleter, typename _Alloc>
653  shared_ptr(_Tp1* __p, _Deleter __d, _Alloc __a)
654  : _Base_type(__p, __d, __a) { }
655 
656  template<typename _Deleter>
657  shared_ptr(nullptr_t __p, _Deleter __d)
658  : _Base_type(__p, __d) { }
659 
660  template<typename _Deleter, typename _Alloc>
661  shared_ptr(nullptr_t __p, _Deleter __d, _Alloc __a)
662  : _Base_type(__p, __d, __a) { }
663 
664  template<typename _Tp1>
665  shared_ptr(const shared_ptr<_Tp1>& __r, element_type* __p) noexcept
666  : _Base_type(__r, __p) { }
667 
668  shared_ptr(const shared_ptr& __r) noexcept
669  : _Base_type(__r) { }
670 
671  template<typename _Tp1, typename = _Compatible<_Tp1>>
672  shared_ptr(const shared_ptr<_Tp1>& __r) noexcept
673  : _Base_type(__r) { }
674 
675  shared_ptr(const shared_ptr<_Tp>&& __r) noexcept
676  : _Base_type(std::move(__r)) { }
677 
678  template<typename _Tp1, typename = _Compatible<_Tp1>>
679  shared_ptr(shared_ptr<_Tp1>&& __r) noexcept
680  : _Base_type(std::move(__r)) { }
681 
682  template<typename _Tp1>
683  explicit shared_ptr(const weak_ptr<_Tp1>& __r)
684  : _Base_type(__r) { }
685 
686 #if _GLIBCXX_USE_DEPRECATED
687  template<typename _Tp1>
688  shared_ptr(std::auto_ptr<_Tp1>&& __r)
689  : _Base_type() { } // TODO
690 #endif
691 
692  template<typename _Tp1, typename _Del, typename
693  = _Compatible<remove_pointer_t<
694  typename unique_ptr<_Tp1, _Del>::pointer>>>
695  shared_ptr(std::unique_ptr<_Tp1, _Del>&& __r)
696  : _Base_type(std::move(__r)) { }
697 
698  constexpr shared_ptr(nullptr_t __p)
699  : _Base_type(__p) { }
700 
701  // C++14 §20.8.2.2
702  ~shared_ptr() = default;
703 
704  // C++14 §20.8.2.3
705  shared_ptr& operator=(const shared_ptr&) noexcept = default;
706 
707  template <typename _Tp1>
708  _Compatible<_Tp1, shared_ptr&>
709  operator=(const shared_ptr<_Tp1>& __r) noexcept
710  {
711  _Base_type::operator=(__r);
712  return *this;
713  }
714 
715  shared_ptr&
716  operator=(shared_ptr&& __r) noexcept
717  {
718  _Base_type::operator=(std::move(__r));
719  return *this;
720  }
721 
722  template <typename _Tp1>
723  _Compatible<_Tp1, shared_ptr&>
724  operator=(shared_ptr<_Tp1>&& __r) noexcept
725  {
726  _Base_type::operator=(std::move(__r));
727  return *this;
728  }
729 
730 #if _GLIBCXX_USE_DEPRECATED
731  template<typename _Tp1>
732  _Compatible<_Tp1, shared_ptr&>
733  operator=(std::auto_ptr<_Tp1>&& __r)
734  {
735  __shared_ptr<_Tp>::operator=(std::move(__r));
736  return *this;
737  }
738 #endif
739 
740  template <typename _Tp1, typename _Del>
741  _Compatible<_Tp1, shared_ptr&>
742  operator=(unique_ptr<_Tp1, _Del>&& __r)
743  {
744  _Base_type::operator=(std::move(__r));
745  return *this;
746  }
747 
748  // C++14 §20.8.2.2.4
749  // swap & reset
750  // 8.2.1.2 shared_ptr observers
751  // in __shared_ptr
752 
753  private:
754  template<typename _Alloc, typename... _Args>
755  shared_ptr(_Sp_make_shared_tag __tag, const _Alloc& __a,
756  _Args&&... __args)
757  : _Base_type(__tag, __a, std::forward<_Args>(__args)...)
758  { }
759 
760  template<typename _Tp1, typename _Alloc, typename... _Args>
761  friend shared_ptr<_Tp1>
762  allocate_shared(const _Alloc& __a, _Args&&... __args);
763 
764  shared_ptr(const weak_ptr<_Tp>& __r, std::nothrow_t)
765  : _Base_type(__r, std::nothrow) { }
766 
767  friend class weak_ptr<_Tp>;
768  };
769 
770  // C++14 §20.8.2.2.7 //DOING
771  template<typename _Tp1, typename _Tp2>
772  bool operator==(const shared_ptr<_Tp1>& __a,
773  const shared_ptr<_Tp2>& __b) noexcept
774  { return __a.get() == __b.get(); }
775 
776  template<typename _Tp>
777  inline bool
778  operator==(const shared_ptr<_Tp>& __a, nullptr_t) noexcept
779  { return !__a; }
780 
781  template<typename _Tp>
782  inline bool
783  operator==(nullptr_t, const shared_ptr<_Tp>& __a) noexcept
784  { return !__a; }
785 
786  template<typename _Tp1, typename _Tp2>
787  inline bool
788  operator!=(const shared_ptr<_Tp1>& __a,
789  const shared_ptr<_Tp2>& __b) noexcept
790  { return __a.get() != __b.get(); }
791 
792  template<typename _Tp>
793  inline bool
794  operator!=(const shared_ptr<_Tp>& __a, nullptr_t) noexcept
795  { return (bool)__a; }
796 
797  template<typename _Tp>
798  inline bool
799  operator!=(nullptr_t, const shared_ptr<_Tp>& __a) noexcept
800  { return (bool)__a; }
801 
802  template<typename _Tp1, typename _Tp2>
803  inline bool
804  operator<(const shared_ptr<_Tp1>& __a,
805  const shared_ptr<_Tp2>& __b) noexcept
806  {
807  using __elem_t1 = typename shared_ptr<_Tp1>::element_type;
808  using __elem_t2 = typename shared_ptr<_Tp2>::element_type;
809  using _CT = common_type_t<__elem_t1*, __elem_t2*>;
810  return std::less<_CT>()(__a.get(), __b.get());
811  }
812 
813  template<typename _Tp>
814  inline bool
815  operator<(const shared_ptr<_Tp>& __a, nullptr_t) noexcept
816  {
817  using __elem_t = typename shared_ptr<_Tp>::element_type;
818  return std::less<__elem_t>()(__a.get(), nullptr);
819  }
820 
821  template<typename _Tp>
822  inline bool
823  operator<(nullptr_t, const shared_ptr<_Tp>& __a) noexcept
824  {
825  using __elem_t = typename shared_ptr<_Tp>::element_type;
826  return std::less<__elem_t*>()(nullptr, __a.get());
827  }
828 
829  template<typename _Tp1, typename _Tp2>
830  inline bool
831  operator<=(const shared_ptr<_Tp1>& __a,
832  const shared_ptr<_Tp2>& __b) noexcept
833  { return !(__b < __a); }
834 
835  template<typename _Tp>
836  inline bool
837  operator<=(const shared_ptr<_Tp>& __a, nullptr_t) noexcept
838  { return !(nullptr < __a); }
839 
840  template<typename _Tp>
841  inline bool
842  operator<=(nullptr_t, const shared_ptr<_Tp>& __a) noexcept
843  { return !(__a < nullptr); }
844 
845  template<typename _Tp1, typename _Tp2>
846  inline bool
847  operator>(const shared_ptr<_Tp1>& __a,
848  const shared_ptr<_Tp2>& __b) noexcept
849  { return (__b < __a); }
850 
851  template<typename _Tp>
852  inline bool
853  operator>(const shared_ptr<_Tp>& __a, nullptr_t) noexcept
854  {
855  using __elem_t = typename shared_ptr<_Tp>::element_type;
856  return std::less<__elem_t*>()(nullptr, __a.get());
857  }
858 
859  template<typename _Tp>
860  inline bool
861  operator>(nullptr_t, const shared_ptr<_Tp>& __a) noexcept
862  {
863  using __elem_t = typename shared_ptr<_Tp>::element_type;
864  return std::less<__elem_t*>()(__a.get(), nullptr);
865  }
866 
867  template<typename _Tp1, typename _Tp2>
868  inline bool
869  operator>=(const shared_ptr<_Tp1>& __a,
870  const shared_ptr<_Tp2>& __b) noexcept
871  { return !(__a < __b); }
872 
873  template<typename _Tp>
874  inline bool
875  operator>=(const shared_ptr<_Tp>& __a, nullptr_t) noexcept
876  { return !(__a < nullptr); }
877 
878  template<typename _Tp>
879  inline bool
880  operator>=(nullptr_t, const shared_ptr<_Tp>& __a) noexcept
881  { return !(nullptr < __a); }
882 
883  // C++14 §20.8.2.2.8
884  template<typename _Tp>
885  inline void
886  swap(shared_ptr<_Tp>& __a, shared_ptr<_Tp>& __b) noexcept
887  { __a.swap(__b); }
888 
889  // 8.2.1.3, shared_ptr casts
890  template<typename _Tp, typename _Tp1>
891  inline shared_ptr<_Tp>
892  static_pointer_cast(const shared_ptr<_Tp1>& __r) noexcept
893  {
894  using __elem_t = typename shared_ptr<_Tp>::element_type;
895  return shared_ptr<_Tp>(__r, static_cast<__elem_t*>(__r.get()));
896  }
897 
898  template<typename _Tp, typename _Tp1>
899  inline shared_ptr<_Tp>
900  dynamic_pointer_cast(const shared_ptr<_Tp1>& __r) noexcept
901  {
902  using __elem_t = typename shared_ptr<_Tp>::element_type;
903  if (_Tp* __p = dynamic_cast<__elem_t*>(__r.get()))
904  return shared_ptr<_Tp>(__r, __p);
905  return shared_ptr<_Tp>();
906  }
907 
908  template<typename _Tp, typename _Tp1>
909  inline shared_ptr<_Tp>
910  const_pointer_cast(const shared_ptr<_Tp1>& __r) noexcept
911  {
912  using __elem_t = typename shared_ptr<_Tp>::element_type;
913  return shared_ptr<_Tp>(__r, const_cast<__elem_t*>(__r.get()));
914  }
915 
916  template<typename _Tp, typename _Tp1>
917  inline shared_ptr<_Tp>
918  reinterpret_pointer_cast(const shared_ptr<_Tp1>& __r) noexcept
919  {
920  using __elem_t = typename shared_ptr<_Tp>::element_type;
921  return shared_ptr<_Tp>(__r, reinterpret_cast<__elem_t*>(__r.get()));
922  }
923 
924  // C++14 §20.8.2.3
925  template<typename _Tp>
926  class weak_ptr : public __weak_ptr<_Tp>
927  {
928  template<typename _Tp1, typename _Res = void>
929  using _Compatible
930  = enable_if_t<__sp_compatible<_Tp1, _Tp>::value, _Res>;
931 
932  using _Base_type = __weak_ptr<_Tp>;
933 
934  public:
935  constexpr weak_ptr() noexcept = default;
936 
937  template<typename _Tp1, typename = _Compatible<_Tp1>>
938  weak_ptr(const shared_ptr<_Tp1>& __r) noexcept
939  : _Base_type(__r) { }
940 
941  weak_ptr(const weak_ptr&) noexcept = default;
942 
943  template<typename _Tp1, typename = _Compatible<_Tp1>>
944  weak_ptr(const weak_ptr<_Tp1>& __r) noexcept
945  : _Base_type(__r) { }
946 
947  weak_ptr(weak_ptr&&) noexcept = default;
948 
949  template<typename _Tp1, typename = _Compatible<_Tp1>>
950  weak_ptr(weak_ptr<_Tp1>&& __r) noexcept
951  : _Base_type(std::move(__r)) { }
952 
953  weak_ptr&
954  operator=(const weak_ptr& __r) noexcept = default;
955 
956  template<typename _Tp1>
957  _Compatible<_Tp1, weak_ptr&>
958  operator=(const weak_ptr<_Tp1>& __r) noexcept
959  {
960  this->_Base_type::operator=(__r);
961  return *this;
962  }
963 
964  template<typename _Tp1>
965  _Compatible<_Tp1, weak_ptr&>
966  operator=(const shared_ptr<_Tp1>& __r) noexcept
967  {
968  this->_Base_type::operator=(__r);
969  return *this;
970  }
971 
972  weak_ptr&
973  operator=(weak_ptr&& __r) noexcept = default;
974 
975  template<typename _Tp1>
976  _Compatible<_Tp1, weak_ptr&>
977  operator=(weak_ptr<_Tp1>&& __r) noexcept
978  {
979  this->_Base_type::operator=(std::move(__r));
980  return *this;
981  }
982 
983  shared_ptr<_Tp>
984  lock() const noexcept
985  { return shared_ptr<_Tp>(*this, std::nothrow); }
986 
987  friend class enable_shared_from_this<_Tp>;
988  };
989 
990  // C++14 §20.8.2.3.6
991  template<typename _Tp>
992  inline void
993  swap(weak_ptr<_Tp>& __a, weak_ptr<_Tp>& __b) noexcept
994  { __a.swap(__b); }
995 
996  /// C++14 §20.8.2.2.10
997  template<typename _Del, typename _Tp, _Lock_policy _Lp>
998  inline _Del*
999  get_deleter(const __shared_ptr<_Tp, _Lp>& __p) noexcept
1000  { return std::get_deleter<_Del>(__p); }
1001 
1002  // C++14 §20.8.2.2.11
1003  template<typename _Ch, typename _Tr, typename _Tp, _Lock_policy _Lp>
1005  operator<<(std::basic_ostream<_Ch, _Tr>& __os,
1006  const __shared_ptr<_Tp, _Lp>& __p)
1007  {
1008  __os << __p.get();
1009  return __os;
1010  }
1011 
1012  // C++14 §20.8.2.4
1013  template<typename _Tp = void> class owner_less;
1014 
1015  /// Partial specialization of owner_less for shared_ptr.
1016  template<typename _Tp>
1017  struct owner_less<shared_ptr<_Tp>>
1018  : public _Sp_owner_less<shared_ptr<_Tp>, weak_ptr<_Tp>>
1019  { };
1020 
1021  /// Partial specialization of owner_less for weak_ptr.
1022  template<typename _Tp>
1023  struct owner_less<weak_ptr<_Tp>>
1024  : public _Sp_owner_less<weak_ptr<_Tp>, shared_ptr<_Tp>>
1025  { };
1026 
1027  template<>
1028  class owner_less<void>
1029  {
1030  template<typename _Tp, typename _Up>
1031  bool
1032  operator()(shared_ptr<_Tp> const& __lhs,
1033  shared_ptr<_Up> const& __rhs) const
1034  { return __lhs.owner_before(__rhs); }
1035 
1036  template<typename _Tp, typename _Up>
1037  bool
1038  operator()(shared_ptr<_Tp> const& __lhs,
1039  weak_ptr<_Up> const& __rhs) const
1040  { return __lhs.owner_before(__rhs); }
1041 
1042  template<typename _Tp, typename _Up>
1043  bool
1044  operator()(weak_ptr<_Tp> const& __lhs,
1045  shared_ptr<_Up> const& __rhs) const
1046  { return __lhs.owner_before(__rhs); }
1047 
1048  template<typename _Tp, typename _Up>
1049  bool
1050  operator()(weak_ptr<_Tp> const& __lhs,
1051  weak_ptr<_Up> const& __rhs) const
1052  { return __lhs.owner_before(__rhs); }
1053 
1054  typedef void is_transparent;
1055  };
1056 
1057  // C++14 §20.8.2.6
1058  template<typename _Tp>
1059  inline bool
1060  atomic_is_lock_free(const shared_ptr<_Tp>* __p)
1061  { return std::atomic_is_lock_free<_Tp, __default_lock_policy>(__p); }
1062 
1063  template<typename _Tp>
1064  shared_ptr<_Tp> atomic_load(const shared_ptr<_Tp>* __p)
1065  { return std::atomic_load<_Tp>(__p); }
1066 
1067  template<typename _Tp>
1068  shared_ptr<_Tp>
1069  atomic_load_explicit(const shared_ptr<_Tp>* __p, memory_order __mo)
1070  { return std::atomic_load_explicit<_Tp>(__p, __mo); }
1071 
1072  template<typename _Tp>
1073  void atomic_store(shared_ptr<_Tp>* __p, shared_ptr<_Tp> __r)
1074  { return std::atomic_store<_Tp>(__p, __r); }
1075 
1076  template<typename _Tp>
1077  shared_ptr<_Tp>
1078  atomic_store_explicit(const shared_ptr<_Tp>* __p,
1079  shared_ptr<_Tp> __r,
1080  memory_order __mo)
1081  { return std::atomic_store_explicit<_Tp>(__p, __r, __mo); }
1082 
1083  template<typename _Tp>
1084  void atomic_exchange(shared_ptr<_Tp>* __p, shared_ptr<_Tp> __r)
1085  { return std::atomic_exchange<_Tp>(__p, __r); }
1086 
1087  template<typename _Tp>
1088  shared_ptr<_Tp>
1089  atomic_exchange_explicit(const shared_ptr<_Tp>* __p,
1090  shared_ptr<_Tp> __r,
1091  memory_order __mo)
1092  { return std::atomic_exchange_explicit<_Tp>(__p, __r, __mo); }
1093 
1094  template<typename _Tp>
1095  bool atomic_compare_exchange_weak(shared_ptr<_Tp>* __p,
1096  shared_ptr<_Tp>* __v,
1097  shared_ptr<_Tp> __w)
1098  { return std::atomic_compare_exchange_weak<_Tp>(__p, __v, __w); }
1099 
1100  template<typename _Tp>
1101  bool atomic_compare_exchange_strong(shared_ptr<_Tp>* __p,
1102  shared_ptr<_Tp>* __v,
1103  shared_ptr<_Tp> __w)
1104  { return std::atomic_compare_exchange_strong<_Tp>(__p, __v, __w); }
1105 
1106  template<typename _Tp>
1107  bool atomic_compare_exchange_weak_explicit(shared_ptr<_Tp>* __p,
1108  shared_ptr<_Tp>* __v,
1109  shared_ptr<_Tp> __w,
1110  memory_order __success,
1111  memory_order __failure)
1112  { return std::atomic_compare_exchange_weak_explicit<_Tp>(__p, __v, __w,
1113  __success,
1114  __failure); }
1115 
1116  template<typename _Tp>
1117  bool atomic_compare_exchange_strong_explicit(shared_ptr<_Tp>* __p,
1118  shared_ptr<_Tp>* __v,
1119  shared_ptr<_Tp> __w,
1120  memory_order __success,
1121  memory_order __failure)
1122  { return std::atomic_compare_exchange_strong_explicit<_Tp>(__p, __v, __w,
1123  __success,
1124  __failure); }
1125 
1126  //enable_shared_from_this
1127  template<typename _Tp>
1128  class enable_shared_from_this
1129  {
1130  protected:
1131  constexpr enable_shared_from_this() noexcept { }
1132 
1133  enable_shared_from_this(const enable_shared_from_this&) noexcept { }
1134 
1135  enable_shared_from_this&
1136  operator=(const enable_shared_from_this&) noexcept
1137  { return *this; }
1138 
1139  ~enable_shared_from_this() { }
1140 
1141  public:
1142  shared_ptr<_Tp>
1143  shared_from_this()
1144  { return shared_ptr<_Tp>(this->_M_weak_this); }
1145 
1146  shared_ptr<const _Tp>
1147  shared_from_this() const
1148  { return shared_ptr<const _Tp>(this->_M_weak_this); }
1149 
1150  private:
1151  template<typename _Tp1>
1152  void
1153  _M_weak_assign(_Tp1* __p, const __shared_count<>& __n) const noexcept
1154  { _M_weak_this._M_assign(__p, __n); }
1155 
1156  template<typename _Tp1>
1157  friend void
1158  __enable_shared_from_this_helper(const __shared_count<>& __pn,
1159  const enable_shared_from_this* __pe,
1160  const _Tp1* __px) noexcept
1161  {
1162  if(__pe != 0)
1163  __pe->_M_weak_assign(const_cast<_Tp1*>(__px), __pn);
1164  }
1165 
1166  mutable weak_ptr<_Tp> _M_weak_this;
1167  };
1168 
1169 _GLIBCXX_END_NAMESPACE_VERSION
1170 } // namespace fundamentals_v2
1171 } // namespace experimental
1172 
1173 _GLIBCXX_BEGIN_NAMESPACE_VERSION
1174 
1175  /// std::hash specialization for shared_ptr.
1176  template<typename _Tp>
1177  struct hash<experimental::shared_ptr<_Tp>>
1178  : public __hash_base<size_t, experimental::shared_ptr<_Tp>>
1179  {
1180  size_t
1181  operator()(const experimental::shared_ptr<_Tp>& __s) const noexcept
1182  { return std::hash<_Tp*>()(__s.get()); }
1183  };
1184 
1185 _GLIBCXX_END_NAMESPACE_VERSION
1186 } // namespace std
1187 
1188 #endif // __cplusplus <= 201103L
1189 
1190 #endif // _GLIBCXX_EXPERIMENTAL_SHARED_PTR_H
Template class basic_ostream.
Definition: iosfwd:86
A smart pointer with reference-counted copy semantics.
constexpr _Tp && forward(typename std::remove_reference< _Tp >::type &__t) noexcept
Forward an lvalue.
Definition: move.h:76
shared_ptr< _Tp > allocate_shared(const _Alloc &__a, _Args &&...__args)
Create an object that is owned by a shared_ptr.
Partial specializations for pointer types.
memory_order
Enumeration for memory_order.
Definition: atomic_base.h:55
A simple smart pointer providing strict ownership semantics.
Definition: auto_ptr.h:87
One of the comparison functors.
Definition: stl_function.h:340
void lock(_L1 &__l1, _L2 &__l2, _L3 &...__l3)
Generic lock.
Definition: mutex:540
20.7.1.2 unique_ptr for single objects.
Definition: unique_ptr.h:116
_Del * get_deleter(const __shared_ptr< _Tp, _Lp > &__p) noexcept
20.7.2.2.10 shared_ptr get_deleter
ISO C++ entities toplevel namespace is std.
integral_constant< bool, true > true_type
The type used as a compile-time boolean with true value.
Definition: type_traits:87
Primary class template hash.
Definition: system_error:134