diff --git a/libcxx/docs/Status/Cxx20Issues.csv b/libcxx/docs/Status/Cxx20Issues.csv --- a/libcxx/docs/Status/Cxx20Issues.csv +++ b/libcxx/docs/Status/Cxx20Issues.csv @@ -37,7 +37,7 @@ "`2988 `__","Clause 32 cleanup missed one typename","Albuquerque","|Complete|","13.0" "`2993 `__","reference_wrapper conversion from T&&","Albuquerque","|Complete|","13.0" "`2998 `__","Requirements on function objects passed to {``forward_``,}list-specific algorithms","Albuquerque","|Nothing To Do|","" -"`3001 `__","weak_ptr::element_type needs remove_extent_t","Albuquerque","","" +"`3001 `__","weak_ptr::element_type needs remove_extent_t","Albuquerque","|Complete|","14.0" "`3024 `__","variant's copies must be deleted instead of disabled via SFINAE","Albuquerque","|Complete|","" "","","","","" "`2164 `__","What are the semantics of ``vector.emplace(vector.begin(), vector.back())``\ ?","Jacksonville","|Complete|","" diff --git a/libcxx/include/__memory/shared_ptr.h b/libcxx/include/__memory/shared_ptr.h --- a/libcxx/include/__memory/shared_ptr.h +++ b/libcxx/include/__memory/shared_ptr.h @@ -374,13 +374,41 @@ template class _LIBCPP_TEMPLATE_VIS enable_shared_from_this; template -struct __compatible_with +struct __shared_ptr_compatible_with #if _LIBCPP_STD_VER > 14 : is_convertible*, remove_extent_t<_Up>*> {}; #else : is_convertible<_Tp*, _Up*> {}; #endif // _LIBCPP_STD_VER > 14 +template +struct __weak_ptr_compatible_with +#if _LIBCPP_STD_VER > 17 + : is_convertible*, remove_extent_t<_Up>*> {}; +#else + : is_convertible<_Tp*, _Up*> {}; +#endif // _LIBCPP_STD_VER > 17 + +template +struct __shared_ptr_convertible_to_weak_ptr +#if _LIBCPP_STD_VER > 17 + : is_convertible*, remove_extent_t<_Up>*> {}; +#elif _LIBCPP_STD_VER > 14 + : is_convertible, _Up*> {}; +#else + : is_convertible<_Tp*, _Up*> {}; +#endif // _LIBCPP_STD_VER > 17 + +template +struct __weak_ptr_convertible_to_shared_ptr +#if _LIBCPP_STD_VER > 17 + : is_convertible*, remove_extent_t<_Up>*> {}; +#elif _LIBCPP_STD_VER > 14 + : is_convertible<_Tp*, remove_extent_t<_Up>> {}; +#else + : is_convertible<_Tp*, _Up*> {}; +#endif // _LIBCPP_STD_VER > 17 + template struct __is_deletable : false_type { }; template @@ -404,7 +432,7 @@ template struct __shared_ptr_deleter_ctor_reqs { - static const bool value = __compatible_with<_Tp, _Yp>::value && + static const bool value = __shared_ptr_compatible_with<_Tp, _Yp>::value && is_move_constructible<_Dp>::value && __well_formed_deleter<_Dp, _Tp*>::value; }; @@ -439,7 +467,7 @@ template + __shared_ptr_compatible_with<_Yp, _Tp> // In C++03 we get errors when trying to do SFINAE with the // delete operator, so we always pretend that it's deletable. // The same happens on GCC. @@ -471,15 +499,15 @@ template _LIBCPP_INLINE_VISIBILITY shared_ptr(const shared_ptr<_Yp>& __r, - typename enable_if<__compatible_with<_Yp, element_type>::value, __nat>::type = __nat()) + typename enable_if<__shared_ptr_compatible_with<_Yp, _Tp>::value, __nat>::type = __nat()) _NOEXCEPT; _LIBCPP_INLINE_VISIBILITY shared_ptr(shared_ptr&& __r) _NOEXCEPT; template _LIBCPP_INLINE_VISIBILITY shared_ptr(shared_ptr<_Yp>&& __r, - typename enable_if<__compatible_with<_Yp, element_type>::value, __nat>::type = __nat()) + typename enable_if<__shared_ptr_compatible_with<_Yp, _Tp>::value, __nat>::type = __nat()) _NOEXCEPT; template explicit shared_ptr(const weak_ptr<_Yp>& __r, - typename enable_if::value, __nat>::type= __nat()); + typename enable_if<__weak_ptr_convertible_to_shared_ptr<_Yp, _Tp>::value, __nat>::type= __nat()); #if _LIBCPP_STD_VER <= 14 || defined(_LIBCPP_ENABLE_CXX17_REMOVED_AUTO_PTR) template shared_ptr(auto_ptr<_Yp>&& __r, @@ -509,7 +537,7 @@ template typename enable_if < - __compatible_with<_Yp, element_type>::value, + __shared_ptr_compatible_with<_Yp, _Tp>::value, shared_ptr& >::type _LIBCPP_INLINE_VISIBILITY @@ -519,7 +547,7 @@ template typename enable_if < - __compatible_with<_Yp, element_type>::value, + __shared_ptr_compatible_with<_Yp, _Tp>::value, shared_ptr& >::type _LIBCPP_INLINE_VISIBILITY @@ -551,7 +579,7 @@ template typename enable_if < - __compatible_with<_Yp, element_type>::value, + __shared_ptr_compatible_with<_Yp, _Tp>::value, void >::type _LIBCPP_INLINE_VISIBILITY @@ -559,7 +587,7 @@ template typename enable_if < - __compatible_with<_Yp, element_type>::value, + __shared_ptr_compatible_with<_Yp, _Tp>::value, void >::type _LIBCPP_INLINE_VISIBILITY @@ -567,7 +595,7 @@ template typename enable_if < - __compatible_with<_Yp, element_type>::value, + __shared_ptr_compatible_with<_Yp, _Tp>::value, void >::type _LIBCPP_INLINE_VISIBILITY @@ -851,7 +879,7 @@ template inline shared_ptr<_Tp>::shared_ptr(const shared_ptr<_Yp>& __r, - typename enable_if<__compatible_with<_Yp, element_type>::value, __nat>::type) + typename enable_if<__shared_ptr_compatible_with<_Yp, _Tp>::value, __nat>::type) _NOEXCEPT : __ptr_(__r.__ptr_), __cntrl_(__r.__cntrl_) @@ -874,7 +902,7 @@ template inline shared_ptr<_Tp>::shared_ptr(shared_ptr<_Yp>&& __r, - typename enable_if<__compatible_with<_Yp, element_type>::value, __nat>::type) + typename enable_if<__shared_ptr_compatible_with<_Yp, _Tp>::value, __nat>::type) _NOEXCEPT : __ptr_(__r.__ptr_), __cntrl_(__r.__cntrl_) @@ -970,7 +998,7 @@ inline typename enable_if < - __compatible_with<_Yp, typename shared_ptr<_Tp>::element_type>::value, + __shared_ptr_compatible_with<_Yp, _Tp>::value, shared_ptr<_Tp>& >::type shared_ptr<_Tp>::operator=(const shared_ptr<_Yp>& __r) _NOEXCEPT @@ -993,7 +1021,7 @@ inline typename enable_if < - __compatible_with<_Yp, typename shared_ptr<_Tp>::element_type>::value, + __shared_ptr_compatible_with<_Yp, _Tp>::value, shared_ptr<_Tp>& >::type shared_ptr<_Tp>::operator=(shared_ptr<_Yp>&& __r) @@ -1056,7 +1084,7 @@ inline typename enable_if < - __compatible_with<_Yp, typename shared_ptr<_Tp>::element_type>::value, + __shared_ptr_compatible_with<_Yp, _Tp>::value, void >::type shared_ptr<_Tp>::reset(_Yp* __p) @@ -1069,7 +1097,7 @@ inline typename enable_if < - __compatible_with<_Yp, typename shared_ptr<_Tp>::element_type>::value, + __shared_ptr_compatible_with<_Yp, _Tp>::value, void >::type shared_ptr<_Tp>::reset(_Yp* __p, _Dp __d) @@ -1082,7 +1110,7 @@ inline typename enable_if < - __compatible_with<_Yp, typename shared_ptr<_Tp>::element_type>::value, + __shared_ptr_compatible_with<_Yp, _Tp>::value, void >::type shared_ptr<_Tp>::reset(_Yp* __p, _Dp __d, _Alloc __a) @@ -1323,7 +1351,12 @@ class _LIBCPP_SHARED_PTR_TRIVIAL_ABI _LIBCPP_TEMPLATE_VIS weak_ptr { public: +#if _LIBCPP_STD_VER > 17 + typedef remove_extent_t<_Tp> element_type; +#else typedef _Tp element_type; +#endif + private: element_type* __ptr_; __shared_weak_count* __cntrl_; @@ -1332,18 +1365,18 @@ _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR weak_ptr() _NOEXCEPT; template _LIBCPP_INLINE_VISIBILITY weak_ptr(shared_ptr<_Yp> const& __r, - typename enable_if::value, __nat*>::type = 0) + typename enable_if<__shared_ptr_convertible_to_weak_ptr<_Yp, _Tp>::value, __nat*>::type = 0) _NOEXCEPT; _LIBCPP_INLINE_VISIBILITY weak_ptr(weak_ptr const& __r) _NOEXCEPT; template _LIBCPP_INLINE_VISIBILITY weak_ptr(weak_ptr<_Yp> const& __r, - typename enable_if::value, __nat*>::type = 0) + typename enable_if<__weak_ptr_compatible_with<_Yp, _Tp>::value, __nat*>::type = 0) _NOEXCEPT; _LIBCPP_INLINE_VISIBILITY weak_ptr(weak_ptr&& __r) _NOEXCEPT; template _LIBCPP_INLINE_VISIBILITY weak_ptr(weak_ptr<_Yp>&& __r, - typename enable_if::value, __nat*>::type = 0) + typename enable_if<__weak_ptr_compatible_with<_Yp, _Tp>::value, __nat*>::type = 0) _NOEXCEPT; ~weak_ptr(); @@ -1352,7 +1385,7 @@ template typename enable_if < - is_convertible<_Yp*, element_type*>::value, + __weak_ptr_compatible_with<_Yp, _Tp>::value, weak_ptr& >::type _LIBCPP_INLINE_VISIBILITY @@ -1363,7 +1396,7 @@ template typename enable_if < - is_convertible<_Yp*, element_type*>::value, + __weak_ptr_compatible_with<_Yp, _Tp>::value, weak_ptr& >::type _LIBCPP_INLINE_VISIBILITY @@ -1372,7 +1405,7 @@ template typename enable_if < - is_convertible<_Yp*, element_type*>::value, + __shared_ptr_convertible_to_weak_ptr<_Yp, _Tp>::value, weak_ptr& >::type _LIBCPP_INLINE_VISIBILITY @@ -1431,7 +1464,7 @@ template inline weak_ptr<_Tp>::weak_ptr(shared_ptr<_Yp> const& __r, - typename enable_if::value, __nat*>::type) + typename enable_if<__shared_ptr_convertible_to_weak_ptr<_Yp, _Tp>::value, __nat*>::type) _NOEXCEPT : __ptr_(__r.__ptr_), __cntrl_(__r.__cntrl_) @@ -1444,7 +1477,7 @@ template inline weak_ptr<_Tp>::weak_ptr(weak_ptr<_Yp> const& __r, - typename enable_if::value, __nat*>::type) + typename enable_if<__weak_ptr_compatible_with<_Yp, _Tp>::value, __nat*>::type) _NOEXCEPT : __ptr_(__r.__ptr_), __cntrl_(__r.__cntrl_) @@ -1467,7 +1500,7 @@ template inline weak_ptr<_Tp>::weak_ptr(weak_ptr<_Yp>&& __r, - typename enable_if::value, __nat*>::type) + typename enable_if<__weak_ptr_compatible_with<_Yp, _Tp>::value, __nat*>::type) _NOEXCEPT : __ptr_(__r.__ptr_), __cntrl_(__r.__cntrl_) @@ -1497,7 +1530,7 @@ inline typename enable_if < - is_convertible<_Yp*, _Tp*>::value, + __weak_ptr_compatible_with<_Yp, _Tp>::value, weak_ptr<_Tp>& >::type weak_ptr<_Tp>::operator=(weak_ptr<_Yp> const& __r) _NOEXCEPT @@ -1520,7 +1553,7 @@ inline typename enable_if < - is_convertible<_Yp*, _Tp*>::value, + __weak_ptr_compatible_with<_Yp, _Tp>::value, weak_ptr<_Tp>& >::type weak_ptr<_Tp>::operator=(weak_ptr<_Yp>&& __r) _NOEXCEPT @@ -1534,7 +1567,7 @@ inline typename enable_if < - is_convertible<_Yp*, _Tp*>::value, + __shared_ptr_convertible_to_weak_ptr<_Yp, _Tp>::value, weak_ptr<_Tp>& >::type weak_ptr<_Tp>::operator=(shared_ptr<_Yp> const& __r) _NOEXCEPT @@ -1571,7 +1604,7 @@ template template shared_ptr<_Tp>::shared_ptr(const weak_ptr<_Yp>& __r, - typename enable_if::value, __nat>::type) + typename enable_if<__weak_ptr_convertible_to_shared_ptr<_Yp, _Tp>::value, __nat>::type) : __ptr_(__r.__ptr_), __cntrl_(__r.__cntrl_ ? __r.__cntrl_->lock() : __r.__cntrl_) { diff --git a/libcxx/include/memory b/libcxx/include/memory --- a/libcxx/include/memory +++ b/libcxx/include/memory @@ -405,7 +405,8 @@ class shared_ptr { public: - typedef T element_type; + typedef T element_type; // until C++17 + typedef remove_extent_t element_type; // since C++17 typedef weak_ptr weak_type; // C++17 // constructors: @@ -525,7 +526,8 @@ class weak_ptr { public: - typedef T element_type; + typedef T element_type; // until C++20 + typedef remove_extent_t element_type; // since C++20 // constructors constexpr weak_ptr() noexcept; diff --git a/libcxx/test/std/utilities/memory/util.smartptr/util.smartptr.shared/types.pass.cpp b/libcxx/test/std/utilities/memory/util.smartptr/util.smartptr.shared/types.pass.cpp --- a/libcxx/test/std/utilities/memory/util.smartptr/util.smartptr.shared/types.pass.cpp +++ b/libcxx/test/std/utilities/memory/util.smartptr/util.smartptr.shared/types.pass.cpp @@ -11,7 +11,8 @@ // template class shared_ptr // { // public: -// typedef T element_type; +// typedef T element_type; // until C++17 +// typedef remove_extent_t element_type; // since C++17 // typedef weak_ptr weak_type; // C++17 // ... // }; diff --git a/libcxx/test/std/utilities/memory/util.smartptr/util.smartptr.shared/util.smartptr.shared.const/weak_ptr.pass.cpp b/libcxx/test/std/utilities/memory/util.smartptr/util.smartptr.shared/util.smartptr.shared.const/weak_ptr.pass.cpp --- a/libcxx/test/std/utilities/memory/util.smartptr/util.smartptr.shared/util.smartptr.shared.const/weak_ptr.pass.cpp +++ b/libcxx/test/std/utilities/memory/util.smartptr/util.smartptr.shared/util.smartptr.shared.const/weak_ptr.pass.cpp @@ -82,5 +82,17 @@ assert(A::count == 0); #endif +#if TEST_STD_VER > 17 + { + std::shared_ptr sp0(new A[8]); + std::weak_ptr wp(sp0); + std::shared_ptr sp(wp); + assert(sp.use_count() == 2); + assert(sp.get() == sp0.get()); + assert(A::count == 8); + } + assert(A::count == 0); +#endif + return 0; } diff --git a/libcxx/test/std/utilities/memory/util.smartptr/util.smartptr.weak/types.pass.cpp b/libcxx/test/std/utilities/memory/util.smartptr/util.smartptr.weak/types.pass.cpp --- a/libcxx/test/std/utilities/memory/util.smartptr/util.smartptr.weak/types.pass.cpp +++ b/libcxx/test/std/utilities/memory/util.smartptr/util.smartptr.weak/types.pass.cpp @@ -11,7 +11,8 @@ // template class weak_ptr // { // public: -// typedef T element_type; +// typedef T element_type; // until C++20 +// typedef remove_extent_t element_type; // since C++20 // ... // }; @@ -20,10 +21,28 @@ #include "test_macros.h" struct A; // purposefully incomplete +struct B { + int x; + B() = default; +}; + +template +void test() { + ASSERT_SAME_TYPE(typename std::weak_ptr::element_type, T); +#if TEST_STD_VER > 17 + static_assert( + std::is_same::element_type, T>::value, ""); + static_assert( + std::is_same::element_type, T>::value, ""); +#endif +} int main(int, char**) { - static_assert((std::is_same::element_type, A>::value), ""); + test(); + test(); + test(); + test(); return 0; } diff --git a/libcxx/test/std/utilities/memory/util.smartptr/util.smartptr.weak/util.smartptr.weak.assign/shared_ptr_Y.pass.cpp b/libcxx/test/std/utilities/memory/util.smartptr/util.smartptr.weak/util.smartptr.weak.assign/shared_ptr_Y.pass.cpp --- a/libcxx/test/std/utilities/memory/util.smartptr/util.smartptr.weak/util.smartptr.weak.assign/shared_ptr_Y.pass.cpp +++ b/libcxx/test/std/utilities/memory/util.smartptr/util.smartptr.weak/util.smartptr.weak.assign/shared_ptr_Y.pass.cpp @@ -61,5 +61,22 @@ assert(B::count == 0); assert(A::count == 0); +#if TEST_STD_VER > 17 + { + const std::shared_ptr p1(new A[8]); + assert(p1.use_count() == 1); + { + std::weak_ptr p2; + p2 = p1; + assert(A::count == 8); + assert(p2.use_count() == 1); + assert(p1.use_count() == 1); + } + assert(p1.use_count() == 1); + assert(A::count == 8); + } + assert(A::count == 0); +#endif + return 0; } diff --git a/libcxx/test/std/utilities/memory/util.smartptr/util.smartptr.weak/util.smartptr.weak.assign/weak_ptr_Y.pass.cpp b/libcxx/test/std/utilities/memory/util.smartptr/util.smartptr.weak/util.smartptr.weak.assign/weak_ptr_Y.pass.cpp --- a/libcxx/test/std/utilities/memory/util.smartptr/util.smartptr.weak/util.smartptr.weak.assign/weak_ptr_Y.pass.cpp +++ b/libcxx/test/std/utilities/memory/util.smartptr/util.smartptr.weak/util.smartptr.weak.assign/weak_ptr_Y.pass.cpp @@ -11,9 +11,11 @@ // weak_ptr // template weak_ptr& operator=(const weak_ptr& r); +// template weak_ptr& operator=(weak_ptr&& r); #include #include +#include #include #include "test_macros.h" @@ -77,5 +79,35 @@ assert(B::count == 0); assert(A::count == 0); +#if TEST_STD_VER > 17 + { + const std::shared_ptr ps(new A[8]); + const std::weak_ptr p1(ps); + { + std::weak_ptr p2; + p2 = p1; + assert(A::count == 8); + assert(p2.use_count() == 1); + assert(p1.use_count() == 1); + } + assert(p1.use_count() == 1); + assert(A::count == 8); + } + assert(A::count == 0); + + { + const std::shared_ptr ps(new A[8]); + std::weak_ptr p1(ps); + { + std::weak_ptr p2; + p2 = std::move(p1); + assert(A::count == 8); + assert(p2.use_count() == 1); + } + assert(A::count == 8); + } + assert(A::count == 0); +#endif + return 0; } diff --git a/libcxx/test/std/utilities/memory/util.smartptr/util.smartptr.weak/util.smartptr.weak.const/shared_ptr_Y.pass.cpp b/libcxx/test/std/utilities/memory/util.smartptr/util.smartptr.weak/util.smartptr.weak.const/shared_ptr_Y.pass.cpp --- a/libcxx/test/std/utilities/memory/util.smartptr/util.smartptr.weak/util.smartptr.weak.const/shared_ptr_Y.pass.cpp +++ b/libcxx/test/std/utilities/memory/util.smartptr/util.smartptr.weak/util.smartptr.weak.const/shared_ptr_Y.pass.cpp @@ -94,5 +94,22 @@ assert(B::count == 0); assert(A::count == 0); +#if TEST_STD_VER > 17 + { + std::shared_ptr p1(new A[8]); + assert(p1.use_count() == 1); + assert(A::count == 8); + { + std::weak_ptr p2(p1); + assert(A::count == 8); + assert(p2.use_count() == 1); + assert(p1.use_count() == 1); + } + assert(p1.use_count() == 1); + assert(A::count == 8); + } + assert(A::count == 0); +#endif + return 0; } diff --git a/libcxx/test/std/utilities/memory/util.smartptr/util.smartptr.weak/util.smartptr.weak.const/weak_ptr_Y.pass.cpp b/libcxx/test/std/utilities/memory/util.smartptr/util.smartptr.weak/util.smartptr.weak.const/weak_ptr_Y.pass.cpp --- a/libcxx/test/std/utilities/memory/util.smartptr/util.smartptr.weak/util.smartptr.weak.const/weak_ptr_Y.pass.cpp +++ b/libcxx/test/std/utilities/memory/util.smartptr/util.smartptr.weak/util.smartptr.weak.const/weak_ptr_Y.pass.cpp @@ -11,10 +11,11 @@ // weak_ptr // template weak_ptr(const weak_ptr& r); -// template weak_ptr(weak_ptr &&r); +// template weak_ptr(weak_ptr&& r); #include #include +#include #include #include "test_macros.h" @@ -107,5 +108,23 @@ assert(B::count == 0); assert(A::count == 0); +#if TEST_STD_VER > 17 + { + std::shared_ptr ps(new A[8]); + std::weak_ptr p1 = source(ps); + std::weak_ptr p2(p1); + assert(p2.use_count() == 1); + } + assert(A::count == 0); + + { + std::shared_ptr ps(new A[8]); + std::weak_ptr p1 = source(ps); + std::weak_ptr p2(std::move(p1)); + assert(p2.use_count() == 1); + } + assert(A::count == 0); +#endif + return 0; }