Index: include/memory =================================================================== --- include/memory +++ include/memory @@ -3737,15 +3737,25 @@ template class _LIBCPP_TEMPLATE_VIS enable_shared_from_this; +template +struct __compatible_with +#if _LIBCPP_STD_VER > 14 + : is_convertible*, remove_extent_t<_Up>*> {}; +#else + : is_convertible<_Tp*, _Up*> {}; +#endif // _LIBCPP_STD_VER > 14 + template class _LIBCPP_TEMPLATE_VIS shared_ptr { public: - typedef _Tp element_type; - #if _LIBCPP_STD_VER > 14 typedef weak_ptr<_Tp> weak_type; + typedef remove_extent_t<_Tp> element_type; +#else + typedef _Tp element_type; #endif + private: element_type* __ptr_; __shared_weak_count* __cntrl_; @@ -3758,13 +3768,13 @@ _LIBCPP_CONSTEXPR shared_ptr(nullptr_t) _NOEXCEPT; template explicit shared_ptr(_Yp* __p, - typename enable_if::value, __nat>::type = __nat()); + typename enable_if<__compatible_with<_Yp, element_type>::value, __nat>::type = __nat()); template shared_ptr(_Yp* __p, _Dp __d, - typename enable_if::value, __nat>::type = __nat()); + typename enable_if<__compatible_with<_Yp, element_type>::value, __nat>::type = __nat()); template shared_ptr(_Yp* __p, _Dp __d, _Alloc __a, - typename enable_if::value, __nat>::type = __nat()); + typename enable_if<__compatible_with<_Yp, element_type>::value, __nat>::type = __nat()); template shared_ptr(nullptr_t __p, _Dp __d); template shared_ptr(nullptr_t __p, _Dp __d, _Alloc __a); template _LIBCPP_INLINE_VISIBILITY shared_ptr(const shared_ptr<_Yp>& __r, element_type* __p) _NOEXCEPT; @@ -3773,13 +3783,13 @@ template _LIBCPP_INLINE_VISIBILITY shared_ptr(const shared_ptr<_Yp>& __r, - typename enable_if::value, __nat>::type = __nat()) + typename enable_if<__compatible_with<_Yp, element_type>::value, __nat>::type = __nat()) _NOEXCEPT; #ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES _LIBCPP_INLINE_VISIBILITY shared_ptr(shared_ptr&& __r) _NOEXCEPT; template _LIBCPP_INLINE_VISIBILITY shared_ptr(shared_ptr<_Yp>&& __r, - typename enable_if::value, __nat>::type = __nat()) + typename enable_if<__compatible_with<_Yp, element_type>::value, __nat>::type = __nat()) _NOEXCEPT; #endif // _LIBCPP_HAS_NO_RVALUE_REFERENCES template explicit shared_ptr(const weak_ptr<_Yp>& __r, @@ -3831,7 +3841,7 @@ template typename enable_if < - is_convertible<_Yp*, element_type*>::value, + __compatible_with<_Yp, element_type>::value, shared_ptr& >::type _LIBCPP_INLINE_VISIBILITY @@ -3842,8 +3852,8 @@ template typename enable_if < - is_convertible<_Yp*, element_type*>::value, - shared_ptr<_Tp>& + __compatible_with<_Yp, element_type>::value, + shared_ptr& >::type _LIBCPP_INLINE_VISIBILITY operator=(shared_ptr<_Yp>&& __r); @@ -3893,7 +3903,7 @@ template typename enable_if < - is_convertible<_Yp*, element_type*>::value, + __compatible_with<_Yp, element_type>::value, void >::type _LIBCPP_INLINE_VISIBILITY @@ -3901,7 +3911,7 @@ template typename enable_if < - is_convertible<_Yp*, element_type*>::value, + __compatible_with<_Yp, element_type>::value, void >::type _LIBCPP_INLINE_VISIBILITY @@ -3909,7 +3919,7 @@ template typename enable_if < - is_convertible<_Yp*, element_type*>::value, + __compatible_with<_Yp, element_type>::value, void >::type _LIBCPP_INLINE_VISIBILITY @@ -3941,6 +3951,13 @@ __owner_equivalent(const shared_ptr& __p) const {return __cntrl_ == __p.__cntrl_;} +#if _LIBCPP_STD_VER > 14 + typename add_lvalue_reference::type + _LIBCPP_INLINE_VISIBILITY + operator[](ptrdiff_t __i) const + {return __ptr_[__i];} +#endif + #ifndef _LIBCPP_NO_RTTI template _LIBCPP_INLINE_VISIBILITY @@ -3991,12 +4008,24 @@ } } + template + struct __shared_ptr_default_delete + : default_delete<_Yp> {}; + + template + struct __shared_ptr_default_delete<_Yp[_Sz], _Un> + : default_delete<_Yp[]> {}; + + template + struct __shared_ptr_default_delete<_Yp[], _Un> + : default_delete<_Yp[]> {}; + _LIBCPP_INLINE_VISIBILITY void __enable_weak_this(...) _NOEXCEPT {} template friend class _LIBCPP_TEMPLATE_VIS shared_ptr; template friend class _LIBCPP_TEMPLATE_VIS weak_ptr; - template, + template, class _Alloc = typename __shared_ptr_default_allocator<_Yp>::type> static __shared_weak_count* __allocate_shared(_Yp* __p, _Deleter __d = _Deleter(), _Alloc __a = _Alloc()) @@ -4019,7 +4048,7 @@ } } - template, + 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()) @@ -4061,7 +4090,7 @@ template template shared_ptr<_Tp>::shared_ptr(_Yp* __p, - typename enable_if::value, __nat>::type) + typename enable_if<__compatible_with<_Yp, element_type>::value, __nat>::type) : __ptr_(__p), __cntrl_(__allocate_shared(__p)) { @@ -4071,7 +4100,7 @@ template template shared_ptr<_Tp>::shared_ptr(_Yp* __p, _Dp __d, - typename enable_if::value, __nat>::type) + typename enable_if<__compatible_with<_Yp, element_type>::value, __nat>::type) : __ptr_(__p), __cntrl_(__allocate_shared(__p, __d)) { @@ -4087,7 +4116,7 @@ template template shared_ptr<_Tp>::shared_ptr(_Yp* __p, _Dp __d, _Alloc __a, - typename enable_if::value, __nat>::type) + typename enable_if<__compatible_with<_Yp, element_type>::value, __nat>::type) : __ptr_(__p), __cntrl_(__allocate_shared(__p, __d, __a)) { @@ -4125,7 +4154,7 @@ template inline shared_ptr<_Tp>::shared_ptr(const shared_ptr<_Yp>& __r, - typename enable_if::value, __nat>::type) + typename enable_if<__compatible_with<_Yp, element_type>::value, __nat>::type) _NOEXCEPT : __ptr_(__r.__ptr_), __cntrl_(__r.__cntrl_) @@ -4150,7 +4179,7 @@ template inline shared_ptr<_Tp>::shared_ptr(shared_ptr<_Yp>&& __r, - typename enable_if::value, __nat>::type) + typename enable_if<__compatible_with<_Yp, element_type>::value, __nat>::type) _NOEXCEPT : __ptr_(__r.__ptr_), __cntrl_(__r.__cntrl_) @@ -4262,7 +4291,7 @@ inline typename enable_if < - is_convertible<_Yp*, typename shared_ptr<_Tp>::element_type*>::value, + __compatible_with<_Yp, typename shared_ptr<_Tp>::element_type>::value, shared_ptr<_Tp>& >::type shared_ptr<_Tp>::operator=(const shared_ptr<_Yp>& __r) _NOEXCEPT @@ -4287,7 +4316,7 @@ inline typename enable_if < - is_convertible<_Yp*, typename shared_ptr<_Tp>::element_type*>::value, + __compatible_with<_Yp, typename shared_ptr<_Tp>::element_type>::value, shared_ptr<_Tp>& >::type shared_ptr<_Tp>::operator=(shared_ptr<_Yp>&& __r) @@ -4388,7 +4417,7 @@ inline typename enable_if < - is_convertible<_Yp*, typename shared_ptr<_Tp>::element_type*>::value, + __compatible_with<_Yp, typename shared_ptr<_Tp>::element_type>::value, void >::type shared_ptr<_Tp>::reset(_Yp* __p) @@ -4401,7 +4430,7 @@ inline typename enable_if < - is_convertible<_Yp*, typename shared_ptr<_Tp>::element_type*>::value, + __compatible_with<_Yp, typename shared_ptr<_Tp>::element_type>::value, void >::type shared_ptr<_Tp>::reset(_Yp* __p, _Dp __d) @@ -4414,7 +4443,7 @@ inline typename enable_if < - is_convertible<_Yp*, typename shared_ptr<_Tp>::element_type*>::value, + __compatible_with<_Yp, typename shared_ptr<_Tp>::element_type>::value, void >::type shared_ptr<_Tp>::reset(_Yp* __p, _Dp __d, _Alloc __a) @@ -4758,41 +4787,41 @@ template inline _LIBCPP_INLINE_VISIBILITY -typename enable_if -< - !is_array<_Tp>::value && !is_array<_Up>::value, - shared_ptr<_Tp> ->::type +shared_ptr<_Tp> static_pointer_cast(const shared_ptr<_Up>& __r) _NOEXCEPT { - return shared_ptr<_Tp>(__r, static_cast<_Tp*>(__r.get())); + return shared_ptr<_Tp>(__r, + static_cast< + typename shared_ptr<_Tp>::element_type*>(__r.get())); } template inline _LIBCPP_INLINE_VISIBILITY -typename enable_if -< - !is_array<_Tp>::value && !is_array<_Up>::value, - shared_ptr<_Tp> ->::type +shared_ptr<_Tp> dynamic_pointer_cast(const shared_ptr<_Up>& __r) _NOEXCEPT { - _Tp* __p = dynamic_cast<_Tp*>(__r.get()); + typedef typename shared_ptr<_Tp>::element_type _ET; + _ET* __p = dynamic_cast<_ET*>(__r.get()); return __p ? shared_ptr<_Tp>(__r, __p) : shared_ptr<_Tp>(); } template -typename enable_if -< - is_array<_Tp>::value == is_array<_Up>::value, - shared_ptr<_Tp> ->::type +shared_ptr<_Tp> const_pointer_cast(const shared_ptr<_Up>& __r) _NOEXCEPT { - typedef typename remove_extent<_Tp>::type _RTp; + typedef typename shared_ptr<_Tp>::element_type _RTp; return shared_ptr<_Tp>(__r, const_cast<_RTp*>(__r.get())); } +template +shared_ptr<_Tp> +reinterpret_pointer_cast(const shared_ptr<_Up>& __r) _NOEXCEPT +{ + return shared_ptr<_Tp>(__r, + reinterpret_cast< + typename shared_ptr<_Tp>::element_type*>(__r.get())); +} + #ifndef _LIBCPP_NO_RTTI template @@ -5191,7 +5220,7 @@ _LIBCPP_INLINE_VISIBILITY result_type operator()(const argument_type& __ptr) const _NOEXCEPT { - return hash<_Tp*>()(__ptr.get()); + return hash::element_type*>()(__ptr.get()); } }; Index: test/std/utilities/memory/util.smartptr/util.smartptr.shared/types.pass.cpp =================================================================== --- test/std/utilities/memory/util.smartptr/util.smartptr.shared/types.pass.cpp +++ test/std/utilities/memory/util.smartptr/util.smartptr.shared/types.pass.cpp @@ -48,6 +48,8 @@ static_assert(std::is_copy_constructible>::value, ""); static_assert(std::is_copy_assignable>::value, ""); static_assert(has_less>::value); + static_assert(std::is_same ::element_type, T>::value, ""); + static_assert(std::is_same::element_type, T>::value, ""); #endif } Index: test/std/utilities/memory/util.smartptr/util.smartptr.shared/util.smartptr.shared.cast/const_pointer_cast.pass.cpp =================================================================== --- test/std/utilities/memory/util.smartptr/util.smartptr.shared/util.smartptr.shared.cast/const_pointer_cast.pass.cpp +++ test/std/utilities/memory/util.smartptr/util.smartptr.shared/util.smartptr.shared.cast/const_pointer_cast.pass.cpp @@ -55,6 +55,14 @@ assert(pB.get() == pA.get()); assert(!pB.owner_before(pA) && !pA.owner_before(pB)); } +#if TEST_STD_VER > 14 + { + const std::shared_ptr pA; + std::shared_ptr pB = std::const_pointer_cast(pA); + assert(pB.get() == pA.get()); + assert(!pB.owner_before(pA) && !pA.owner_before(pB)); + } +#endif // TEST_STD_VER > 14 - return 0; + return 0; } Index: test/std/utilities/memory/util.smartptr/util.smartptr.shared/util.smartptr.shared.cast/dynamic_pointer_cast.pass.cpp =================================================================== --- test/std/utilities/memory/util.smartptr/util.smartptr.shared/util.smartptr.shared.cast/dynamic_pointer_cast.pass.cpp +++ test/std/utilities/memory/util.smartptr/util.smartptr.shared/util.smartptr.shared.cast/dynamic_pointer_cast.pass.cpp @@ -55,6 +55,14 @@ assert(pA.get() == 0); assert(pA.use_count() == 0); } +#if TEST_STD_VER > 14 + { + const std::shared_ptr pB(new B[8]); + std::shared_ptr pA = std::dynamic_pointer_cast(pB); + assert(pA.get() == 0); + assert(pA.use_count() == 0); + } +#endif // TEST_STD_VER > 14 return 0; } Index: test/std/utilities/memory/util.smartptr/util.smartptr.shared/util.smartptr.shared.cast/reinterpret_pointer_cast.pass.cpp =================================================================== --- /dev/null +++ test/std/utilities/memory/util.smartptr/util.smartptr.shared/util.smartptr.shared.cast/reinterpret_pointer_cast.pass.cpp @@ -0,0 +1,51 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +// + +// shared_ptr + +// template +// shared_ptr reinterpret_pointer_cast(const shared_ptr& r) noexcept; + +#include "test_macros.h" + +#include +#include +#include + +struct A { int x; }; + +int main(int, char**) +{ + { + const std::shared_ptr pA(new A); + std::shared_ptr pi = std::reinterpret_pointer_cast(pA); + std::shared_ptr pA2 = std::reinterpret_pointer_cast(pi); + assert(pA2.get() == pA.get()); + assert(!pi.owner_before(pA) && !pA.owner_before(pi)); + } + { + const std::shared_ptr pA; + std::shared_ptr pi = std::reinterpret_pointer_cast(pA); + std::shared_ptr pA2 = std::reinterpret_pointer_cast(pi); + assert(pA2.get() == pA.get()); + assert(!pi.owner_before(pA) && !pA.owner_before(pi)); + } +#if TEST_STD_VER > 14 + { + const std::shared_ptr pA; + std::shared_ptr pi = std::reinterpret_pointer_cast(pA); + std::shared_ptr pA2 = std::reinterpret_pointer_cast(pi); + assert(pA2.get() == pA.get()); + assert(!pi.owner_before(pA) && !pA.owner_before(pi)); + } +#endif // TEST_STD_VER > 14 + + return 0; +} Index: test/std/utilities/memory/util.smartptr/util.smartptr.shared/util.smartptr.shared.cast/static_pointer_cast.pass.cpp =================================================================== --- test/std/utilities/memory/util.smartptr/util.smartptr.shared/util.smartptr.shared.cast/static_pointer_cast.pass.cpp +++ test/std/utilities/memory/util.smartptr/util.smartptr.shared/util.smartptr.shared.cast/static_pointer_cast.pass.cpp @@ -67,6 +67,20 @@ assert(pB.get() == pA.get()); assert(!pB.owner_before(pA) && !pA.owner_before(pB)); } +#if TEST_STD_VER > 14 + { + const std::shared_ptr pA; + std::shared_ptr pB = std::static_pointer_cast(pA); + assert(pB.get() == pA.get()); + assert(!pB.owner_before(pA) && !pA.owner_before(pB)); + } + { + const std::shared_ptr pA; + std::shared_ptr pB = std::static_pointer_cast(pA); + assert(pB.get() == pA.get()); + assert(!pB.owner_before(pA) && !pA.owner_before(pB)); + } +#endif // TEST_STD_VER > 14 return 0; } Index: test/std/utilities/memory/util.smartptr/util.smartptr.shared/util.smartptr.shared.const/default.pass.cpp =================================================================== --- test/std/utilities/memory/util.smartptr/util.smartptr.shared/util.smartptr.shared.const/default.pass.cpp +++ test/std/utilities/memory/util.smartptr/util.smartptr.shared/util.smartptr.shared.const/default.pass.cpp @@ -30,6 +30,8 @@ test(); test(); test(); + test(); + test(); return 0; } Index: test/std/utilities/memory/util.smartptr/util.smartptr.shared/util.smartptr.shared.const/pointer.pass.cpp =================================================================== --- test/std/utilities/memory/util.smartptr/util.smartptr.shared/util.smartptr.shared.const/pointer.pass.cpp +++ test/std/utilities/memory/util.smartptr/util.smartptr.shared/util.smartptr.shared.const/pointer.pass.cpp @@ -45,5 +45,21 @@ } assert(A::count == 0); +#if TEST_STD_VER > 14 + { + std::shared_ptr pA(new A[8]); + assert(pA.use_count() == 1); + assert(A::count == 8); + } + assert(A::count == 0); + + { + std::shared_ptr pA(new A[8]); + assert(pA.use_count() == 1); + assert(A::count == 8); + } + assert(A::count == 0); +#endif + return 0; } Index: test/std/utilities/memory/util.smartptr/util.smartptr.shared/util.smartptr.shared.obs/op_bracket.pass.cpp =================================================================== --- /dev/null +++ test/std/utilities/memory/util.smartptr/util.smartptr.shared/util.smartptr.shared.obs/op_bracket.pass.cpp @@ -0,0 +1,52 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +// + +// UNSUPPORTED: c++98, c++03, c++11, c++14 + +// shared_ptr + +// element_type& operator[](ptrdiff_t i) const; + +#include "test_macros.h" + +#include +#include + +int main(int, char**) +{ + { + const std::shared_ptr p(new int[8]); + + for (int i = 0; i < 8; ++i) + p[i] = i; + for (int i = 0; i < 8; ++i) + assert(p[i] == i); + } + { + int *iptr = new int[8]; + for (int i = 0; i < 8; ++i) + iptr[i] = i; + + const std::shared_ptr p(iptr); + + for (int i = 0; i < 8; ++i) + assert(p[i] == i); + } + { + const std::shared_ptr p(new int[8]); + + for (int i = 0; i < 8; ++i) + p[i] = i; + for (int i = 0; i < 8; ++i) + assert(p[i] == i); + } + + return 0; +} Index: www/cxx1z_status.html =================================================================== --- www/cxx1z_status.html +++ www/cxx1z_status.html @@ -128,7 +128,7 @@ P0003R5LWGRemoving Deprecated Exception Specifications from C++17IssaquahComplete5.0 P0067R5LWGElementary string conversions, revision 5IssaquahPartially done P0403R1LWGLiteral suffixes for basic_string_viewIssaquahComplete4.0 - P0414R2LWGMerging shared_ptr changes from Library Fundamentals to C++17Issaquah + P0414R2LWGMerging shared_ptr changes from Library Fundamentals to C++17IssaquahComplete P0418R2LWGFail or succeed: there is no atomic latticeIssaquah P0426R1LWGConstexpr for std::char_traitsIssaquahComplete4.0 P0435R1LWGResolving LWG Issues re common_typeIssaquahComplete4.0