[libcxx-commits] [libcxx] b2d25ef - [libc++] Implement shared_ptr methods inline in the class

Louis Dionne via libcxx-commits libcxx-commits at lists.llvm.org
Tue Oct 26 10:11:16 PDT 2021


Author: Louis Dionne
Date: 2021-10-26T13:11:10-04:00
New Revision: b2d25ef2d1e50bf012fdb18ef721917292d67bcf

URL: https://github.com/llvm/llvm-project/commit/b2d25ef2d1e50bf012fdb18ef721917292d67bcf
DIFF: https://github.com/llvm/llvm-project/commit/b2d25ef2d1e50bf012fdb18ef721917292d67bcf.diff

LOG: [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

Added: 
    

Modified: 
    libcxx/include/__memory/shared_ptr.h

Removed: 
    


################################################################################
diff  --git a/libcxx/include/__memory/shared_ptr.h b/libcxx/include/__memory/shared_ptr.h
index 0f366794a62d1..7b08641762d84 100644
--- a/libcxx/include/__memory/shared_ptr.h
+++ b/libcxx/include/__memory/shared_ptr.h
@@ -430,12 +430,18 @@ class _LIBCPP_SHARED_PTR_TRIVIAL_ABI _LIBCPP_TEMPLATE_VIS shared_ptr
     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,638 +463,483 @@ class _LIBCPP_SHARED_PTR_TRIVIAL_ABI _LIBCPP_TEMPLATE_VIS shared_ptr
         __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();
+    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
+        {
+#endif // _LIBCPP_NO_EXCEPTIONS
+            typedef typename __shared_ptr_default_allocator<_Yp>::type _AllocT;
+            typedef __shared_ptr_pointer<_Yp*, _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
+            __enable_weak_this(__p, __p);
+#ifndef _LIBCPP_NO_EXCEPTIONS
+        }
+        catch (...)
+        {
+            __d(__p);
+            throw;
+        }
+#endif // _LIBCPP_NO_EXCEPTIONS
+    }
 
-    _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);
+    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
+        {
+#endif // _LIBCPP_NO_EXCEPTIONS
+            typedef __shared_ptr_pointer<_Yp*, _Dp, _Alloc> _CntrlBlk;
+            typedef typename __allocator_traits_rebind<_Alloc, _CntrlBlk>::type _A2;
+            typedef __allocator_destructor<_A2> _D2;
+            _A2 __a2(__a);
+            unique_ptr<_CntrlBlk, _D2> __hold2(__a2.allocate(1), _D2(__a2, 1));
+            ::new ((void*)_VSTD::addressof(*__hold2.get()))
+#ifndef _LIBCPP_CXX03_LANG
+                _CntrlBlk(__p, _VSTD::move(__d), __a);
+#else
+                _CntrlBlk(__p, __d, __a);
+#endif // not _LIBCPP_CXX03_LANG
+            __cntrl_ = _VSTD::addressof(*__hold2.release());
+            __enable_weak_this(__p, __p);
+#ifndef _LIBCPP_NO_EXCEPTIONS
+        }
+        catch (...)
+        {
+            __d(__p);
+            throw;
+        }
+#endif // _LIBCPP_NO_EXCEPTIONS
+    }
+
+    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
+        {
+#endif // _LIBCPP_NO_EXCEPTIONS
+            typedef __shared_ptr_pointer<nullptr_t, _Dp, _Alloc> _CntrlBlk;
+            typedef typename __allocator_traits_rebind<_Alloc, _CntrlBlk>::type _A2;
+            typedef __allocator_destructor<_A2> _D2;
+            _A2 __a2(__a);
+            unique_ptr<_CntrlBlk, _D2> __hold2(__a2.allocate(1), _D2(__a2, 1));
+            ::new ((void*)_VSTD::addressof(*__hold2.get()))
+#ifndef _LIBCPP_CXX03_LANG
+                _CntrlBlk(__p, _VSTD::move(__d), __a);
+#else
+                _CntrlBlk(__p, __d, __a);
+#endif // not _LIBCPP_CXX03_LANG
+            __cntrl_ = _VSTD::addressof(*__hold2.release());
+#ifndef _LIBCPP_NO_EXCEPTIONS
+        }
+        catch (...)
+        {
+            __d(__p);
+            throw;
+        }
+#endif // _LIBCPP_NO_EXCEPTIONS
+    }
 
-    _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_HIDE_FROM_ABI
+    shared_ptr(const shared_ptr<_Yp>& __r, element_type *__p) _NOEXCEPT
+        : __ptr_(__p),
+          __cntrl_(__r.__cntrl_)
+    {
+        if (__cntrl_)
+            __cntrl_->__add_shared();
+    }
 
-    _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
+    _LIBCPP_HIDE_FROM_ABI
+    shared_ptr(const shared_ptr& __r) _NOEXCEPT
+        : __ptr_(__r.__ptr_),
+          __cntrl_(__r.__cntrl_)
     {
-        static_assert(!is_array<_Tp>::value,
-                      "std::shared_ptr<T>::operator-> is only valid when T is not an array type.");
-        return __ptr_;
+        if (__cntrl_)
+            __cntrl_->__add_shared();
     }
-    _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[](ptr
diff _t __i) const
+    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_)
     {
-            static_assert(is_array<_Tp>::value,
-                          "std::shared_ptr<T>::operator[] is only valid when T is an array type.");
-            return __ptr_[__i];
+        if (__cntrl_)
+            __cntrl_->__add_shared();
     }
-#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
+    _LIBCPP_HIDE_FROM_ABI
+    shared_ptr(shared_ptr&& __r) _NOEXCEPT
+        : __ptr_(__r.__ptr_),
+          __cntrl_(__r.__cntrl_)
+    {
+        __r.__ptr_ = nullptr;
+        __r.__cntrl_ = nullptr;
+    }
 
-    template<class _Yp, class _CntrlBlk>
-    static shared_ptr<_Tp>
-    __create_with_control_block(_Yp* __p, _CntrlBlk* __cntrl) _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_)
     {
-        shared_ptr<_Tp> __r;
-        __r.__ptr_ = __p;
-        __r.__cntrl_ = __cntrl;
-        __r.__enable_weak_this(__r.__ptr_, __r.__ptr_);
-        return __r;
+        __r.__ptr_ = nullptr;
+        __r.__cntrl_ = nullptr;
     }
 
-private:
-    template <class _Yp, bool = is_function<_Yp>::value>
-        struct __shared_ptr_default_allocator
-        {
-            typedef allocator<_Yp> type;
-        };
+    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();
+    }
 
-    template <class _Yp>
-        struct __shared_ptr_default_allocator<_Yp, true>
+#if _LIBCPP_STD_VER <= 14 || defined(_LIBCPP_ENABLE_CXX17_REMOVED_AUTO_PTR)
+    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 _Yp, class _Dp, class = __enable_if_t<
+        !is_lvalue_reference<_Dp>::value &&
+         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;
+        else
+#endif
         {
-            typedef allocator<__shared_ptr_dummy_rebind_allocator_type> type;
-        };
+            typedef typename __shared_ptr_default_allocator<_Yp>::type _AllocT;
+            typedef __shared_ptr_pointer<typename unique_ptr<_Yp, _Dp>::pointer, _Dp, _AllocT > _CntrlBlk;
+            __cntrl_ = new _CntrlBlk(__r.get(), __r.get_deleter(), _AllocT());
+            __enable_weak_this(__r.get(), __r.get());
+        }
+        __r.release();
+    }
 
-    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
+    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
+    > >
+    _LIBCPP_HIDE_FROM_ABI
+    shared_ptr(unique_ptr<_Yp, _Dp>&& __r)
+        : __ptr_(__r.get())
+    {
+#if _LIBCPP_STD_VER > 11
+        if (__ptr_ == nullptr)
+            __cntrl_ = nullptr;
+        else
+#endif
         {
-            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)));
-            }
+            typedef typename __shared_ptr_default_allocator<_Yp>::type _AllocT;
+            typedef __shared_ptr_pointer<typename unique_ptr<_Yp, _Dp>::pointer,
+                                        reference_wrapper<typename remove_reference<_Dp>::type>,
+                                        _AllocT > _CntrlBlk;
+            __cntrl_ = new _CntrlBlk(__r.get(), _VSTD::ref(__r.get_deleter()), _AllocT());
+            __enable_weak_this(__r.get(), __r.get());
         }
+        __r.release();
+    }
 
-    _LIBCPP_INLINE_VISIBILITY void __enable_weak_this(...) _NOEXCEPT {}
+    _LIBCPP_HIDE_FROM_ABI
+    ~shared_ptr()
+    {
+        if (__cntrl_)
+            __cntrl_->__release_shared();
+    }
 
-    template <class, class _Yp>
-        struct __shared_ptr_default_delete
-            : default_delete<_Yp> {};
+    _LIBCPP_HIDE_FROM_ABI
+    shared_ptr<_Tp>& operator=(const shared_ptr& __r) _NOEXCEPT
+    {
+        shared_ptr(__r).swap(*this);
+        return *this;
+    }
 
-    template <class _Yp, class _Un, size_t _Sz>
-        struct __shared_ptr_default_delete<_Yp[_Sz], _Un>
-            : default_delete<_Yp[]> {};
+    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 _Yp, class _Un>
-        struct __shared_ptr_default_delete<_Yp[], _Un>
-            : default_delete<_Yp[]> {};
+    _LIBCPP_HIDE_FROM_ABI
+    shared_ptr<_Tp>& operator=(shared_ptr&& __r) _NOEXCEPT
+    {
+        shared_ptr(_VSTD::move(__r)).swap(*this);
+        return *this;
+    }
 
-    template <class _Up> friend class _LIBCPP_TEMPLATE_VIS shared_ptr;
-    template <class _Up> friend class _LIBCPP_TEMPLATE_VIS weak_ptr;
-};
+    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
-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>;
+#if _LIBCPP_STD_VER <= 14 || defined(_LIBCPP_ENABLE_CXX17_REMOVED_AUTO_PTR)
+    template<class _Yp, class = __enable_if_t<
+        !is_array<_Yp>::value &&
+        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>
-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 _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>
-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)
-    : __ptr_(__p)
-{
-#ifndef _LIBCPP_NO_EXCEPTIONS
-    try
+    _LIBCPP_HIDE_FROM_ABI
+    void swap(shared_ptr& __r) _NOEXCEPT
     {
-#endif // _LIBCPP_NO_EXCEPTIONS
-        typedef typename __shared_ptr_default_allocator<_Yp>::type _AllocT;
-        typedef __shared_ptr_pointer<_Yp*, _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
-        __enable_weak_this(__p, __p);
-#ifndef _LIBCPP_NO_EXCEPTIONS
+        _VSTD::swap(__ptr_, __r.__ptr_);
+        _VSTD::swap(__cntrl_, __r.__cntrl_);
     }
-    catch (...)
+
+    _LIBCPP_HIDE_FROM_ABI
+    void reset() _NOEXCEPT
     {
-        __d(__p);
-        throw;
+        shared_ptr().swap(*this);
     }
-#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
+    template<class _Yp, class = __enable_if_t<
+        __compatible_with<_Yp, _Tp>::value
+    > >
+    _LIBCPP_HIDE_FROM_ABI
+    void reset(_Yp* __p)
     {
-#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
+        shared_ptr(__p).swap(*this);
+    }
+
+    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);
     }
-    catch (...)
+
+    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)
     {
-        __d(__p);
-        throw;
+        shared_ptr(__p, __d, __a).swap(*this);
     }
-#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)
-    : __ptr_(__p)
-{
-#ifndef _LIBCPP_NO_EXCEPTIONS
-    try
+    _LIBCPP_HIDE_FROM_ABI
+    element_type* get() const _NOEXCEPT
     {
-#endif // _LIBCPP_NO_EXCEPTIONS
-        typedef __shared_ptr_pointer<_Yp*, _Dp, _Alloc> _CntrlBlk;
-        typedef typename __allocator_traits_rebind<_Alloc, _CntrlBlk>::type _A2;
-        typedef __allocator_destructor<_A2> _D2;
-        _A2 __a2(__a);
-        unique_ptr<_CntrlBlk, _D2> __hold2(__a2.allocate(1), _D2(__a2, 1));
-        ::new ((void*)_VSTD::addressof(*__hold2.get()))
-#ifndef _LIBCPP_CXX03_LANG
-            _CntrlBlk(__p, _VSTD::move(__d), __a);
-#else
-            _CntrlBlk(__p, __d, __a);
-#endif // not _LIBCPP_CXX03_LANG
-        __cntrl_ = _VSTD::addressof(*__hold2.release());
-        __enable_weak_this(__p, __p);
-#ifndef _LIBCPP_NO_EXCEPTIONS
+        return __ptr_;
     }
-    catch (...)
+
+    _LIBCPP_HIDE_FROM_ABI
+    typename add_lvalue_reference<element_type>::type operator*() const _NOEXCEPT
     {
-        __d(__p);
-        throw;
+        return *__ptr_;
     }
-#endif // _LIBCPP_NO_EXCEPTIONS
-}
 
-template<class _Tp>
-template<class _Dp, class _Alloc>
-shared_ptr<_Tp>::shared_ptr(nullptr_t __p, _Dp __d, _Alloc __a)
-    : __ptr_(nullptr)
-{
-#ifndef _LIBCPP_NO_EXCEPTIONS
-    try
+    _LIBCPP_HIDE_FROM_ABI
+    element_type* operator->() const _NOEXCEPT
     {
-#endif // _LIBCPP_NO_EXCEPTIONS
-        typedef __shared_ptr_pointer<nullptr_t, _Dp, _Alloc> _CntrlBlk;
-        typedef typename __allocator_traits_rebind<_Alloc, _CntrlBlk>::type _A2;
-        typedef __allocator_destructor<_A2> _D2;
-        _A2 __a2(__a);
-        unique_ptr<_CntrlBlk, _D2> __hold2(__a2.allocate(1), _D2(__a2, 1));
-        ::new ((void*)_VSTD::addressof(*__hold2.get()))
-#ifndef _LIBCPP_CXX03_LANG
-            _CntrlBlk(__p, _VSTD::move(__d), __a);
-#else
-            _CntrlBlk(__p, __d, __a);
-#endif // not _LIBCPP_CXX03_LANG
-        __cntrl_ = _VSTD::addressof(*__hold2.release());
-#ifndef _LIBCPP_NO_EXCEPTIONS
+        static_assert(!is_array<_Tp>::value,
+                      "std::shared_ptr<T>::operator-> is only valid when T is not an array type.");
+        return __ptr_;
     }
-    catch (...)
+
+    _LIBCPP_HIDE_FROM_ABI
+    long use_count() const _NOEXCEPT
     {
-        __d(__p);
-        throw;
+        return __cntrl_ ? __cntrl_->use_count() : 0;
     }
-#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
-    : __ptr_(__p),
-      __cntrl_(__r.__cntrl_)
-{
-    if (__cntrl_)
-        __cntrl_->__add_shared();
-}
+    _LIBCPP_HIDE_FROM_ABI
+    bool unique() const _NOEXCEPT
+    {
+        return use_count() == 1;
+    }
 
-template<class _Tp>
-inline
-shared_ptr<_Tp>::shared_ptr(const shared_ptr& __r) _NOEXCEPT
-    : __ptr_(__r.__ptr_),
-      __cntrl_(__r.__cntrl_)
-{
-    if (__cntrl_)
-        __cntrl_->__add_shared();
-}
+    _LIBCPP_HIDE_FROM_ABI
+    explicit operator bool() const _NOEXCEPT
+    {
+        return get() != nullptr;
+    }
 
-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
-    : __ptr_(__r.__ptr_),
-      __cntrl_(__r.__cntrl_)
-{
-    if (__cntrl_)
-        __cntrl_->__add_shared();
-}
+    template <class _Up>
+    _LIBCPP_HIDE_FROM_ABI
+    bool owner_before(shared_ptr<_Up> const& __p) const _NOEXCEPT
+    {
+        return __cntrl_ < __p.__cntrl_;
+    }
 
-template<class _Tp>
-inline
-shared_ptr<_Tp>::shared_ptr(shared_ptr&& __r) _NOEXCEPT
-    : __ptr_(__r.__ptr_),
-      __cntrl_(__r.__cntrl_)
-{
-    __r.__ptr_ = nullptr;
-    __r.__cntrl_ = nullptr;
-}
+    template <class _Up>
+    _LIBCPP_HIDE_FROM_ABI
+    bool owner_before(weak_ptr<_Up> const& __p) const _NOEXCEPT
+    {
+        return __cntrl_ < __p.__cntrl_;
+    }
 
-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
-    : __ptr_(__r.__ptr_),
-      __cntrl_(__r.__cntrl_)
-{
-    __r.__ptr_ = nullptr;
-    __r.__cntrl_ = nullptr;
-}
+    _LIBCPP_HIDE_FROM_ABI
+    bool __owner_equivalent(const shared_ptr& __p) const
+    {
+        return __cntrl_ == __p.__cntrl_;
+    }
 
-#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)
-    : __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();
-}
+#if _LIBCPP_STD_VER > 14
+    _LIBCPP_HIDE_FROM_ABI
+    typename add_lvalue_reference<element_type>::type operator[](ptr
diff _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
 
-template<class _Tp>
-template <class _Yp, class _Dp>
-shared_ptr<_Tp>::shared_ptr(unique_ptr<_Yp, _Dp>&& __r,
-                            typename enable_if
-                            <
-                                !is_lvalue_reference<_Dp>::value &&
-                                is_convertible<typename unique_ptr<_Yp, _Dp>::pointer, element_type*>::value,
-                                __nat
-                            >::type)
-    : __ptr_(__r.get())
-{
-#if _LIBCPP_STD_VER > 11
-    if (__ptr_ == nullptr)
-        __cntrl_ = nullptr;
-    else
-#endif
+#ifndef _LIBCPP_NO_RTTI
+    template <class _Dp>
+    _LIBCPP_HIDE_FROM_ABI
+    _Dp* __get_deleter() const _NOEXCEPT
     {
-        typedef typename __shared_ptr_default_allocator<_Yp>::type _AllocT;
-        typedef __shared_ptr_pointer<typename unique_ptr<_Yp, _Dp>::pointer, _Dp, _AllocT > _CntrlBlk;
-        __cntrl_ = new _CntrlBlk(__r.get(), __r.get_deleter(), _AllocT());
-        __enable_weak_this(__r.get(), __r.get());
+        return static_cast<_Dp*>(__cntrl_
+                    ? const_cast<void *>(__cntrl_->__get_deleter(typeid(_Dp)))
+                      : nullptr);
     }
-    __r.release();
-}
+#endif // _LIBCPP_NO_RTTI
 
-template<class _Tp>
-template <class _Yp, class _Dp>
-shared_ptr<_Tp>::shared_ptr(unique_ptr<_Yp, _Dp>&& __r,
-                            typename enable_if
-                            <
-                                is_lvalue_reference<_Dp>::value &&
-                                is_convertible<typename unique_ptr<_Yp, _Dp>::pointer, element_type*>::value,
-                                __nat
-                            >::type)
-    : __ptr_(__r.get())
-{
-#if _LIBCPP_STD_VER > 11
-    if (__ptr_ == nullptr)
-        __cntrl_ = nullptr;
-    else
-#endif
+    template<class _Yp, class _CntrlBlk>
+    _LIBCPP_HIDE_FROM_ABI
+    static shared_ptr<_Tp> __create_with_control_block(_Yp* __p, _CntrlBlk* __cntrl) _NOEXCEPT
     {
-        typedef typename __shared_ptr_default_allocator<_Yp>::type _AllocT;
-        typedef __shared_ptr_pointer<typename unique_ptr<_Yp, _Dp>::pointer,
-                                     reference_wrapper<typename remove_reference<_Dp>::type>,
-                                     _AllocT > _CntrlBlk;
-        __cntrl_ = new _CntrlBlk(__r.get(), _VSTD::ref(__r.get_deleter()), _AllocT());
-        __enable_weak_this(__r.get(), __r.get());
+        shared_ptr<_Tp> __r;
+        __r.__ptr_ = __p;
+        __r.__cntrl_ = __cntrl;
+        __r.__enable_weak_this(__r.__ptr_, __r.__ptr_);
+        return __r;
     }
-    __r.release();
-}
-
-template<class _Tp>
-shared_ptr<_Tp>::~shared_ptr()
-{
-    if (__cntrl_)
-        __cntrl_->__release_shared();
-}
-
-template<class _Tp>
-inline
-shared_ptr<_Tp>&
-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
-{
-    shared_ptr(__r).swap(*this);
-    return *this;
-}
 
-template<class _Tp>
-inline
-shared_ptr<_Tp>&
-shared_ptr<_Tp>::operator=(shared_ptr&& __r) _NOEXCEPT
-{
-    shared_ptr(_VSTD::move(__r)).swap(*this);
-    return *this;
-}
+private:
+    template <class _Yp, bool = is_function<_Yp>::value>
+    struct __shared_ptr_default_allocator
+    {
+        typedef allocator<_Yp> type;
+    };
 
-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)
-{
-    shared_ptr(_VSTD::move(__r)).swap(*this);
-    return *this;
-}
+    template <class _Yp>
+    struct __shared_ptr_default_allocator<_Yp, true>
+    {
+        typedef allocator<__shared_ptr_dummy_rebind_allocator_type> type;
+    };
 
-#if _LIBCPP_STD_VER <= 14 || defined(_LIBCPP_ENABLE_CXX17_REMOVED_AUTO_PTR)
-template<class _Tp>
-template<class _Yp>
-inline
-typename enable_if
-<
-    !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)
-{
-    shared_ptr(_VSTD::move(__r)).swap(*this);
-    return *this;
-}
-#endif
+    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)));
+        }
+    }
 
-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)
-{
-    shared_ptr(_VSTD::move(__r)).swap(*this);
-    return *this;
-}
+    _LIBCPP_HIDE_FROM_ABI void __enable_weak_this(...) _NOEXCEPT { }
 
-template<class _Tp>
-inline
-void
-shared_ptr<_Tp>::swap(shared_ptr& __r) _NOEXCEPT
-{
-    _VSTD::swap(__ptr_, __r.__ptr_);
-    _VSTD::swap(__cntrl_, __r.__cntrl_);
-}
+    template <class, class _Yp>
+    struct __shared_ptr_default_delete
+        : default_delete<_Yp>
+    { };
 
-template<class _Tp>
-inline
-void
-shared_ptr<_Tp>::reset() _NOEXCEPT
-{
-    shared_ptr().swap(*this);
-}
+    template <class _Yp, class _Un, size_t _Sz>
+    struct __shared_ptr_default_delete<_Yp[_Sz], _Un>
+        : default_delete<_Yp[]>
+    { };
 
-template<class _Tp>
-template<class _Yp>
-inline
-typename enable_if
-<
-    __compatible_with<_Yp, _Tp>::value,
-    void
->::type
-shared_ptr<_Tp>::reset(_Yp* __p)
-{
-    shared_ptr(__p).swap(*this);
-}
+    template <class _Yp, class _Un>
+    struct __shared_ptr_default_delete<_Yp[], _Un>
+        : default_delete<_Yp[]>
+    { };
 
-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)
-{
-    shared_ptr(__p, __d).swap(*this);
-}
+    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>
-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)
-{
-    shared_ptr(__p, __d, __a).swap(*this);
-}
+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


        


More information about the libcxx-commits mailing list