From fb3fc4bded8d934b603a7f07ab3cfe3b644ee971 Mon Sep 17 00:00:00 2001 From: Jonathan Wakely Date: Thu, 23 May 2019 22:41:02 +0100 Subject: LWG 2996 add rvalue overloads for shared_ptr aliasing and casting * doc/xml/manual/intro.xml: Document LWG DR 2996 change. * doc/html/*: Regenerate. * include/bits/shared_ptr.h (shared_ptr(shared_ptr&&, T*)): Add rvalue aliasing constructor. (static_pointer_cast, const_pointer, dynamic_pointer_cast) (reinterpret_pointer_cast): Add overloads taking rvalues. * include/bits/shared_ptr_base.h (__shared_ptr(__shared_ptr&&, T*)): Add rvalue aliasing constructor. * testsuite/20_util/shared_ptr/casts/1.cc: Change "compile" test to "run" and check return values as well as types. * testsuite/20_util/shared_ptr/casts/reinterpret.cc: Likewise. * testsuite/20_util/shared_ptr/casts/rval.cc: New test. * testsuite/20_util/shared_ptr/cons/alias-rval.cc: New test. * testsuite/20_util/shared_ptr/cons/alias.cc: Remove unused return values. From-SVN: r271583 --- libstdc++-v3/include/bits/shared_ptr.h | 93 ++++++++++++++++++++++++++--- libstdc++-v3/include/bits/shared_ptr_base.h | 11 ++++ 2 files changed, 95 insertions(+), 9 deletions(-) (limited to 'libstdc++-v3/include') diff --git a/libstdc++-v3/include/bits/shared_ptr.h b/libstdc++-v3/include/bits/shared_ptr.h index 8f219e7..41f6b12 100644 --- a/libstdc++-v3/include/bits/shared_ptr.h +++ b/libstdc++-v3/include/bits/shared_ptr.h @@ -235,17 +235,19 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION // Aliasing constructor /** - * @brief Constructs a %shared_ptr instance that stores @a __p - * and shares ownership with @a __r. - * @param __r A %shared_ptr. - * @param __p A pointer that will remain valid while @a *__r is valid. - * @post get() == __p && use_count() == __r.use_count() + * @brief Constructs a `shared_ptr` instance that stores `__p` + * and shares ownership with `__r`. + * @param __r A `shared_ptr`. + * @param __p A pointer that will remain valid while `*__r` is valid. + * @post `get() == __p && use_count() == __r.use_count()` * - * This can be used to construct a @c shared_ptr to a sub-object - * of an object managed by an existing @c shared_ptr. + * This can be used to construct a `shared_ptr` to a sub-object + * of an object managed by an existing `shared_ptr`. The complete + * object will remain valid while any `shared_ptr` owns it, even + * if they don't store a pointer to the complete object. * * @code - * shared_ptr< pair > pii(new pair()); + * shared_ptr> pii(new pair()); * shared_ptr pi(pii, &pii->first); * assert(pii.use_count() == 2); * @endcode @@ -254,6 +256,33 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION shared_ptr(const shared_ptr<_Yp>& __r, element_type* __p) noexcept : __shared_ptr<_Tp>(__r, __p) { } +#if __cplusplus > 201703L + // _GLIBCXX_RESOLVE_LIB_DEFECTS + // 2996. Missing rvalue overloads for shared_ptr operations + /** + * @brief Constructs a `shared_ptr` instance that stores `__p` + * and shares ownership with `__r`. + * @param __r A `shared_ptr`. + * @param __p A pointer that will remain valid while `*__r` is valid. + * @post `get() == __p && !__r.use_count() && !__r.get()` + * + * This can be used to construct a `shared_ptr` to a sub-object + * of an object managed by an existing `shared_ptr`. The complete + * object will remain valid while any `shared_ptr` owns it, even + * if they don't store a pointer to the complete object. + * + * @code + * shared_ptr> pii(new pair()); + * shared_ptr pi1(pii, &pii->first); + * assert(pii.use_count() == 2); + * shared_ptr pi2(std::move(pii), &pii->second); + * assert(pii.use_count() == 0); + * @endcode + */ + template + shared_ptr(shared_ptr<_Yp>&& __r, element_type* __p) noexcept + : __shared_ptr<_Tp>(std::move(__r), __p) { } +#endif /** * @brief If @a __r is empty, constructs an empty %shared_ptr; * otherwise construct a %shared_ptr that shares ownership @@ -568,7 +597,53 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION using _Sp = shared_ptr<_Tp>; return _Sp(__r, reinterpret_cast(__r.get())); } -#endif + +#if __cplusplus > 201703L + // _GLIBCXX_RESOLVE_LIB_DEFECTS + // 2996. Missing rvalue overloads for shared_ptr operations + + /// Convert type of `shared_ptr` rvalue, via `static_cast` + template + inline shared_ptr<_Tp> + static_pointer_cast(shared_ptr<_Up>&& __r) noexcept + { + using _Sp = shared_ptr<_Tp>; + return _Sp(std::move(__r), + static_cast(__r.get())); + } + + /// Convert type of `shared_ptr` rvalue, via `const_cast` + template + inline shared_ptr<_Tp> + const_pointer_cast(shared_ptr<_Up>&& __r) noexcept + { + using _Sp = shared_ptr<_Tp>; + return _Sp(std::move(__r), + const_cast(__r.get())); + } + + /// Convert type of `shared_ptr` rvalue, via `dynamic_cast` + template + inline shared_ptr<_Tp> + dynamic_pointer_cast(shared_ptr<_Up>&& __r) noexcept + { + using _Sp = shared_ptr<_Tp>; + if (auto* __p = dynamic_cast(__r.get())) + return _Sp(std::move(__r), __p); + return _Sp(); + } + + /// Convert type of `shared_ptr` rvalue, via `reinterpret_cast` + template + inline shared_ptr<_Tp> + reinterpret_pointer_cast(shared_ptr<_Up>&& __r) noexcept + { + using _Sp = shared_ptr<_Tp>; + return _Sp(std::move(__r), + reinterpret_cast(__r.get())); + } +#endif // C++20 +#endif // C++17 // @} diff --git a/libstdc++-v3/include/bits/shared_ptr_base.h b/libstdc++-v3/include/bits/shared_ptr_base.h index 968cc96..4acec1c 100644 --- a/libstdc++-v3/include/bits/shared_ptr_base.h +++ b/libstdc++-v3/include/bits/shared_ptr_base.h @@ -1158,12 +1158,23 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION : _M_ptr(0), _M_refcount(__p, std::move(__d), std::move(__a)) { } + // Aliasing constructor template __shared_ptr(const __shared_ptr<_Yp, _Lp>& __r, element_type* __p) noexcept : _M_ptr(__p), _M_refcount(__r._M_refcount) // never throws { } + // Aliasing constructor + template + __shared_ptr(__shared_ptr<_Yp, _Lp>&& __r, + element_type* __p) noexcept + : _M_ptr(__p), _M_refcount() + { + _M_refcount._M_swap(__r._M_refcount); + __r._M_ptr = 0; + } + __shared_ptr(const __shared_ptr&) noexcept = default; __shared_ptr& operator=(const __shared_ptr&) noexcept = default; ~__shared_ptr() = default; -- cgit v1.1