From: Jonathan Wakely Date: Thu, 20 Oct 2016 12:07:45 +0000 (+0100) Subject: Prepare shared_ptr for array support X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=a2e0054e1d169984ec64d64145b71a88a9628537;p=gcc.git Prepare shared_ptr for array support * include/backward/auto_ptr.h (__shared_ptr(auto_ptr&&)) (shared_ptr(auto_ptr&&)): Adjust template parameter lists. * include/bits/shared_ptr.h (__sp_compatible_with) (__sp_is_constructible): New helper traits for shared_ptr. (shared_ptr::_Convertible): Replace with _Constructible. (shared_ptr::_Constructible, shared_ptr::_Assignable): Forward checks to base class. (shared_ptr::shared_ptr, shared_ptr::operator=): Constrain template with _Constructible and _Assignable. (shared_ptr::shared_ptr(shared_ptr<_Tp1>, _Tp*)): Use element_type instead of _Tp. (operator<): Likewise. (operator>): Define in terms of operator<. (static_pointer_cast, const_pointer_cast, dynamic_pointer_cast): Use element_type instead of _Tp. (reinterpret_pointer_cast): Define for C++17. (weak_ptr::_Convertible): Replace with _Constructible. (weak_ptr::_Constructible, weak_ptr::_Assignable): Forward checks to base class. (weak_ptr::weak_ptr, weak_ptr::operator=): Constrain templates with _Constructible and _Assignable. * include/bits/shared_ptr_base.h (__shared_ptr::_Convertible): Replace with _Compatible. (__shared_ptr::_SafeConv): New constraint for incoming raw pointers. (__shared_ptr::_Compatible): New constraint for converting from other types of shared_ptr and weak_ptr. (__shared_ptr::_Assignable): Define in terms of _Compatible. (__shared_ptr::_UniqCompatible, __shared_ptr::_UniqAssignable): New constraints for converting from unique_ptr. (__shared_ptr::__shared_ptr, __shared_ptr::operator=): Constrain template with _SaveConf, _Compatible and _Assignable. Remove __glibcxx_function_requires concept checks. Add static assertion for deleter expression being well-formed. (__shared_ptr::__shared_ptr(__shared_ptr<_Tp1>, _Tp*)) (__shared_ptr::operator*, __shared_ptr::operator->) (__shared_ptr::get, __shared_ptr::_M_ptr): Use element_type instead of _Tp. (operator<): Likewise. (operator>): Define in terms of operator<. (static_pointer_cast, const_pointer_cast, dynamic_pointer_cast): Use element_type instead of _Tp. (reinterpret_pointer_cast): Define for C++17. (weak_ptr::_Convertible): Replace with _Compatible. (weak_ptr::_Compatible, weak_ptr::_Assignable): New constraints for conversions from other types of weak_ptr and shared_ptr. (__weak_ptr::__weak_ptr, __weak_ptr::operator=): Constrain templates with _Constructible and _Assignable. (__weak_ptr::_M_ptr): Use element_type instead of _Tp. * testsuite/20_util/shared_ptr/assign/auto_ptr_neg.cc: Adjust dg-error pattern. * testsuite/20_util/shared_ptr/cons/auto_ptr.cc: Test conversions. * testsuite/20_util/shared_ptr/cons/unique_ptr.cc: Likewise. * testsuite/20_util/shared_ptr/cons/void_neg.cc: Likewise. * testsuite/20_util/shared_ptr/casts/reinterpret.cc: New test. From-SVN: r241373 --- diff --git a/libstdc++-v3/ChangeLog b/libstdc++-v3/ChangeLog index 378e9fad145..6f47e0d2b62 100644 --- a/libstdc++-v3/ChangeLog +++ b/libstdc++-v3/ChangeLog @@ -1,3 +1,60 @@ +2016-10-20 Jonathan Wakely + + * include/backward/auto_ptr.h (__shared_ptr(auto_ptr&&)) + (shared_ptr(auto_ptr&&)): Adjust template parameter lists. + * include/bits/shared_ptr.h (__sp_compatible_with) + (__sp_is_constructible): New helper traits for shared_ptr. + (shared_ptr::_Convertible): Replace with _Constructible. + (shared_ptr::_Constructible, shared_ptr::_Assignable): Forward checks + to base class. + (shared_ptr::shared_ptr, shared_ptr::operator=): Constrain template + with _Constructible and _Assignable. + (shared_ptr::shared_ptr(shared_ptr<_Tp1>, _Tp*)): Use element_type + instead of _Tp. + (operator<): Likewise. + (operator>): Define in terms of operator<. + (static_pointer_cast, const_pointer_cast, dynamic_pointer_cast): Use + element_type instead of _Tp. + (reinterpret_pointer_cast): Define for C++17. + (weak_ptr::_Convertible): Replace with _Constructible. + (weak_ptr::_Constructible, weak_ptr::_Assignable): Forward checks + to base class. + (weak_ptr::weak_ptr, weak_ptr::operator=): Constrain templates + with _Constructible and _Assignable. + * include/bits/shared_ptr_base.h (__shared_ptr::_Convertible): Replace + with _Compatible. + (__shared_ptr::_SafeConv): New constraint for incoming raw pointers. + (__shared_ptr::_Compatible): New constraint for converting from + other types of shared_ptr and weak_ptr. + (__shared_ptr::_Assignable): Define in terms of _Compatible. + (__shared_ptr::_UniqCompatible, __shared_ptr::_UniqAssignable): New + constraints for converting from unique_ptr. + (__shared_ptr::__shared_ptr, __shared_ptr::operator=): Constrain + template with _SaveConf, _Compatible and _Assignable. Remove + __glibcxx_function_requires concept checks. Add static assertion for + deleter expression being well-formed. + (__shared_ptr::__shared_ptr(__shared_ptr<_Tp1>, _Tp*)) + (__shared_ptr::operator*, __shared_ptr::operator->) + (__shared_ptr::get, __shared_ptr::_M_ptr): Use element_type instead + of _Tp. + (operator<): Likewise. + (operator>): Define in terms of operator<. + (static_pointer_cast, const_pointer_cast, dynamic_pointer_cast): Use + element_type instead of _Tp. + (reinterpret_pointer_cast): Define for C++17. + (weak_ptr::_Convertible): Replace with _Compatible. + (weak_ptr::_Compatible, weak_ptr::_Assignable): New constraints for + conversions from other types of weak_ptr and shared_ptr. + (__weak_ptr::__weak_ptr, __weak_ptr::operator=): Constrain templates + with _Constructible and _Assignable. + (__weak_ptr::_M_ptr): Use element_type instead of _Tp. + * testsuite/20_util/shared_ptr/assign/auto_ptr_neg.cc: Adjust + dg-error pattern. + * testsuite/20_util/shared_ptr/cons/auto_ptr.cc: Test conversions. + * testsuite/20_util/shared_ptr/cons/unique_ptr.cc: Likewise. + * testsuite/20_util/shared_ptr/cons/void_neg.cc: Likewise. + * testsuite/20_util/shared_ptr/casts/reinterpret.cc: New test. + 2016-10-20 Ville Voutilainen Do the operator= SFINAE in the return type for optional, diff --git a/libstdc++-v3/include/backward/auto_ptr.h b/libstdc++-v3/include/backward/auto_ptr.h index 94911c87981..855b6f90dea 100644 --- a/libstdc++-v3/include/backward/auto_ptr.h +++ b/libstdc++-v3/include/backward/auto_ptr.h @@ -302,7 +302,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION { __r.release(); } template - template + template inline __shared_ptr<_Tp, _Lp>::__shared_ptr(std::auto_ptr<_Tp1>&& __r) : _M_ptr(__r.get()), _M_refcount() @@ -315,7 +315,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION } template - template + template inline shared_ptr<_Tp>::shared_ptr(std::auto_ptr<_Tp1>&& __r) : __shared_ptr<_Tp>(std::move(__r)) { } diff --git a/libstdc++-v3/include/bits/shared_ptr.h b/libstdc++-v3/include/bits/shared_ptr.h index 9b9261c04e4..9f7a40c5e1e 100644 --- a/libstdc++-v3/include/bits/shared_ptr.h +++ b/libstdc++-v3/include/bits/shared_ptr.h @@ -92,16 +92,20 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION template class shared_ptr : public __shared_ptr<_Tp> { - template - using _Convertible = typename - enable_if::value>::type; + template + using _Constructible = typename enable_if< + is_constructible<__shared_ptr<_Tp>, _Args...>::value + >::type; - template - using _Assignable = typename - enable_if::value, shared_ptr&>::type; + template + using _Assignable = typename enable_if< + is_assignable<__shared_ptr<_Tp>&, _Arg>::value, shared_ptr& + >::type; public: + using element_type = typename __shared_ptr<_Tp>::element_type; + #if __cplusplus > 201402L # define __cpp_lib_shared_ptr_weak_type 201606 using weak_type = weak_ptr<_Tp>; @@ -110,8 +114,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION * @brief Construct an empty %shared_ptr. * @post use_count()==0 && get()==0 */ - constexpr shared_ptr() noexcept - : __shared_ptr<_Tp>() { } + constexpr shared_ptr() noexcept : __shared_ptr<_Tp>() { } shared_ptr(const shared_ptr&) noexcept = default; @@ -121,9 +124,9 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION * @post use_count() == 1 && get() == __p * @throw std::bad_alloc, in which case @c delete @a __p is called. */ - template - explicit shared_ptr(_Tp1* __p) - : __shared_ptr<_Tp>(__p) { } + template> + explicit + shared_ptr(_Yp* __p) : __shared_ptr<_Tp>(__p) { } /** * @brief Construct a %shared_ptr that owns the pointer @a __p @@ -138,8 +141,9 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION * * __shared_ptr will release __p by calling __d(__p) */ - template - shared_ptr(_Tp1* __p, _Deleter __d) + template> + shared_ptr(_Yp* __p, _Deleter __d) : __shared_ptr<_Tp>(__p, __d) { } /** @@ -174,8 +178,9 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION * * __shared_ptr will release __p by calling __d(__p) */ - template - shared_ptr(_Tp1* __p, _Deleter __d, _Alloc __a) + template> + shared_ptr(_Yp* __p, _Deleter __d, _Alloc __a) : __shared_ptr<_Tp>(__p, __d, std::move(__a)) { } /** @@ -215,8 +220,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION * assert(pii.use_count() == 2); * @endcode */ - template - shared_ptr(const shared_ptr<_Tp1>& __r, _Tp* __p) noexcept + template + shared_ptr(const shared_ptr<_Yp>& __r, element_type* __p) noexcept : __shared_ptr<_Tp>(__r, __p) { } /** @@ -226,8 +231,9 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION * @param __r A %shared_ptr. * @post get() == __r.get() && use_count() == __r.use_count() */ - template> - shared_ptr(const shared_ptr<_Tp1>& __r) noexcept + template&>> + shared_ptr(const shared_ptr<_Yp>& __r) noexcept : __shared_ptr<_Tp>(__r) { } /** @@ -243,8 +249,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION * @param __r A %shared_ptr rvalue. * @post *this contains the old value of @a __r, @a __r is empty. */ - template> - shared_ptr(shared_ptr<_Tp1>&& __r) noexcept + template>> + shared_ptr(shared_ptr<_Yp>&& __r) noexcept : __shared_ptr<_Tp>(std::move(__r)) { } /** @@ -255,20 +261,20 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION * @throw bad_weak_ptr when __r.expired(), * in which case the constructor has no effect. */ - template - explicit shared_ptr(const weak_ptr<_Tp1>& __r) + template&>> + explicit shared_ptr(const weak_ptr<_Yp>& __r) : __shared_ptr<_Tp>(__r) { } #if _GLIBCXX_USE_DEPRECATED - template - shared_ptr(std::auto_ptr<_Tp1>&& __r); + template>> + shared_ptr(auto_ptr<_Yp>&& __r); #endif // _GLIBCXX_RESOLVE_LIB_DEFECTS // 2399. shared_ptr's constructor from unique_ptr should be constrained - template::pointer>> - shared_ptr(std::unique_ptr<_Tp1, _Del>&& __r) + template>> + shared_ptr(unique_ptr<_Yp, _Del>&& __r) : __shared_ptr<_Tp>(std::move(__r)) { } /** @@ -279,18 +285,18 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION shared_ptr& operator=(const shared_ptr&) noexcept = default; - template - _Assignable<_Tp1*> - operator=(const shared_ptr<_Tp1>& __r) noexcept + template + _Assignable&> + operator=(const shared_ptr<_Yp>& __r) noexcept { this->__shared_ptr<_Tp>::operator=(__r); return *this; } #if _GLIBCXX_USE_DEPRECATED - template - shared_ptr& - operator=(std::auto_ptr<_Tp1>&& __r) + template + _Assignable> + operator=(auto_ptr<_Yp>&& __r) { this->__shared_ptr<_Tp>::operator=(std::move(__r)); return *this; @@ -304,17 +310,17 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION return *this; } - template - _Assignable<_Tp1*> - operator=(shared_ptr<_Tp1>&& __r) noexcept + template + _Assignable> + operator=(shared_ptr<_Yp>&& __r) noexcept { this->__shared_ptr<_Tp>::operator=(std::move(__r)); return *this; } - template - _Assignable::pointer> - operator=(std::unique_ptr<_Tp1, _Del>&& __r) + template + _Assignable> + operator=(unique_ptr<_Yp, _Del>&& __r) { this->__shared_ptr<_Tp>::operator=(std::move(__r)); return *this; @@ -328,8 +334,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION : __shared_ptr<_Tp>(__tag, __a, std::forward<_Args>(__args)...) { } - template - friend shared_ptr<_Tp1> + template + friend shared_ptr<_Yp> allocate_shared(const _Alloc& __a, _Args&&... __args); // This constructor is non-standard, it is used by weak_ptr::lock(). @@ -340,10 +346,9 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION }; // 20.7.2.2.7 shared_ptr comparisons - template + template inline bool - operator==(const shared_ptr<_Tp1>& __a, - const shared_ptr<_Tp2>& __b) noexcept + operator==(const shared_ptr<_Tp>& __a, const shared_ptr<_Up>& __b) noexcept { return __a.get() == __b.get(); } template @@ -356,10 +361,9 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION operator==(nullptr_t, const shared_ptr<_Tp>& __a) noexcept { return !__a; } - template + template inline bool - operator!=(const shared_ptr<_Tp1>& __a, - const shared_ptr<_Tp2>& __b) noexcept + operator!=(const shared_ptr<_Tp>& __a, const shared_ptr<_Up>& __b) noexcept { return __a.get() != __b.get(); } template @@ -372,29 +376,35 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION operator!=(nullptr_t, const shared_ptr<_Tp>& __a) noexcept { return (bool)__a; } - template + template inline bool - operator<(const shared_ptr<_Tp1>& __a, - const shared_ptr<_Tp2>& __b) noexcept + operator<(const shared_ptr<_Tp>& __a, const shared_ptr<_Up>& __b) noexcept { - typedef typename std::common_type<_Tp1*, _Tp2*>::type _CT; - return std::less<_CT>()(__a.get(), __b.get()); + using _Tp_elt = typename shared_ptr<_Tp>::element_type; + using _Up_elt = typename shared_ptr<_Up>::element_type; + using _Vp = typename common_type<_Tp_elt*, _Up_elt*>::type; + return less<_Vp>()(__a.get(), __b.get()); } template inline bool operator<(const shared_ptr<_Tp>& __a, nullptr_t) noexcept - { return std::less<_Tp*>()(__a.get(), nullptr); } + { + using _Tp_elt = typename shared_ptr<_Tp>::element_type; + return less<_Tp_elt*>()(__a.get(), nullptr); + } template inline bool operator<(nullptr_t, const shared_ptr<_Tp>& __a) noexcept - { return std::less<_Tp*>()(nullptr, __a.get()); } + { + using _Tp_elt = typename shared_ptr<_Tp>::element_type; + return less<_Tp_elt*>()(nullptr, __a.get()); + } - template + template inline bool - operator<=(const shared_ptr<_Tp1>& __a, - const shared_ptr<_Tp2>& __b) noexcept + operator<=(const shared_ptr<_Tp>& __a, const shared_ptr<_Up>& __b) noexcept { return !(__b < __a); } template @@ -407,26 +417,24 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION operator<=(nullptr_t, const shared_ptr<_Tp>& __a) noexcept { return !(__a < nullptr); } - template + template inline bool - operator>(const shared_ptr<_Tp1>& __a, - const shared_ptr<_Tp2>& __b) noexcept + operator>(const shared_ptr<_Tp>& __a, const shared_ptr<_Up>& __b) noexcept { return (__b < __a); } template inline bool operator>(const shared_ptr<_Tp>& __a, nullptr_t) noexcept - { return std::less<_Tp*>()(nullptr, __a.get()); } + { return nullptr < __a; } template inline bool operator>(nullptr_t, const shared_ptr<_Tp>& __a) noexcept - { return std::less<_Tp*>()(__a.get(), nullptr); } + { return __a < nullptr; } - template + template inline bool - operator>=(const shared_ptr<_Tp1>& __a, - const shared_ptr<_Tp2>& __b) noexcept + operator>=(const shared_ptr<_Tp>& __a, const shared_ptr<_Up>& __b) noexcept { return !(__a < __b); } template @@ -450,25 +458,41 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION { __a.swap(__b); } // 20.7.2.2.9 shared_ptr casts. - template + template inline shared_ptr<_Tp> - static_pointer_cast(const shared_ptr<_Tp1>& __r) noexcept - { return shared_ptr<_Tp>(__r, static_cast<_Tp*>(__r.get())); } + static_pointer_cast(const shared_ptr<_Up>& __r) noexcept + { + using _Sp = shared_ptr<_Tp>; + return _Sp(__r, static_cast(__r.get())); + } - template + template inline shared_ptr<_Tp> - const_pointer_cast(const shared_ptr<_Tp1>& __r) noexcept - { return shared_ptr<_Tp>(__r, const_cast<_Tp*>(__r.get())); } + const_pointer_cast(const shared_ptr<_Up>& __r) noexcept + { + using _Sp = shared_ptr<_Tp>; + return _Sp(__r, const_cast(__r.get())); + } - template + template inline shared_ptr<_Tp> - dynamic_pointer_cast(const shared_ptr<_Tp1>& __r) noexcept + dynamic_pointer_cast(const shared_ptr<_Up>& __r) noexcept { - if (_Tp* __p = dynamic_cast<_Tp*>(__r.get())) - return shared_ptr<_Tp>(__r, __p); - return shared_ptr<_Tp>(); + using _Sp = shared_ptr<_Tp>; + if (auto* __p = dynamic_cast(__r.get())) + return _Sp(__r, __p); + return _Sp(); } +#if __cplusplus > 201402L + template + inline shared_ptr<_Tp> + reinterpret_pointer_cast(const shared_ptr<_Up>& __r) noexcept + { + using _Sp = shared_ptr<_Tp>; + return _Sp(__r, reinterpret_cast(__r.get())); + } +#endif /** * @brief A smart pointer with weak semantics. @@ -478,43 +502,50 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION template class weak_ptr : public __weak_ptr<_Tp> { - template - using _Convertible - = typename enable_if::value>::type; + template + using _Constructible = typename enable_if< + is_constructible<__weak_ptr<_Tp>, _Arg>::value + >::type; + + template + using _Assignable = typename enable_if< + is_assignable<__weak_ptr<_Tp>&, _Arg>::value, weak_ptr& + >::type; public: constexpr weak_ptr() noexcept = default; - template> - weak_ptr(const shared_ptr<_Tp1>& __r) noexcept + template&>> + weak_ptr(const shared_ptr<_Yp>& __r) noexcept : __weak_ptr<_Tp>(__r) { } weak_ptr(const weak_ptr&) noexcept = default; - template> - weak_ptr(const weak_ptr<_Tp1>& __r) noexcept + template&>> + weak_ptr(const weak_ptr<_Yp>& __r) noexcept : __weak_ptr<_Tp>(__r) { } weak_ptr(weak_ptr&&) noexcept = default; - template> - weak_ptr(weak_ptr<_Tp1>&& __r) noexcept + template>> + weak_ptr(weak_ptr<_Yp>&& __r) noexcept : __weak_ptr<_Tp>(std::move(__r)) { } weak_ptr& operator=(const weak_ptr& __r) noexcept = default; - template - weak_ptr& - operator=(const weak_ptr<_Tp1>& __r) noexcept + template + _Assignable&> + operator=(const weak_ptr<_Yp>& __r) noexcept { this->__weak_ptr<_Tp>::operator=(__r); return *this; } - template - weak_ptr& - operator=(const shared_ptr<_Tp1>& __r) noexcept + template + _Assignable&> + operator=(const shared_ptr<_Yp>& __r) noexcept { this->__weak_ptr<_Tp>::operator=(__r); return *this; @@ -523,9 +554,9 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION weak_ptr& operator=(weak_ptr&& __r) noexcept = default; - template - weak_ptr& - operator=(weak_ptr<_Tp1>&& __r) noexcept + template + _Assignable> + operator=(weak_ptr<_Yp>&& __r) noexcept { this->__weak_ptr<_Tp>::operator=(std::move(__r)); return *this; diff --git a/libstdc++-v3/include/bits/shared_ptr_base.h b/libstdc++-v3/include/bits/shared_ptr_base.h index c0686ad95da..c74c92ae730 100644 --- a/libstdc++-v3/include/bits/shared_ptr_base.h +++ b/libstdc++-v3/include/bits/shared_ptr_base.h @@ -847,19 +847,55 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION _M_pi = nullptr; } + // Helper traits for shared_ptr + + template + struct __sp_compatible_with + : false_type + { }; + + template + struct __sp_compatible_with<_Yp*, _Tp*> + : is_convertible<_Yp*, _Tp*>::type + { }; + template class __shared_ptr { - template - using _Convertible - = typename enable_if::value>::type; + public: + using element_type = _Tp; - template - using _Assignable = typename - enable_if::value, __shared_ptr&>::type; + private: + // Trait to check if shared_ptr can be constructed from Y*. + template + using __sp_is_constructible = is_convertible<_Yp*, _Tp1*>; + + // Constraint for taking ownership of a pointer of type _Yp*: + template + using _SafeConv + = typename enable_if<__sp_is_constructible<_Tp, _Yp>::value>::type; + + // Constraint for construction from shared_ptr and weak_ptr: + template + using _Compatible = typename + enable_if<__sp_compatible_with<_Yp*, _Tp*>::value, _Res>::type; + + // Constraint for assignment from shared_ptr and weak_ptr: + template + using _Assignable = _Compatible<_Yp, __shared_ptr&>; + + // Constraint for construction from unique_ptr: + template::pointer> + using _UniqCompatible = typename enable_if< + is_convertible<_Ptr, element_type*>::value + , _Res>::type; + + // Constraint for assignment from unique_ptr: + template + using _UniqAssignable = _UniqCompatible<_Yp, _Del, __shared_ptr&>; public: - typedef _Tp element_type; #if __cplusplus > 201402L using weak_type = __weak_ptr<_Tp, _Lp>; @@ -869,31 +905,32 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION : _M_ptr(0), _M_refcount() { } - template - explicit __shared_ptr(_Tp1* __p) - : _M_ptr(__p), _M_refcount(__p) + template> + explicit + __shared_ptr(_Yp* __p) + : _M_ptr(__p), _M_refcount(__p) { - __glibcxx_function_requires(_ConvertibleConcept<_Tp1*, _Tp*>) - static_assert( !is_void<_Tp1>::value, "incomplete type" ); - static_assert( sizeof(_Tp1) > 0, "incomplete type" ); + static_assert( !is_void<_Yp>::value, "incomplete type" ); + static_assert( sizeof(_Yp) > 0, "incomplete type" ); _M_enable_shared_from_this_with(__p); } - template - __shared_ptr(_Tp1* __p, _Deleter __d) + template> + __shared_ptr(_Yp* __p, _Deleter __d) : _M_ptr(__p), _M_refcount(__p, __d) { - __glibcxx_function_requires(_ConvertibleConcept<_Tp1*, _Tp*>) - // TODO requires _Deleter CopyConstructible and __d(__p) well-formed + static_assert(__is_callable<_Deleter(_Yp*)>::value, + "deleter expression d(p) is well-formed"); _M_enable_shared_from_this_with(__p); } - template - __shared_ptr(_Tp1* __p, _Deleter __d, _Alloc __a) + template> + __shared_ptr(_Yp* __p, _Deleter __d, _Alloc __a) : _M_ptr(__p), _M_refcount(__p, __d, std::move(__a)) { - __glibcxx_function_requires(_ConvertibleConcept<_Tp1*, _Tp*>) - // TODO requires _Deleter CopyConstructible and __d(__p) well-formed + static_assert(__is_callable<_Deleter(_Yp*)>::value, + "deleter expression d(p) is well-formed"); _M_enable_shared_from_this_with(__p); } @@ -907,8 +944,9 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION : _M_ptr(0), _M_refcount(__p, __d, std::move(__a)) { } - template - __shared_ptr(const __shared_ptr<_Tp1, _Lp>& __r, _Tp* __p) noexcept + template + __shared_ptr(const __shared_ptr<_Yp, _Lp>& __r, + element_type* __p) noexcept : _M_ptr(__p), _M_refcount(__r._M_refcount) // never throws { } @@ -916,8 +954,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION __shared_ptr& operator=(const __shared_ptr&) noexcept = default; ~__shared_ptr() = default; - template> - __shared_ptr(const __shared_ptr<_Tp1, _Lp>& __r) noexcept + template> + __shared_ptr(const __shared_ptr<_Yp, _Lp>& __r) noexcept : _M_ptr(__r._M_ptr), _M_refcount(__r._M_refcount) { } @@ -928,32 +966,29 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION __r._M_ptr = 0; } - template> - __shared_ptr(__shared_ptr<_Tp1, _Lp>&& __r) noexcept + template> + __shared_ptr(__shared_ptr<_Yp, _Lp>&& __r) noexcept : _M_ptr(__r._M_ptr), _M_refcount() { _M_refcount._M_swap(__r._M_refcount); __r._M_ptr = 0; } - template - explicit __shared_ptr(const __weak_ptr<_Tp1, _Lp>& __r) + template> + explicit __shared_ptr(const __weak_ptr<_Yp, _Lp>& __r) : _M_refcount(__r._M_refcount) // may throw { - __glibcxx_function_requires(_ConvertibleConcept<_Tp1*, _Tp*>) - // It is now safe to copy __r._M_ptr, as // _M_refcount(__r._M_refcount) did not throw. _M_ptr = __r._M_ptr; } // If an exception is thrown this constructor has no effect. - template::pointer>> - __shared_ptr(std::unique_ptr<_Tp1, _Del>&& __r) + template> + __shared_ptr(unique_ptr<_Yp, _Del>&& __r) : _M_ptr(__r.get()), _M_refcount() { - __glibcxx_function_requires(_ConvertibleConcept<_Tp1*, _Tp*>) auto __raw = _S_raw_ptr(__r.get()); _M_refcount = __shared_count<_Lp>(std::move(__r)); _M_enable_shared_from_this_with(__raw); @@ -961,15 +996,15 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION #if _GLIBCXX_USE_DEPRECATED // Postcondition: use_count() == 1 and __r.get() == 0 - template - __shared_ptr(std::auto_ptr<_Tp1>&& __r); + template> + __shared_ptr(auto_ptr<_Yp>&& __r); #endif constexpr __shared_ptr(nullptr_t) noexcept : __shared_ptr() { } - template - _Assignable<_Tp1*> - operator=(const __shared_ptr<_Tp1, _Lp>& __r) noexcept + template + _Assignable<_Yp> + operator=(const __shared_ptr<_Yp, _Lp>& __r) noexcept { _M_ptr = __r._M_ptr; _M_refcount = __r._M_refcount; // __shared_count::op= doesn't throw @@ -977,9 +1012,9 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION } #if _GLIBCXX_USE_DEPRECATED - template - __shared_ptr& - operator=(std::auto_ptr<_Tp1>&& __r) + template + _Assignable<_Yp> + operator=(auto_ptr<_Yp>&& __r) { __shared_ptr(std::move(__r)).swap(*this); return *this; @@ -993,17 +1028,17 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION return *this; } - template - _Assignable<_Tp1*> - operator=(__shared_ptr<_Tp1, _Lp>&& __r) noexcept + template + _Assignable<_Yp> + operator=(__shared_ptr<_Yp, _Lp>&& __r) noexcept { __shared_ptr(std::move(__r)).swap(*this); return *this; } - template - _Assignable::pointer> - operator=(std::unique_ptr<_Tp1, _Del>&& __r) + template + _UniqAssignable<_Yp, _Del> + operator=(unique_ptr<_Yp, _Del>&& __r) { __shared_ptr(std::move(__r)).swap(*this); return *this; @@ -1013,41 +1048,41 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION reset() noexcept { __shared_ptr().swap(*this); } - template - _Convertible<_Tp1*> - reset(_Tp1* __p) // _Tp1 must be complete. + template + _SafeConv<_Yp> + reset(_Yp* __p) // _Yp must be complete. { // Catch self-reset errors. __glibcxx_assert(__p == 0 || __p != _M_ptr); __shared_ptr(__p).swap(*this); } - template - _Convertible<_Tp1*> - reset(_Tp1* __p, _Deleter __d) + template + _SafeConv<_Yp> + reset(_Yp* __p, _Deleter __d) { __shared_ptr(__p, __d).swap(*this); } - template - _Convertible<_Tp1*> - reset(_Tp1* __p, _Deleter __d, _Alloc __a) + template + _SafeConv<_Yp> + reset(_Yp* __p, _Deleter __d, _Alloc __a) { __shared_ptr(__p, __d, std::move(__a)).swap(*this); } // Allow class instantiation when _Tp is [cv-qual] void. - typename std::add_lvalue_reference<_Tp>::type + typename std::add_lvalue_reference::type operator*() const noexcept { __glibcxx_assert(_M_ptr != 0); return *_M_ptr; } - _Tp* + element_type* operator->() const noexcept { _GLIBCXX_DEBUG_PEDASSERT(_M_ptr != 0); return _M_ptr; } - _Tp* + element_type* get() const noexcept { return _M_ptr; } @@ -1192,7 +1227,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION template friend _Del* get_deleter(const __shared_ptr<_Tp1, _Lp1>&) noexcept; - _Tp* _M_ptr; // Contained pointer. + element_type* _M_ptr; // Contained pointer. __shared_count<_Lp> _M_refcount; // Reference counter. }; @@ -1230,24 +1265,32 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION operator!=(nullptr_t, const __shared_ptr<_Tp, _Lp>& __a) noexcept { return (bool)__a; } - template + template inline bool - operator<(const __shared_ptr<_Tp1, _Lp>& __a, - const __shared_ptr<_Tp2, _Lp>& __b) noexcept + operator<(const __shared_ptr<_Tp, _Lp>& __a, + const __shared_ptr<_Up, _Lp>& __b) noexcept { - typedef typename std::common_type<_Tp1*, _Tp2*>::type _CT; - return std::less<_CT>()(__a.get(), __b.get()); + using _Tp_elt = typename __shared_ptr<_Tp, _Lp>::element_type; + using _Up_elt = typename __shared_ptr<_Up, _Lp>::element_type; + using _Vp = typename common_type<_Tp_elt*, _Up_elt*>::type; + return less<_Vp>()(__a.get(), __b.get()); } template inline bool operator<(const __shared_ptr<_Tp, _Lp>& __a, nullptr_t) noexcept - { return std::less<_Tp*>()(__a.get(), nullptr); } + { + using _Tp_elt = typename __shared_ptr<_Tp, _Lp>::element_type; + return less<_Tp_elt*>()(__a.get(), nullptr); + } template inline bool operator<(nullptr_t, const __shared_ptr<_Tp, _Lp>& __a) noexcept - { return std::less<_Tp*>()(nullptr, __a.get()); } + { + using _Tp_elt = typename __shared_ptr<_Tp, _Lp>::element_type; + return less<_Tp_elt*>()(nullptr, __a.get()); + } template inline bool @@ -1274,12 +1317,12 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION template inline bool operator>(const __shared_ptr<_Tp, _Lp>& __a, nullptr_t) noexcept - { return std::less<_Tp*>()(nullptr, __a.get()); } + { return nullptr < __a; } template inline bool operator>(nullptr_t, const __shared_ptr<_Tp, _Lp>& __a) noexcept - { return std::less<_Tp*>()(__a.get(), nullptr); } + { return __a < nullptr; } template inline bool @@ -1329,7 +1372,10 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION template inline __shared_ptr<_Tp, _Lp> static_pointer_cast(const __shared_ptr<_Tp1, _Lp>& __r) noexcept - { return __shared_ptr<_Tp, _Lp>(__r, static_cast<_Tp*>(__r.get())); } + { + using _Sp = __shared_ptr<_Tp, _Lp>; + return _Sp(__r, static_cast(__r.get())); + } // The seemingly equivalent code: // shared_ptr<_Tp, _Lp>(const_cast<_Tp*>(__r.get())) @@ -1339,7 +1385,10 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION template inline __shared_ptr<_Tp, _Lp> const_pointer_cast(const __shared_ptr<_Tp1, _Lp>& __r) noexcept - { return __shared_ptr<_Tp, _Lp>(__r, const_cast<_Tp*>(__r.get())); } + { + using _Sp = __shared_ptr<_Tp, _Lp>; + return _Sp(__r, const_cast(__r.get())); + } // The seemingly equivalent code: // shared_ptr<_Tp, _Lp>(dynamic_cast<_Tp*>(__r.get())) @@ -1350,21 +1399,35 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION inline __shared_ptr<_Tp, _Lp> dynamic_pointer_cast(const __shared_ptr<_Tp1, _Lp>& __r) noexcept { - if (_Tp* __p = dynamic_cast<_Tp*>(__r.get())) - return __shared_ptr<_Tp, _Lp>(__r, __p); - return __shared_ptr<_Tp, _Lp>(); + using _Sp = __shared_ptr<_Tp, _Lp>; + if (auto* __p = dynamic_cast(__r.get())) + return _Sp(__r, __p); + return _Sp(); } +#if __cplusplus > 201402L + template + inline __shared_ptr<_Tp, _Lp> + reinterpret_pointer_cast(const __shared_ptr<_Tp1, _Lp>& __r) noexcept + { + using _Sp = __shared_ptr<_Tp, _Lp>; + return _Sp(__r, reinterpret_cast(__r.get())); + } +#endif template class __weak_ptr { - template - using _Convertible - = typename enable_if::value>::type; + template + using _Compatible = typename + enable_if<__sp_compatible_with<_Yp*, _Tp*>::value, _Res>::type; + + // Constraint for assignment from shared_ptr and weak_ptr: + template + using _Assignable = _Compatible<_Yp, __weak_ptr&>; public: - typedef _Tp element_type; + using element_type = _Tp; constexpr __weak_ptr() noexcept : _M_ptr(nullptr), _M_refcount() @@ -1388,13 +1451,13 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION // // It is not possible to avoid spurious access violations since // in multithreaded programs __r._M_ptr may be invalidated at any point. - template> - __weak_ptr(const __weak_ptr<_Tp1, _Lp>& __r) noexcept + template> + __weak_ptr(const __weak_ptr<_Yp, _Lp>& __r) noexcept : _M_refcount(__r._M_refcount) { _M_ptr = __r.lock().get(); } - template> - __weak_ptr(const __shared_ptr<_Tp1, _Lp>& __r) noexcept + template> + __weak_ptr(const __shared_ptr<_Yp, _Lp>& __r) noexcept : _M_ptr(__r._M_ptr), _M_refcount(__r._M_refcount) { } @@ -1402,26 +1465,26 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION : _M_ptr(__r._M_ptr), _M_refcount(std::move(__r._M_refcount)) { __r._M_ptr = nullptr; } - template> - __weak_ptr(__weak_ptr<_Tp1, _Lp>&& __r) noexcept + template> + __weak_ptr(__weak_ptr<_Yp, _Lp>&& __r) noexcept : _M_ptr(__r.lock().get()), _M_refcount(std::move(__r._M_refcount)) { __r._M_ptr = nullptr; } __weak_ptr& operator=(const __weak_ptr& __r) noexcept = default; - template - __weak_ptr& - operator=(const __weak_ptr<_Tp1, _Lp>& __r) noexcept + template + _Assignable<_Yp> + operator=(const __weak_ptr<_Yp, _Lp>& __r) noexcept { _M_ptr = __r.lock().get(); _M_refcount = __r._M_refcount; return *this; } - template - __weak_ptr& - operator=(const __shared_ptr<_Tp1, _Lp>& __r) noexcept + template + _Assignable<_Yp> + operator=(const __shared_ptr<_Yp, _Lp>& __r) noexcept { _M_ptr = __r._M_ptr; _M_refcount = __r._M_refcount; @@ -1437,9 +1500,9 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION return *this; } - template - __weak_ptr& - operator=(__weak_ptr<_Tp1, _Lp>&& __r) noexcept + template + _Assignable<_Yp> + operator=(__weak_ptr<_Yp, _Lp>&& __r) noexcept { _M_ptr = __r.lock().get(); _M_refcount = std::move(__r._M_refcount); @@ -1497,7 +1560,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION friend class __enable_shared_from_this<_Tp, _Lp>; friend class enable_shared_from_this<_Tp>; - _Tp* _M_ptr; // Contained pointer. + element_type* _M_ptr; // Contained pointer. __weak_count<_Lp> _M_refcount; // Reference counter. }; diff --git a/libstdc++-v3/testsuite/20_util/shared_ptr/assign/auto_ptr_neg.cc b/libstdc++-v3/testsuite/20_util/shared_ptr/assign/auto_ptr_neg.cc index 56d818ec10a..0558cf4153f 100644 --- a/libstdc++-v3/testsuite/20_util/shared_ptr/assign/auto_ptr_neg.cc +++ b/libstdc++-v3/testsuite/20_util/shared_ptr/assign/auto_ptr_neg.cc @@ -34,7 +34,7 @@ test01() { std::shared_ptr a; std::auto_ptr b; - a = std::move(b); // { dg-error "here" } + a = std::move(b); // { dg-error "no match" } return 0; } diff --git a/libstdc++-v3/testsuite/20_util/shared_ptr/casts/reinterpret.cc b/libstdc++-v3/testsuite/20_util/shared_ptr/casts/reinterpret.cc new file mode 100644 index 00000000000..e519f0ed73e --- /dev/null +++ b/libstdc++-v3/testsuite/20_util/shared_ptr/casts/reinterpret.cc @@ -0,0 +1,42 @@ +// { dg-options "-std=gnu++17" } +// { dg-do compile { target c++1z } } + +// Copyright (C) 2016 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License along +// with this library; see the file COPYING3. If not see +// . + +// 20.11.2.2.9 shared_ptr casts [util.smartptr.shared.cast] + +#include +#include + +struct MyP { virtual ~MyP() { }; }; +struct MyDP : MyP { }; + +int main() +{ + using __gnu_test::check_ret_type; + using std::shared_ptr; + using std::reinterpret_pointer_cast; + + shared_ptr spd; + shared_ptr spci; + shared_ptr spa; + + check_ret_type >(reinterpret_pointer_cast(spd)); + check_ret_type >(reinterpret_pointer_cast(spci)); + check_ret_type >(reinterpret_pointer_cast(spa)); +} diff --git a/libstdc++-v3/testsuite/20_util/shared_ptr/cons/auto_ptr.cc b/libstdc++-v3/testsuite/20_util/shared_ptr/cons/auto_ptr.cc index 7a99490bcac..52481c122e2 100644 --- a/libstdc++-v3/testsuite/20_util/shared_ptr/cons/auto_ptr.cc +++ b/libstdc++-v3/testsuite/20_util/shared_ptr/cons/auto_ptr.cc @@ -25,10 +25,28 @@ struct A { }; +int destroyed = 0; +struct B : A { ~B() { ++destroyed; } }; + // 20.6.6.2.1 shared_ptr constructors [util.smartptr.shared.const] // Construction from auto_ptr -int + +template +constexpr bool constructible() +{ + using namespace std; + return is_constructible, auto_ptr>::value + && is_constructible, auto_ptr>::value + && is_constructible, auto_ptr>::value; +} + +static_assert( constructible< A, A >(), "A -> A compatible" ); +static_assert( constructible< B, A >(), "B -> A compatible" ); +static_assert( constructible< int, int >(), "int -> int compatible" ); +static_assert( !constructible< int, long >(), "int -> long not compatible" ); + +void test01() { std::auto_ptr a(new A); @@ -36,13 +54,24 @@ test01() VERIFY( a.get() == 0 ); VERIFY( a2.get() != 0 ); VERIFY( a2.use_count() == 1 ); +} - return 0; +void +test02() +{ + std::auto_ptr b(new B); + std::shared_ptr a(std::move(b)); + VERIFY( b.get() == 0 ); + VERIFY( a.get() != 0 ); + VERIFY( a.use_count() == 1 ); + a.reset(); + VERIFY( destroyed == 1 ); } int main() { test01(); + test02(); return 0; } diff --git a/libstdc++-v3/testsuite/20_util/shared_ptr/cons/unique_ptr.cc b/libstdc++-v3/testsuite/20_util/shared_ptr/cons/unique_ptr.cc index 18e66162754..52bbd3b0e46 100644 --- a/libstdc++-v3/testsuite/20_util/shared_ptr/cons/unique_ptr.cc +++ b/libstdc++-v3/testsuite/20_util/shared_ptr/cons/unique_ptr.cc @@ -24,10 +24,28 @@ struct A { }; +int destroyed = 0; +struct B : A { ~B() { ++destroyed; } }; + // 20.7.2.2.1 shared_ptr constructors [util.smartptr.shared.const] // Construction from unique_ptr -int + +template +constexpr bool constructible() +{ + using namespace std; + return is_constructible, unique_ptr>::value + && is_constructible, unique_ptr>::value + && is_constructible, unique_ptr>::value; +} + +static_assert( constructible< A, A >(), "A -> A compatible" ); +static_assert( constructible< B, A >(), "B -> A compatible" ); +static_assert( constructible< int, int >(), "int -> int compatible" ); +static_assert( !constructible< int, long >(), "int -> long not compatible" ); + +void test01() { std::unique_ptr up(new A); @@ -35,13 +53,24 @@ test01() VERIFY( up.get() == 0 ); VERIFY( sp.get() != 0 ); VERIFY( sp.use_count() == 1 ); +} - return 0; +void +test02() +{ + std::unique_ptr b(new B); + std::shared_ptr a(std::move(b)); + VERIFY( b.get() == 0 ); + VERIFY( a.get() != 0 ); + VERIFY( a.use_count() == 1 ); + a.reset(); + VERIFY( destroyed == 1 ); } int main() { test01(); + test02(); return 0; } diff --git a/libstdc++-v3/testsuite/20_util/shared_ptr/cons/void_neg.cc b/libstdc++-v3/testsuite/20_util/shared_ptr/cons/void_neg.cc index 0cadf25bffb..ba286449912 100644 --- a/libstdc++-v3/testsuite/20_util/shared_ptr/cons/void_neg.cc +++ b/libstdc++-v3/testsuite/20_util/shared_ptr/cons/void_neg.cc @@ -26,3 +26,7 @@ void test01() std::shared_ptr p((void*)nullptr); // { dg-error "here" } // { dg-error "incomplete" "" { target *-*-* } 0 } } + +using std::shared_ptr; +using std::is_constructible; +static_assert(!is_constructible, const void*>::value, "");