Index: include/memory =================================================================== --- include/memory +++ include/memory @@ -3657,8 +3657,14 @@ class __shared_ptr_emplace : public __shared_weak_count { +private: __compressed_pair<_Alloc, _Tp> __data_; + + virtual void __on_zero_shared() _NOEXCEPT; + virtual void __on_zero_shared_weak() _NOEXCEPT; + public: + #ifndef _LIBCPP_HAS_NO_VARIADICS _LIBCPP_INLINE_VISIBILITY @@ -3694,10 +3700,6 @@ #endif // _LIBCPP_HAS_NO_VARIADICS -private: - virtual void __on_zero_shared() _NOEXCEPT; - virtual void __on_zero_shared_weak() _NOEXCEPT; -public: _LIBCPP_INLINE_VISIBILITY _Tp* get() _NOEXCEPT {return _VSTD::addressof(__data_.second());} }; @@ -3738,18 +3740,18 @@ template class _LIBCPP_TEMPLATE_VIS shared_ptr { -public: - typedef _Tp element_type; - -#if _LIBCPP_STD_VER > 14 - typedef weak_ptr<_Tp> weak_type; -#endif private: - element_type* __ptr_; + _Tp* __ptr_; __shared_weak_count* __cntrl_; struct __nat {int __for_bool_;}; public: +#if _LIBCPP_STD_VER > 14 + typedef weak_ptr<_Tp> weak_type; +#endif + + typedef _Tp element_type; + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR shared_ptr() _NOEXCEPT; _LIBCPP_INLINE_VISIBILITY @@ -3793,45 +3795,34 @@ typename enable_if::value, __nat>::type = __nat()); #endif #endif + + template #ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES - template - shared_ptr(unique_ptr<_Yp, _Dp>&&, - typename enable_if - < - !is_lvalue_reference<_Dp>::value && - !is_array<_Yp>::value && - is_convertible::pointer, element_type*>::value, - __nat - >::type = __nat()); - template - shared_ptr(unique_ptr<_Yp, _Dp>&&, - typename enable_if - < - is_lvalue_reference<_Dp>::value && - !is_array<_Yp>::value && - is_convertible::pointer, element_type*>::value, - __nat - >::type = __nat()); -#else // _LIBCPP_HAS_NO_RVALUE_REFERENCES - template - shared_ptr(unique_ptr<_Yp, _Dp>, - typename enable_if - < - !is_lvalue_reference<_Dp>::value && - !is_array<_Yp>::value && - is_convertible::pointer, element_type*>::value, - __nat - >::type = __nat()); - template - shared_ptr(unique_ptr<_Yp, _Dp>, - typename enable_if - < - is_lvalue_reference<_Dp>::value && - !is_array<_Yp>::value && - is_convertible::pointer, element_type*>::value, - __nat - >::type = __nat()); -#endif // _LIBCPP_HAS_NO_RVALUE_REFERENCES + shared_ptr(unique_ptr<_Yp, _Dp&>&& __r, +#else + shared_ptr(unique_ptr<_Yp, _Dp&> __r, +#endif + typename enable_if + < + !is_array<_Yp>::value && + is_convertible::pointer, + element_type*>::value, + __nat + >::type = __nat()); + + template +#ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES + shared_ptr(unique_ptr<_Yp, _Dp>&& __r, +#else + shared_ptr(unique_ptr<_Yp, _Dp> __r, +#endif + typename enable_if + < + !is_array<_Yp>::value && + is_convertible::pointer, + element_type*>::value, + __nat + >::type = __nat()); ~shared_ptr(); @@ -4036,6 +4027,52 @@ template friend class _LIBCPP_TEMPLATE_VIS shared_ptr; template friend class _LIBCPP_TEMPLATE_VIS weak_ptr; + + template, + class _Alloc = typename __shared_ptr_default_allocator<_Yp>::type> + static __shared_weak_count* + __allocate_shared(_Yp* __p, _Deleter __d = _Deleter {}, _Alloc __a = _Alloc {}) + { + try { + typedef __shared_ptr_pointer<_Yp*, _Deleter, _Alloc> _CT; + typedef typename __allocator_traits_rebind<_Alloc, _CT>::type _A2; + typedef __allocator_destructor<_A2> _D2; + + _A2 __a2(__a); + unique_ptr<_CT, _D2> __hold2(__a2.allocate(1), _D2(__a2, 1)); + + ::new(static_cast(_VSTD::addressof(*__hold2.get()))) + _CT(__p, __d, __a); + + return _VSTD::addressof(*__hold2.release()); + } catch (...) { + __d(__p); + throw; + } + } + + template, + class _Alloc = typename __shared_ptr_default_allocator<_Tp>::type> + static __shared_weak_count* + __allocate_shared(nullptr_t __p, _Deleter __d = _Deleter {}, _Alloc __a = _Alloc {}) + { + try { + typedef __shared_ptr_pointer<_Tp*, _Deleter, _Alloc> _CT; + typedef typename __allocator_traits_rebind<_Alloc, _CT>::type _A2; + typedef __allocator_destructor<_A2> _D2; + + _A2 __a2(__a); + unique_ptr<_CT, _D2> __hold2(__a2.allocate(1), _D2(__a2, 1)); + + ::new(static_cast(_VSTD::addressof(*__hold2.get()))) + _CT(__p, __d, __a); + + return _VSTD::addressof(*__hold2.release()); + } catch (...) { + __d(__p); + throw; + } + } }; @@ -4044,30 +4081,22 @@ _LIBCPP_CONSTEXPR shared_ptr<_Tp>::shared_ptr() _NOEXCEPT : __ptr_(0), - __cntrl_(0) -{ -} + __cntrl_(0) {} template inline _LIBCPP_CONSTEXPR shared_ptr<_Tp>::shared_ptr(nullptr_t) _NOEXCEPT : __ptr_(0), - __cntrl_(0) -{ -} + __cntrl_(0) {} template template shared_ptr<_Tp>::shared_ptr(_Yp* __p, typename enable_if::value, __nat>::type) - : __ptr_(__p) + : __ptr_(__p), + __cntrl_(__allocate_shared(__p)) { - unique_ptr<_Yp> __hold(__p); - typedef typename __shared_ptr_default_allocator<_Yp>::type _AllocT; - typedef __shared_ptr_pointer<_Yp*, default_delete<_Yp>, _AllocT > _CntrlBlk; - __cntrl_ = new _CntrlBlk(__p, default_delete<_Yp>(), _AllocT()); - __hold.release(); __enable_weak_this(__p, __p); } @@ -4075,103 +4104,33 @@ template shared_ptr<_Tp>::shared_ptr(_Yp* __p, _Dp __d, typename enable_if::value, __nat>::type) - : __ptr_(__p) + : __ptr_(__p), + __cntrl_(__allocate_shared(__p, __d)) { -#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; - __cntrl_ = new _CntrlBlk(__p, __d, _AllocT()); - __enable_weak_this(__p, __p); -#ifndef _LIBCPP_NO_EXCEPTIONS - } - catch (...) - { - __d(__p); - throw; - } -#endif // _LIBCPP_NO_EXCEPTIONS + __enable_weak_this(__p, __p); } template template shared_ptr<_Tp>::shared_ptr(nullptr_t __p, _Dp __d) - : __ptr_(0) -{ -#ifndef _LIBCPP_NO_EXCEPTIONS - try - { -#endif // _LIBCPP_NO_EXCEPTIONS - typedef typename __shared_ptr_default_allocator<_Tp>::type _AllocT; - typedef __shared_ptr_pointer _CntrlBlk; - __cntrl_ = new _CntrlBlk(__p, __d, _AllocT()); -#ifndef _LIBCPP_NO_EXCEPTIONS - } - catch (...) - { - __d(__p); - throw; - } -#endif // _LIBCPP_NO_EXCEPTIONS -} + : __ptr_(0), + __cntrl_(__allocate_shared(__p, __d)) {} template template shared_ptr<_Tp>::shared_ptr(_Yp* __p, _Dp __d, _Alloc __a, typename enable_if::value, __nat>::type) - : __ptr_(__p) + : __ptr_(__p), + __cntrl_(__allocate_shared(__p, __d, __a)) { -#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(static_cast(_VSTD::addressof(*__hold2.get()))) - _CntrlBlk(__p, __d, __a); - __cntrl_ = _VSTD::addressof(*__hold2.release()); - __enable_weak_this(__p, __p); -#ifndef _LIBCPP_NO_EXCEPTIONS - } - catch (...) - { - __d(__p); - throw; - } -#endif // _LIBCPP_NO_EXCEPTIONS + __enable_weak_this(__p, __p); } template template shared_ptr<_Tp>::shared_ptr(nullptr_t __p, _Dp __d, _Alloc __a) - : __ptr_(0) -{ -#ifndef _LIBCPP_NO_EXCEPTIONS - try - { -#endif // _LIBCPP_NO_EXCEPTIONS - typedef __shared_ptr_pointer _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(static_cast(_VSTD::addressof(*__hold2.get()))) - _CntrlBlk(__p, __d, __a); - __cntrl_ = _VSTD::addressof(*__hold2.release()); -#ifndef _LIBCPP_NO_EXCEPTIONS - } - catch (...) - { - __d(__p); - throw; - } -#endif // _LIBCPP_NO_EXCEPTIONS -} + : __ptr_(0), + __cntrl_(__allocate_shared(__p, __d, __a)) {} template template @@ -4255,15 +4214,15 @@ template template #ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES -shared_ptr<_Tp>::shared_ptr(unique_ptr<_Yp, _Dp>&& __r, +shared_ptr<_Tp>::shared_ptr(unique_ptr<_Yp, _Dp&>&& __r, #else -shared_ptr<_Tp>::shared_ptr(unique_ptr<_Yp, _Dp> __r, +shared_ptr<_Tp>::shared_ptr(unique_ptr<_Yp, _Dp&> __r, #endif typename enable_if < - !is_lvalue_reference<_Dp>::value && !is_array<_Yp>::value && - is_convertible::pointer, element_type*>::value, + is_convertible::pointer, + element_type*>::value, __nat >::type) : __ptr_(__r.get()) @@ -4275,8 +4234,10 @@ #endif { typedef typename __shared_ptr_default_allocator<_Yp>::type _AllocT; - typedef __shared_ptr_pointer<_Yp*, _Dp, _AllocT > _CntrlBlk; - __cntrl_ = new _CntrlBlk(__r.get(), __r.get_deleter(), _AllocT()); + typedef __shared_ptr_pointer<_Yp*, + reference_wrapper::type>, + _AllocT > _CntrlBlk; + __cntrl_ = new _CntrlBlk(__r.get(), ref(__r.get_deleter()), _AllocT()); __enable_weak_this(__r.get(), __r.get()); } __r.release(); @@ -4291,9 +4252,9 @@ #endif typename enable_if < - is_lvalue_reference<_Dp>::value && !is_array<_Yp>::value && - is_convertible::pointer, element_type*>::value, + is_convertible::pointer, + element_type*>::value, __nat >::type) : __ptr_(__r.get()) @@ -4305,10 +4266,8 @@ #endif { typedef typename __shared_ptr_default_allocator<_Yp>::type _AllocT; - typedef __shared_ptr_pointer<_Yp*, - reference_wrapper::type>, - _AllocT > _CntrlBlk; - __cntrl_ = new _CntrlBlk(__r.get(), ref(__r.get_deleter()), _AllocT()); + typedef __shared_ptr_pointer<_Yp*, _Dp, _AllocT > _CntrlBlk; + __cntrl_ = new _CntrlBlk(__r.get(), __r.get_deleter(), _AllocT()); __enable_weak_this(__r.get(), __r.get()); } __r.release(); @@ -4325,9 +4284,11 @@ typedef __shared_ptr_emplace<_Tp, allocator<_Tp> > _CntrlBlk; typedef allocator<_CntrlBlk> _A2; typedef __allocator_destructor<_A2> _D2; + _A2 __a2; unique_ptr<_CntrlBlk, _D2> __hold2(__a2.allocate(1), _D2(__a2, 1)); ::new(__hold2.get()) _CntrlBlk(__a2, _VSTD::forward<_Args>(__args)...); + shared_ptr<_Tp> __r; __r.__ptr_ = __hold2.get()->get(); __r.__cntrl_ = __hold2.release(); @@ -4340,14 +4301,17 @@ shared_ptr<_Tp> shared_ptr<_Tp>::allocate_shared(const _Alloc& __a, _Args&& ...__args) { - static_assert( is_constructible<_Tp, _Args...>::value, "Can't construct object in allocate_shared" ); + static_assert(is_constructible<_Tp, _Args...>::value, "Can't construct object in allocate_shared"); + typedef __shared_ptr_emplace<_Tp, _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(static_cast(_VSTD::addressof(*__hold2.get()))) _CntrlBlk(__a, _VSTD::forward<_Args>(__args)...); + shared_ptr<_Tp> __r; __r.__ptr_ = __hold2.get()->get(); __r.__cntrl_ = _VSTD::addressof(*__hold2.release());