[libc++] Implement shared_ptr methods inline in the class

This patch refactors the shared_ptr methods from being defined out-of-line
to being defined inline in the class, like what we do for all new code in
the library. The benefits of doing that are that code is not as scattered
around and is hence easier to understand, and it avoids a ton of duplication
due to SFINAE checks. Defining the method where it is declared also removes
the possibility for mismatched attributes.

As a fly-by change, this also:

- Adds a few _LIBCPP_HIDE_FROM_ABI attributes
- Uses __enable_if_t instead of enable_if as a function argument, to match
  the style that we use everywhere else.

Differential Revision: https://reviews.llvm.org/D112478
This commit is contained in:
Louis Dionne 2021-10-25 15:05:27 -04:00
parent da1318ccca
commit b2d25ef2d1
1 changed files with 422 additions and 582 deletions

View File

@ -430,12 +430,18 @@ private:
element_type* __ptr_;
__shared_weak_count* __cntrl_;
struct __nat {int __for_bool_;};
public:
_LIBCPP_INLINE_VISIBILITY
_LIBCPP_CONSTEXPR shared_ptr() _NOEXCEPT;
_LIBCPP_INLINE_VISIBILITY
_LIBCPP_CONSTEXPR shared_ptr(nullptr_t) _NOEXCEPT;
_LIBCPP_HIDE_FROM_ABI
_LIBCPP_CONSTEXPR shared_ptr() _NOEXCEPT
: __ptr_(nullptr),
__cntrl_(nullptr)
{ }
_LIBCPP_HIDE_FROM_ABI
_LIBCPP_CONSTEXPR shared_ptr(nullptr_t) _NOEXCEPT
: __ptr_(nullptr),
__cntrl_(nullptr)
{ }
template<class _Yp, class = __enable_if_t<
_And<
@ -457,263 +463,11 @@ public:
__enable_weak_this(__p, __p);
}
template<class _Yp, class _Dp>
shared_ptr(_Yp* __p, _Dp __d,
typename enable_if<__shared_ptr_deleter_ctor_reqs<_Dp, _Yp, element_type>::value, __nat>::type = __nat());
template<class _Yp, class _Dp, class _Alloc>
shared_ptr(_Yp* __p, _Dp __d, _Alloc __a,
typename enable_if<__shared_ptr_deleter_ctor_reqs<_Dp, _Yp, element_type>::value, __nat>::type = __nat());
template <class _Dp> shared_ptr(nullptr_t __p, _Dp __d);
template <class _Dp, class _Alloc> shared_ptr(nullptr_t __p, _Dp __d, _Alloc __a);
template<class _Yp> _LIBCPP_INLINE_VISIBILITY shared_ptr(const shared_ptr<_Yp>& __r, element_type* __p) _NOEXCEPT;
_LIBCPP_INLINE_VISIBILITY
shared_ptr(const shared_ptr& __r) _NOEXCEPT;
template<class _Yp>
_LIBCPP_INLINE_VISIBILITY
shared_ptr(const shared_ptr<_Yp>& __r,
typename enable_if<__compatible_with<_Yp, _Tp>::value, __nat>::type = __nat())
_NOEXCEPT;
_LIBCPP_INLINE_VISIBILITY
shared_ptr(shared_ptr&& __r) _NOEXCEPT;
template<class _Yp> _LIBCPP_INLINE_VISIBILITY shared_ptr(shared_ptr<_Yp>&& __r,
typename enable_if<__compatible_with<_Yp, _Tp>::value, __nat>::type = __nat())
_NOEXCEPT;
template<class _Yp> explicit shared_ptr(const weak_ptr<_Yp>& __r,
typename enable_if<__compatible_with<_Yp, _Tp>::value, __nat>::type = __nat());
#if _LIBCPP_STD_VER <= 14 || defined(_LIBCPP_ENABLE_CXX17_REMOVED_AUTO_PTR)
template<class _Yp>
shared_ptr(auto_ptr<_Yp>&& __r,
typename enable_if<is_convertible<_Yp*, element_type*>::value, __nat>::type = __nat());
#endif
template <class _Yp, class _Dp>
shared_ptr(unique_ptr<_Yp, _Dp>&&,
typename enable_if
<
!is_lvalue_reference<_Dp>::value &&
is_convertible<typename unique_ptr<_Yp, _Dp>::pointer, element_type*>::value,
__nat
>::type = __nat());
template <class _Yp, class _Dp>
shared_ptr(unique_ptr<_Yp, _Dp>&&,
typename enable_if
<
is_lvalue_reference<_Dp>::value &&
is_convertible<typename unique_ptr<_Yp, _Dp>::pointer, element_type*>::value,
__nat
>::type = __nat());
~shared_ptr();
_LIBCPP_INLINE_VISIBILITY
shared_ptr& operator=(const shared_ptr& __r) _NOEXCEPT;
template<class _Yp>
typename enable_if
<
__compatible_with<_Yp, _Tp>::value,
shared_ptr&
>::type
_LIBCPP_INLINE_VISIBILITY
operator=(const shared_ptr<_Yp>& __r) _NOEXCEPT;
_LIBCPP_INLINE_VISIBILITY
shared_ptr& operator=(shared_ptr&& __r) _NOEXCEPT;
template<class _Yp>
typename enable_if
<
__compatible_with<_Yp, _Tp>::value,
shared_ptr&
>::type
_LIBCPP_INLINE_VISIBILITY
operator=(shared_ptr<_Yp>&& __r);
#if _LIBCPP_STD_VER <= 14 || defined(_LIBCPP_ENABLE_CXX17_REMOVED_AUTO_PTR)
template<class _Yp>
_LIBCPP_INLINE_VISIBILITY
typename enable_if
<
!is_array<_Yp>::value &&
is_convertible<_Yp*, element_type*>::value,
shared_ptr
>::type&
operator=(auto_ptr<_Yp>&& __r);
#endif
template <class _Yp, class _Dp>
typename enable_if
<
is_convertible<typename unique_ptr<_Yp, _Dp>::pointer, element_type*>::value,
shared_ptr&
>::type
_LIBCPP_INLINE_VISIBILITY
operator=(unique_ptr<_Yp, _Dp>&& __r);
_LIBCPP_INLINE_VISIBILITY
void swap(shared_ptr& __r) _NOEXCEPT;
_LIBCPP_INLINE_VISIBILITY
void reset() _NOEXCEPT;
template<class _Yp>
typename enable_if
<
__compatible_with<_Yp, _Tp>::value,
void
>::type
_LIBCPP_INLINE_VISIBILITY
reset(_Yp* __p);
template<class _Yp, class _Dp>
typename enable_if
<
__compatible_with<_Yp, _Tp>::value,
void
>::type
_LIBCPP_INLINE_VISIBILITY
reset(_Yp* __p, _Dp __d);
template<class _Yp, class _Dp, class _Alloc>
typename enable_if
<
__compatible_with<_Yp, _Tp>::value,
void
>::type
_LIBCPP_INLINE_VISIBILITY
reset(_Yp* __p, _Dp __d, _Alloc __a);
_LIBCPP_INLINE_VISIBILITY
element_type* get() const _NOEXCEPT {return __ptr_;}
_LIBCPP_INLINE_VISIBILITY
typename add_lvalue_reference<element_type>::type operator*() const _NOEXCEPT
{return *__ptr_;}
_LIBCPP_INLINE_VISIBILITY
element_type* operator->() const _NOEXCEPT
{
static_assert(!is_array<_Tp>::value,
"std::shared_ptr<T>::operator-> is only valid when T is not an array type.");
return __ptr_;
}
_LIBCPP_INLINE_VISIBILITY
long use_count() const _NOEXCEPT {return __cntrl_ ? __cntrl_->use_count() : 0;}
_LIBCPP_INLINE_VISIBILITY
bool unique() const _NOEXCEPT {return use_count() == 1;}
_LIBCPP_INLINE_VISIBILITY
explicit operator bool() const _NOEXCEPT {return get() != nullptr;}
template <class _Up>
_LIBCPP_INLINE_VISIBILITY
bool owner_before(shared_ptr<_Up> const& __p) const _NOEXCEPT
{return __cntrl_ < __p.__cntrl_;}
template <class _Up>
_LIBCPP_INLINE_VISIBILITY
bool owner_before(weak_ptr<_Up> const& __p) const _NOEXCEPT
{return __cntrl_ < __p.__cntrl_;}
_LIBCPP_INLINE_VISIBILITY
bool
__owner_equivalent(const shared_ptr& __p) const
{return __cntrl_ == __p.__cntrl_;}
#if _LIBCPP_STD_VER > 14
typename add_lvalue_reference<element_type>::type
_LIBCPP_INLINE_VISIBILITY
operator[](ptrdiff_t __i) const
{
static_assert(is_array<_Tp>::value,
"std::shared_ptr<T>::operator[] is only valid when T is an array type.");
return __ptr_[__i];
}
#endif
#ifndef _LIBCPP_NO_RTTI
template <class _Dp>
_LIBCPP_INLINE_VISIBILITY
_Dp* __get_deleter() const _NOEXCEPT
{return static_cast<_Dp*>(__cntrl_
? const_cast<void *>(__cntrl_->__get_deleter(typeid(_Dp)))
: nullptr);}
#endif // _LIBCPP_NO_RTTI
template<class _Yp, class _CntrlBlk>
static shared_ptr<_Tp>
__create_with_control_block(_Yp* __p, _CntrlBlk* __cntrl) _NOEXCEPT
{
shared_ptr<_Tp> __r;
__r.__ptr_ = __p;
__r.__cntrl_ = __cntrl;
__r.__enable_weak_this(__r.__ptr_, __r.__ptr_);
return __r;
}
private:
template <class _Yp, bool = is_function<_Yp>::value>
struct __shared_ptr_default_allocator
{
typedef allocator<_Yp> type;
};
template <class _Yp>
struct __shared_ptr_default_allocator<_Yp, true>
{
typedef allocator<__shared_ptr_dummy_rebind_allocator_type> type;
};
template <class _Yp, class _OrigPtr>
_LIBCPP_INLINE_VISIBILITY
typename enable_if<is_convertible<_OrigPtr*,
const enable_shared_from_this<_Yp>*
>::value,
void>::type
__enable_weak_this(const enable_shared_from_this<_Yp>* __e,
_OrigPtr* __ptr) _NOEXCEPT
{
typedef typename remove_cv<_Yp>::type _RawYp;
if (__e && __e->__weak_this_.expired())
{
__e->__weak_this_ = shared_ptr<_RawYp>(*this,
const_cast<_RawYp*>(static_cast<const _Yp*>(__ptr)));
}
}
_LIBCPP_INLINE_VISIBILITY void __enable_weak_this(...) _NOEXCEPT {}
template <class, class _Yp>
struct __shared_ptr_default_delete
: default_delete<_Yp> {};
template <class _Yp, class _Un, size_t _Sz>
struct __shared_ptr_default_delete<_Yp[_Sz], _Un>
: default_delete<_Yp[]> {};
template <class _Yp, class _Un>
struct __shared_ptr_default_delete<_Yp[], _Un>
: default_delete<_Yp[]> {};
template <class _Up> friend class _LIBCPP_TEMPLATE_VIS shared_ptr;
template <class _Up> friend class _LIBCPP_TEMPLATE_VIS weak_ptr;
};
#if _LIBCPP_STD_VER > 14
template<class _Tp>
shared_ptr(weak_ptr<_Tp>) -> shared_ptr<_Tp>;
template<class _Tp, class _Dp>
shared_ptr(unique_ptr<_Tp, _Dp>) -> shared_ptr<_Tp>;
#endif
template<class _Tp>
inline
_LIBCPP_CONSTEXPR
shared_ptr<_Tp>::shared_ptr() _NOEXCEPT
: __ptr_(nullptr),
__cntrl_(nullptr)
{
}
template<class _Tp>
inline
_LIBCPP_CONSTEXPR
shared_ptr<_Tp>::shared_ptr(nullptr_t) _NOEXCEPT
: __ptr_(nullptr),
__cntrl_(nullptr)
{
}
template<class _Tp>
template<class _Yp, class _Dp>
shared_ptr<_Tp>::shared_ptr(_Yp* __p, _Dp __d,
typename enable_if<__shared_ptr_deleter_ctor_reqs<_Dp, _Yp, element_type>::value, __nat>::type)
template<class _Yp, class _Dp, class = __enable_if_t<__shared_ptr_deleter_ctor_reqs<_Dp, _Yp, element_type>::value> >
_LIBCPP_HIDE_FROM_ABI
shared_ptr(_Yp* __p, _Dp __d)
: __ptr_(__p)
{
{
#ifndef _LIBCPP_NO_EXCEPTIONS
try
{
@ -734,40 +488,13 @@ shared_ptr<_Tp>::shared_ptr(_Yp* __p, _Dp __d,
throw;
}
#endif // _LIBCPP_NO_EXCEPTIONS
}
template<class _Tp>
template<class _Dp>
shared_ptr<_Tp>::shared_ptr(nullptr_t __p, _Dp __d)
: __ptr_(nullptr)
{
#ifndef _LIBCPP_NO_EXCEPTIONS
try
{
#endif // _LIBCPP_NO_EXCEPTIONS
typedef typename __shared_ptr_default_allocator<_Tp>::type _AllocT;
typedef __shared_ptr_pointer<nullptr_t, _Dp, _AllocT > _CntrlBlk;
#ifndef _LIBCPP_CXX03_LANG
__cntrl_ = new _CntrlBlk(__p, _VSTD::move(__d), _AllocT());
#else
__cntrl_ = new _CntrlBlk(__p, __d, _AllocT());
#endif // not _LIBCPP_CXX03_LANG
#ifndef _LIBCPP_NO_EXCEPTIONS
}
catch (...)
{
__d(__p);
throw;
}
#endif // _LIBCPP_NO_EXCEPTIONS
}
template<class _Tp>
template<class _Yp, class _Dp, class _Alloc>
shared_ptr<_Tp>::shared_ptr(_Yp* __p, _Dp __d, _Alloc __a,
typename enable_if<__shared_ptr_deleter_ctor_reqs<_Dp, _Yp, element_type>::value, __nat>::type)
template<class _Yp, class _Dp, class _Alloc, class = __enable_if_t<__shared_ptr_deleter_ctor_reqs<_Dp, _Yp, element_type>::value> >
_LIBCPP_HIDE_FROM_ABI
shared_ptr(_Yp* __p, _Dp __d, _Alloc __a)
: __ptr_(__p)
{
{
#ifndef _LIBCPP_NO_EXCEPTIONS
try
{
@ -793,13 +520,39 @@ shared_ptr<_Tp>::shared_ptr(_Yp* __p, _Dp __d, _Alloc __a,
throw;
}
#endif // _LIBCPP_NO_EXCEPTIONS
}
}
template<class _Tp>
template<class _Dp, class _Alloc>
shared_ptr<_Tp>::shared_ptr(nullptr_t __p, _Dp __d, _Alloc __a)
template<class _Dp>
_LIBCPP_HIDE_FROM_ABI
shared_ptr(nullptr_t __p, _Dp __d)
: __ptr_(nullptr)
{
{
#ifndef _LIBCPP_NO_EXCEPTIONS
try
{
#endif // _LIBCPP_NO_EXCEPTIONS
typedef typename __shared_ptr_default_allocator<_Tp>::type _AllocT;
typedef __shared_ptr_pointer<nullptr_t, _Dp, _AllocT > _CntrlBlk;
#ifndef _LIBCPP_CXX03_LANG
__cntrl_ = new _CntrlBlk(__p, _VSTD::move(__d), _AllocT());
#else
__cntrl_ = new _CntrlBlk(__p, __d, _AllocT());
#endif // not _LIBCPP_CXX03_LANG
#ifndef _LIBCPP_NO_EXCEPTIONS
}
catch (...)
{
__d(__p);
throw;
}
#endif // _LIBCPP_NO_EXCEPTIONS
}
template<class _Dp, class _Alloc>
_LIBCPP_HIDE_FROM_ABI
shared_ptr(nullptr_t __p, _Dp __d, _Alloc __a)
: __ptr_(nullptr)
{
#ifndef _LIBCPP_NO_EXCEPTIONS
try
{
@ -824,90 +577,87 @@ shared_ptr<_Tp>::shared_ptr(nullptr_t __p, _Dp __d, _Alloc __a)
throw;
}
#endif // _LIBCPP_NO_EXCEPTIONS
}
}
template<class _Tp>
template<class _Yp>
inline
shared_ptr<_Tp>::shared_ptr(const shared_ptr<_Yp>& __r, element_type *__p) _NOEXCEPT
template<class _Yp>
_LIBCPP_HIDE_FROM_ABI
shared_ptr(const shared_ptr<_Yp>& __r, element_type *__p) _NOEXCEPT
: __ptr_(__p),
__cntrl_(__r.__cntrl_)
{
{
if (__cntrl_)
__cntrl_->__add_shared();
}
}
template<class _Tp>
inline
shared_ptr<_Tp>::shared_ptr(const shared_ptr& __r) _NOEXCEPT
_LIBCPP_HIDE_FROM_ABI
shared_ptr(const shared_ptr& __r) _NOEXCEPT
: __ptr_(__r.__ptr_),
__cntrl_(__r.__cntrl_)
{
{
if (__cntrl_)
__cntrl_->__add_shared();
}
}
template<class _Tp>
template<class _Yp>
inline
shared_ptr<_Tp>::shared_ptr(const shared_ptr<_Yp>& __r,
typename enable_if<__compatible_with<_Yp, _Tp>::value, __nat>::type)
_NOEXCEPT
template<class _Yp, class = __enable_if_t<__compatible_with<_Yp, _Tp>::value> >
_LIBCPP_HIDE_FROM_ABI
shared_ptr(const shared_ptr<_Yp>& __r) _NOEXCEPT
: __ptr_(__r.__ptr_),
__cntrl_(__r.__cntrl_)
{
{
if (__cntrl_)
__cntrl_->__add_shared();
}
}
template<class _Tp>
inline
shared_ptr<_Tp>::shared_ptr(shared_ptr&& __r) _NOEXCEPT
_LIBCPP_HIDE_FROM_ABI
shared_ptr(shared_ptr&& __r) _NOEXCEPT
: __ptr_(__r.__ptr_),
__cntrl_(__r.__cntrl_)
{
{
__r.__ptr_ = nullptr;
__r.__cntrl_ = nullptr;
}
}
template<class _Tp>
template<class _Yp>
inline
shared_ptr<_Tp>::shared_ptr(shared_ptr<_Yp>&& __r,
typename enable_if<__compatible_with<_Yp, _Tp>::value, __nat>::type)
_NOEXCEPT
template<class _Yp, class = __enable_if_t<__compatible_with<_Yp, _Tp>::value> >
_LIBCPP_HIDE_FROM_ABI
shared_ptr(shared_ptr<_Yp>&& __r) _NOEXCEPT
: __ptr_(__r.__ptr_),
__cntrl_(__r.__cntrl_)
{
{
__r.__ptr_ = nullptr;
__r.__cntrl_ = nullptr;
}
}
template<class _Yp, class = __enable_if_t<__compatible_with<_Yp, _Tp>::value> >
_LIBCPP_HIDE_FROM_ABI
explicit shared_ptr(const weak_ptr<_Yp>& __r)
: __ptr_(__r.__ptr_),
__cntrl_(__r.__cntrl_ ? __r.__cntrl_->lock() : __r.__cntrl_)
{
if (__cntrl_ == nullptr)
__throw_bad_weak_ptr();
}
#if _LIBCPP_STD_VER <= 14 || defined(_LIBCPP_ENABLE_CXX17_REMOVED_AUTO_PTR)
template<class _Tp>
template<class _Yp>
shared_ptr<_Tp>::shared_ptr(auto_ptr<_Yp>&& __r,
typename enable_if<is_convertible<_Yp*, element_type*>::value, __nat>::type)
template<class _Yp, class = __enable_if_t<is_convertible<_Yp*, element_type*>::value> >
_LIBCPP_HIDE_FROM_ABI
shared_ptr(auto_ptr<_Yp>&& __r)
: __ptr_(__r.get())
{
{
typedef __shared_ptr_pointer<_Yp*, default_delete<_Yp>, allocator<_Yp> > _CntrlBlk;
__cntrl_ = new _CntrlBlk(__r.get(), default_delete<_Yp>(), allocator<_Yp>());
__enable_weak_this(__r.get(), __r.get());
__r.release();
}
}
#endif
template<class _Tp>
template <class _Yp, class _Dp>
shared_ptr<_Tp>::shared_ptr(unique_ptr<_Yp, _Dp>&& __r,
typename enable_if
<
template <class _Yp, class _Dp, class = __enable_if_t<
!is_lvalue_reference<_Dp>::value &&
is_convertible<typename unique_ptr<_Yp, _Dp>::pointer, element_type*>::value,
__nat
>::type)
is_convertible<typename unique_ptr<_Yp, _Dp>::pointer, element_type*>::value
> >
_LIBCPP_HIDE_FROM_ABI
shared_ptr(unique_ptr<_Yp, _Dp>&& __r)
: __ptr_(__r.get())
{
{
#if _LIBCPP_STD_VER > 11
if (__ptr_ == nullptr)
__cntrl_ = nullptr;
@ -920,19 +670,16 @@ shared_ptr<_Tp>::shared_ptr(unique_ptr<_Yp, _Dp>&& __r,
__enable_weak_this(__r.get(), __r.get());
}
__r.release();
}
}
template<class _Tp>
template <class _Yp, class _Dp>
shared_ptr<_Tp>::shared_ptr(unique_ptr<_Yp, _Dp>&& __r,
typename enable_if
<
template <class _Yp, class _Dp, class = void, class = __enable_if_t<
is_lvalue_reference<_Dp>::value &&
is_convertible<typename unique_ptr<_Yp, _Dp>::pointer, element_type*>::value,
__nat
>::type)
is_convertible<typename unique_ptr<_Yp, _Dp>::pointer, element_type*>::value
> >
_LIBCPP_HIDE_FROM_ABI
shared_ptr(unique_ptr<_Yp, _Dp>&& __r)
: __ptr_(__r.get())
{
{
#if _LIBCPP_STD_VER > 11
if (__ptr_ == nullptr)
__cntrl_ = nullptr;
@ -947,148 +694,252 @@ shared_ptr<_Tp>::shared_ptr(unique_ptr<_Yp, _Dp>&& __r,
__enable_weak_this(__r.get(), __r.get());
}
__r.release();
}
}
template<class _Tp>
shared_ptr<_Tp>::~shared_ptr()
{
_LIBCPP_HIDE_FROM_ABI
~shared_ptr()
{
if (__cntrl_)
__cntrl_->__release_shared();
}
}
template<class _Tp>
inline
shared_ptr<_Tp>&
shared_ptr<_Tp>::operator=(const shared_ptr& __r) _NOEXCEPT
{
_LIBCPP_HIDE_FROM_ABI
shared_ptr<_Tp>& operator=(const shared_ptr& __r) _NOEXCEPT
{
shared_ptr(__r).swap(*this);
return *this;
}
}
template<class _Tp>
template<class _Yp>
inline
typename enable_if
<
__compatible_with<_Yp, _Tp>::value,
shared_ptr<_Tp>&
>::type
shared_ptr<_Tp>::operator=(const shared_ptr<_Yp>& __r) _NOEXCEPT
{
template<class _Yp, class = __enable_if_t<__compatible_with<_Yp, _Tp>::value> >
_LIBCPP_HIDE_FROM_ABI
shared_ptr<_Tp>& operator=(const shared_ptr<_Yp>& __r) _NOEXCEPT
{
shared_ptr(__r).swap(*this);
return *this;
}
}
template<class _Tp>
inline
shared_ptr<_Tp>&
shared_ptr<_Tp>::operator=(shared_ptr&& __r) _NOEXCEPT
{
_LIBCPP_HIDE_FROM_ABI
shared_ptr<_Tp>& operator=(shared_ptr&& __r) _NOEXCEPT
{
shared_ptr(_VSTD::move(__r)).swap(*this);
return *this;
}
}
template<class _Tp>
template<class _Yp>
inline
typename enable_if
<
__compatible_with<_Yp, _Tp>::value,
shared_ptr<_Tp>&
>::type
shared_ptr<_Tp>::operator=(shared_ptr<_Yp>&& __r)
{
template<class _Yp, class = __enable_if_t<__compatible_with<_Yp, _Tp>::value> >
_LIBCPP_HIDE_FROM_ABI
shared_ptr<_Tp>& operator=(shared_ptr<_Yp>&& __r)
{
shared_ptr(_VSTD::move(__r)).swap(*this);
return *this;
}
}
#if _LIBCPP_STD_VER <= 14 || defined(_LIBCPP_ENABLE_CXX17_REMOVED_AUTO_PTR)
template<class _Tp>
template<class _Yp>
inline
typename enable_if
<
template<class _Yp, class = __enable_if_t<
!is_array<_Yp>::value &&
is_convertible<_Yp*, typename shared_ptr<_Tp>::element_type*>::value,
shared_ptr<_Tp>
>::type&
shared_ptr<_Tp>::operator=(auto_ptr<_Yp>&& __r)
{
is_convertible<_Yp*, typename shared_ptr<_Tp>::element_type*>::value
> >
_LIBCPP_HIDE_FROM_ABI
shared_ptr<_Tp>& operator=(auto_ptr<_Yp>&& __r)
{
shared_ptr(_VSTD::move(__r)).swap(*this);
return *this;
}
}
#endif
template<class _Tp>
template <class _Yp, class _Dp>
inline
typename enable_if
<
is_convertible<typename unique_ptr<_Yp, _Dp>::pointer,
typename shared_ptr<_Tp>::element_type*>::value,
shared_ptr<_Tp>&
>::type
shared_ptr<_Tp>::operator=(unique_ptr<_Yp, _Dp>&& __r)
{
template <class _Yp, class _Dp, class = __enable_if_t<
is_convertible<typename unique_ptr<_Yp, _Dp>::pointer, element_type*>::value
> >
_LIBCPP_HIDE_FROM_ABI
shared_ptr<_Tp>& operator=(unique_ptr<_Yp, _Dp>&& __r)
{
shared_ptr(_VSTD::move(__r)).swap(*this);
return *this;
}
}
template<class _Tp>
inline
void
shared_ptr<_Tp>::swap(shared_ptr& __r) _NOEXCEPT
{
_LIBCPP_HIDE_FROM_ABI
void swap(shared_ptr& __r) _NOEXCEPT
{
_VSTD::swap(__ptr_, __r.__ptr_);
_VSTD::swap(__cntrl_, __r.__cntrl_);
}
}
template<class _Tp>
inline
void
shared_ptr<_Tp>::reset() _NOEXCEPT
{
_LIBCPP_HIDE_FROM_ABI
void reset() _NOEXCEPT
{
shared_ptr().swap(*this);
}
}
template<class _Tp>
template<class _Yp>
inline
typename enable_if
<
__compatible_with<_Yp, _Tp>::value,
void
>::type
shared_ptr<_Tp>::reset(_Yp* __p)
{
template<class _Yp, class = __enable_if_t<
__compatible_with<_Yp, _Tp>::value
> >
_LIBCPP_HIDE_FROM_ABI
void reset(_Yp* __p)
{
shared_ptr(__p).swap(*this);
}
}
template<class _Tp>
template<class _Yp, class _Dp>
inline
typename enable_if
<
__compatible_with<_Yp, _Tp>::value,
void
>::type
shared_ptr<_Tp>::reset(_Yp* __p, _Dp __d)
{
template<class _Yp, class _Dp, class = __enable_if_t<
__compatible_with<_Yp, _Tp>::value
> >
_LIBCPP_HIDE_FROM_ABI
void reset(_Yp* __p, _Dp __d)
{
shared_ptr(__p, __d).swap(*this);
}
}
template<class _Tp>
template<class _Yp, class _Dp, class _Alloc>
inline
typename enable_if
<
__compatible_with<_Yp, _Tp>::value,
void
>::type
shared_ptr<_Tp>::reset(_Yp* __p, _Dp __d, _Alloc __a)
{
template<class _Yp, class _Dp, class _Alloc, class = __enable_if_t<
__compatible_with<_Yp, _Tp>::value
> >
_LIBCPP_HIDE_FROM_ABI
void reset(_Yp* __p, _Dp __d, _Alloc __a)
{
shared_ptr(__p, __d, __a).swap(*this);
}
}
_LIBCPP_HIDE_FROM_ABI
element_type* get() const _NOEXCEPT
{
return __ptr_;
}
_LIBCPP_HIDE_FROM_ABI
typename add_lvalue_reference<element_type>::type operator*() const _NOEXCEPT
{
return *__ptr_;
}
_LIBCPP_HIDE_FROM_ABI
element_type* operator->() const _NOEXCEPT
{
static_assert(!is_array<_Tp>::value,
"std::shared_ptr<T>::operator-> is only valid when T is not an array type.");
return __ptr_;
}
_LIBCPP_HIDE_FROM_ABI
long use_count() const _NOEXCEPT
{
return __cntrl_ ? __cntrl_->use_count() : 0;
}
_LIBCPP_HIDE_FROM_ABI
bool unique() const _NOEXCEPT
{
return use_count() == 1;
}
_LIBCPP_HIDE_FROM_ABI
explicit operator bool() const _NOEXCEPT
{
return get() != nullptr;
}
template <class _Up>
_LIBCPP_HIDE_FROM_ABI
bool owner_before(shared_ptr<_Up> const& __p) const _NOEXCEPT
{
return __cntrl_ < __p.__cntrl_;
}
template <class _Up>
_LIBCPP_HIDE_FROM_ABI
bool owner_before(weak_ptr<_Up> const& __p) const _NOEXCEPT
{
return __cntrl_ < __p.__cntrl_;
}
_LIBCPP_HIDE_FROM_ABI
bool __owner_equivalent(const shared_ptr& __p) const
{
return __cntrl_ == __p.__cntrl_;
}
#if _LIBCPP_STD_VER > 14
_LIBCPP_HIDE_FROM_ABI
typename add_lvalue_reference<element_type>::type operator[](ptrdiff_t __i) const
{
static_assert(is_array<_Tp>::value,
"std::shared_ptr<T>::operator[] is only valid when T is an array type.");
return __ptr_[__i];
}
#endif
#ifndef _LIBCPP_NO_RTTI
template <class _Dp>
_LIBCPP_HIDE_FROM_ABI
_Dp* __get_deleter() const _NOEXCEPT
{
return static_cast<_Dp*>(__cntrl_
? const_cast<void *>(__cntrl_->__get_deleter(typeid(_Dp)))
: nullptr);
}
#endif // _LIBCPP_NO_RTTI
template<class _Yp, class _CntrlBlk>
_LIBCPP_HIDE_FROM_ABI
static shared_ptr<_Tp> __create_with_control_block(_Yp* __p, _CntrlBlk* __cntrl) _NOEXCEPT
{
shared_ptr<_Tp> __r;
__r.__ptr_ = __p;
__r.__cntrl_ = __cntrl;
__r.__enable_weak_this(__r.__ptr_, __r.__ptr_);
return __r;
}
private:
template <class _Yp, bool = is_function<_Yp>::value>
struct __shared_ptr_default_allocator
{
typedef allocator<_Yp> type;
};
template <class _Yp>
struct __shared_ptr_default_allocator<_Yp, true>
{
typedef allocator<__shared_ptr_dummy_rebind_allocator_type> type;
};
template <class _Yp, class _OrigPtr, class = __enable_if_t<
is_convertible<_OrigPtr*, const enable_shared_from_this<_Yp>*>::value
> >
_LIBCPP_HIDE_FROM_ABI
void __enable_weak_this(const enable_shared_from_this<_Yp>* __e, _OrigPtr* __ptr) _NOEXCEPT
{
typedef typename remove_cv<_Yp>::type _RawYp;
if (__e && __e->__weak_this_.expired())
{
__e->__weak_this_ = shared_ptr<_RawYp>(*this,
const_cast<_RawYp*>(static_cast<const _Yp*>(__ptr)));
}
}
_LIBCPP_HIDE_FROM_ABI void __enable_weak_this(...) _NOEXCEPT { }
template <class, class _Yp>
struct __shared_ptr_default_delete
: default_delete<_Yp>
{ };
template <class _Yp, class _Un, size_t _Sz>
struct __shared_ptr_default_delete<_Yp[_Sz], _Un>
: default_delete<_Yp[]>
{ };
template <class _Yp, class _Un>
struct __shared_ptr_default_delete<_Yp[], _Un>
: default_delete<_Yp[]>
{ };
template <class _Up> friend class _LIBCPP_TEMPLATE_VIS shared_ptr;
template <class _Up> friend class _LIBCPP_TEMPLATE_VIS weak_ptr;
};
#if _LIBCPP_STD_VER > 14
template<class _Tp>
shared_ptr(weak_ptr<_Tp>) -> shared_ptr<_Tp>;
template<class _Tp, class _Dp>
shared_ptr(unique_ptr<_Tp, _Dp>) -> shared_ptr<_Tp>;
#endif
//
// std::allocate_shared and std::make_shared
@ -1573,17 +1424,6 @@ weak_ptr<_Tp>::reset() _NOEXCEPT
weak_ptr().swap(*this);
}
template<class _Tp>
template<class _Yp>
shared_ptr<_Tp>::shared_ptr(const weak_ptr<_Yp>& __r,
typename enable_if<__compatible_with<_Yp, _Tp>::value, __nat>::type)
: __ptr_(__r.__ptr_),
__cntrl_(__r.__cntrl_ ? __r.__cntrl_->lock() : __r.__cntrl_)
{
if (__cntrl_ == nullptr)
__throw_bad_weak_ptr();
}
template<class _Tp>
shared_ptr<_Tp>
weak_ptr<_Tp>::lock() const _NOEXCEPT