* 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
2019-05-23 Jonathan Wakely <jwakely@redhat.com>
+ * 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.
+
* doc/xml/manual/evolution.xml: Document LWG DR 2921 change.
* doc/xml/manual/intro.xml: Likewise.
* include/std/future (__create_task_state): Add default arguments
<code class="filename"><experimental/timer></code>.
</p></div><div class="section"><div class="titlepage"><div><div><h3 class="title"><a id="api.rel_101"></a><code class="constant">10</code></h3></div></div></div><p> Deprecated features removed:
</p><div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; "><li class="listitem"> Profile Mode </li><li class="listitem"><code class="classname">__gnu_cxx::array_allocator</code></li></ul></div><p>
+</p><p>
+ The <code class="classname">std::packaged_task</code> constructors taking
+ an allocator argument are only defined for C++11 and C++14.
</p></div></div><div class="navfooter"><hr /><table width="100%" summary="Navigation footer"><tr><td width="40%" align="left"><a accesskey="p" href="abi.html">Prev</a> </td><td width="20%" align="center"><a accesskey="u" href="appendix_porting.html">Up</a></td><td width="40%" align="right"> <a accesskey="n" href="backwards.html">Next</a></td></tr><tr><td width="40%" align="left" valign="top">ABI Policy and Guidelines </td><td width="20%" align="center"><a accesskey="h" href="../index.html">Home</a></td><td width="40%" align="right" valign="top"> Backwards Compatibility</td></tr></table></div></body></html>
\ No newline at end of file
<span class="emphasis"><em><code class="code">shared_ptr</code> constructor requirements for a deleter
</em></span>
</span></dt><dd><p>Use rvalues for deleters.
+ </p></dd><dt><a id="manual.bugs.dr2921"></a><span class="term"><a class="link" href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#2921" target="_top">2921</a>:
+ <span class="emphasis"><em><code class="code">packaged_task</code> and type-erased allocators
+ </em></span>
+ </span></dt><dd><p>For C++17 mode, remove the constructors taking
+ an allocator argument.
</p></dd><dt><a id="manual.bugs.dr2942"></a><span class="term"><a class="link" href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#2942" target="_top">2942</a>:
<span class="emphasis"><em>LWG 2873's resolution missed
<code class="code">weak_ptr::owner_before</code>
</em></span>
</span></dt><dd><p>Add noexcept.
+ </p></dd><dt><a id="manual.bugs.dr2996"></a><span class="term"><a class="link" href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#2996" target="_top">2996</a>:
+ <span class="emphasis"><em>Missing rvalue overloads for
+ <code class="code">shared_ptr</code> operations
+ </em></span>
+ </span></dt><dd><p>Add additional constructor and cast overloads.
</p></dd><dt><a id="manual.bugs.dr2993"></a><span class="term"><a class="link" href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#2993" target="_top">2993</a>:
<span class="emphasis"><em><code class="code">reference_wrapper<T></code> conversion from <code class="code">T&&</code>
</em></span>
<listitem><para>Add noexcept.
</para></listitem></varlistentry>
+ <varlistentry xml:id="manual.bugs.dr2996"><term><link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="&DR;#2996">2996</link>:
+ <emphasis>Missing rvalue overloads for
+ <code>shared_ptr</code> operations
+ </emphasis>
+ </term>
+ <listitem><para>Add additional constructor and cast overloads.
+ </para></listitem></varlistentry>
+
<varlistentry xml:id="manual.bugs.dr2993"><term><link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="&DR;#2993">2993</link>:
<emphasis><code>reference_wrapper<T></code> conversion from <code>T&&</code>
</emphasis>
// 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<int,int> > pii(new pair<int,int>());
+ * shared_ptr<pair<int,int>> pii(new pair<int,int>());
* shared_ptr<int> pi(pii, &pii->first);
* assert(pii.use_count() == 2);
* @endcode
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<pair<int,int>> pii(new pair<int,int>());
+ * shared_ptr<int> pi1(pii, &pii->first);
+ * assert(pii.use_count() == 2);
+ * shared_ptr<int> pi2(std::move(pii), &pii->second);
+ * assert(pii.use_count() == 0);
+ * @endcode
+ */
+ template<typename _Yp>
+ 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
using _Sp = shared_ptr<_Tp>;
return _Sp(__r, reinterpret_cast<typename _Sp::element_type*>(__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<typename _Tp, typename _Up>
+ inline shared_ptr<_Tp>
+ static_pointer_cast(shared_ptr<_Up>&& __r) noexcept
+ {
+ using _Sp = shared_ptr<_Tp>;
+ return _Sp(std::move(__r),
+ static_cast<typename _Sp::element_type*>(__r.get()));
+ }
+
+ /// Convert type of `shared_ptr` rvalue, via `const_cast`
+ template<typename _Tp, typename _Up>
+ inline shared_ptr<_Tp>
+ const_pointer_cast(shared_ptr<_Up>&& __r) noexcept
+ {
+ using _Sp = shared_ptr<_Tp>;
+ return _Sp(std::move(__r),
+ const_cast<typename _Sp::element_type*>(__r.get()));
+ }
+
+ /// Convert type of `shared_ptr` rvalue, via `dynamic_cast`
+ template<typename _Tp, typename _Up>
+ inline shared_ptr<_Tp>
+ dynamic_pointer_cast(shared_ptr<_Up>&& __r) noexcept
+ {
+ using _Sp = shared_ptr<_Tp>;
+ if (auto* __p = dynamic_cast<typename _Sp::element_type*>(__r.get()))
+ return _Sp(std::move(__r), __p);
+ return _Sp();
+ }
+
+ /// Convert type of `shared_ptr` rvalue, via `reinterpret_cast`
+ template<typename _Tp, typename _Up>
+ inline shared_ptr<_Tp>
+ reinterpret_pointer_cast(shared_ptr<_Up>&& __r) noexcept
+ {
+ using _Sp = shared_ptr<_Tp>;
+ return _Sp(std::move(__r),
+ reinterpret_cast<typename _Sp::element_type*>(__r.get()));
+ }
+#endif // C++20
+#endif // C++17
// @}
: _M_ptr(0), _M_refcount(__p, std::move(__d), std::move(__a))
{ }
+ // Aliasing constructor
template<typename _Yp>
__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<typename _Yp>
+ __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;
-// { dg-do compile { target c++11 } }
+// { dg-do run { target c++11 } }
// Copyright (C) 2006-2019 Free Software Foundation, Inc.
//
// 20.6.6.2.10 shared_ptr casts [util.smartptr.shared.cast]
#include <memory>
+#include <testsuite_hooks.h>
#include <testsuite_tr1.h>
struct MyP { virtual ~MyP() { }; };
struct MyDP : MyP { };
-int main()
+void
+test01()
{
using __gnu_test::check_ret_type;
using std::shared_ptr;
shared_ptr<const int> spci;
shared_ptr<MyP> spa;
- check_ret_type<shared_ptr<void> >(static_pointer_cast<void>(spd));
- check_ret_type<shared_ptr<int> >(const_pointer_cast<int>(spci));
- check_ret_type<shared_ptr<MyDP> >(static_pointer_cast<MyDP>(spa));
+ check_ret_type<shared_ptr<void>>(static_pointer_cast<void>(spd));
+ check_ret_type<shared_ptr<int>>(const_pointer_cast<int>(spci));
+ check_ret_type<shared_ptr<MyDP>>(dynamic_pointer_cast<MyDP>(spa));
+}
+
+void
+test02()
+{
+ using std::shared_ptr;
+ using std::static_pointer_cast;
+ using std::const_pointer_cast;
+ using std::dynamic_pointer_cast;
+
+ int* ptr = new int(1);
+ shared_ptr<const void> pcv(ptr);
+ auto pci = static_pointer_cast<const int>(pcv);
+ VERIFY(pci.use_count() == 2);
+ VERIFY(pcv.use_count() == 2);
+ VERIFY(pci.get() == ptr);
+ VERIFY(pcv.get() == ptr);
+ auto pi = const_pointer_cast<int>(pci);
+ VERIFY(pi.use_count() == 3);
+ VERIFY(pcv.use_count() == 3);
+ VERIFY(pi.get() == ptr);
+ VERIFY(pci.get() == ptr);
+
+ MyP* pptr = new MyP;
+ shared_ptr<MyP> pp(pptr);
+ auto pdp = dynamic_pointer_cast<MyDP>(pp);
+ VERIFY(pp.use_count() == 1);
+ VERIFY(pdp.use_count() == 0);
+ VERIFY(pdp.get() == nullptr);
+ VERIFY(pp.get() == pptr);
+ pptr = new MyDP;
+ pp.reset(pptr);
+ pdp = dynamic_pointer_cast<MyDP>(pp);
+ VERIFY(pp.use_count() == 2);
+ VERIFY(pdp.use_count() == 2);
+ VERIFY(pdp.get() == pptr);
+ VERIFY(pp.get() == pptr);
+}
+
+int main()
+{
+ test01();
+ test02();
}
// { dg-options "-std=gnu++17" }
-// { dg-do compile { target c++17 } }
+// { dg-do run { target c++17 } }
// Copyright (C) 2016-2019 Free Software Foundation, Inc.
//
// 20.11.2.2.9 shared_ptr casts [util.smartptr.shared.cast]
#include <memory>
+#include <testsuite_hooks.h>
#include <testsuite_tr1.h>
struct MyP { virtual ~MyP() { }; };
struct MyDP : MyP { };
-int main()
+void
+test01()
{
using __gnu_test::check_ret_type;
using std::shared_ptr;
shared_ptr<const int> spci;
shared_ptr<MyP> spa;
- check_ret_type<shared_ptr<void> >(reinterpret_pointer_cast<void>(spd));
- check_ret_type<shared_ptr<const short> >(reinterpret_pointer_cast<const short>(spci));
- check_ret_type<shared_ptr<MyDP> >(reinterpret_pointer_cast<MyDP>(spa));
+ check_ret_type<shared_ptr<void>>(reinterpret_pointer_cast<void>(spd));
+ check_ret_type<shared_ptr<const short>>(reinterpret_pointer_cast<const short>(spci));
+ check_ret_type<shared_ptr<MyDP>>(reinterpret_pointer_cast<MyDP>(spa));
+}
+
+void
+test02()
+{
+ using std::shared_ptr;
+ using std::reinterpret_pointer_cast;
+
+ int* ptr = new int(2);
+ shared_ptr<int> pi(ptr);
+ auto pl = reinterpret_pointer_cast<long>(pi);
+ VERIFY(pi.use_count() == 2);
+ VERIFY(pl.use_count() == 2);
+ VERIFY(pi.get() == ptr);
+ VERIFY(reinterpret_cast<int*>(pl.get()) == ptr);
+}
+
+int main()
+{
+ test01();
+ test02();
}
--- /dev/null
+// { dg-options "-std=gnu++2a" }
+// { dg-do run { target c++2a } }
+
+// Copyright (C) 2019 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
+// <http://www.gnu.org/licenses/>.
+
+// shared_ptr casts [util.smartptr.shared.cast]
+
+#include <memory>
+#include <testsuite_hooks.h>
+#include <testsuite_tr1.h>
+
+struct MyP { virtual ~MyP() { }; };
+struct MyDP : MyP { };
+
+void test01()
+{
+ using __gnu_test::check_ret_type;
+ using std::shared_ptr;
+ using std::static_pointer_cast;
+ using std::const_pointer_cast;
+ using std::dynamic_pointer_cast;
+ using std::reinterpret_pointer_cast;
+
+ shared_ptr<double> spd;
+ shared_ptr<const int> spci;
+ shared_ptr<MyP> spa;
+
+ check_ret_type<shared_ptr<void>>(static_pointer_cast<void>(std::move(spd)));
+ check_ret_type<shared_ptr<int>>(const_pointer_cast<int>(std::move(spci)));
+ check_ret_type<shared_ptr<MyDP>>(dynamic_pointer_cast<MyDP>(std::move(spa)));
+ check_ret_type<shared_ptr<void>>(reinterpret_pointer_cast<void>(std::move(spd)));
+ check_ret_type<shared_ptr<const short>>(reinterpret_pointer_cast<const short>(std::move(spci)));
+ check_ret_type<shared_ptr<MyDP>>(reinterpret_pointer_cast<MyDP>(std::move(spa)));
+}
+
+void
+test02()
+{
+ using std::shared_ptr;
+ using std::static_pointer_cast;
+ using std::const_pointer_cast;
+ using std::dynamic_pointer_cast;
+ using std::reinterpret_pointer_cast;
+
+ int* ptr = new int(1);
+ shared_ptr<const void> pcv(ptr);
+ auto pci = static_pointer_cast<const int>(std::move(pcv));
+ VERIFY(pci.use_count() == 1);
+ VERIFY(pcv.use_count() == 0);
+ VERIFY(pci.get() == ptr);
+ VERIFY(pcv.get() == nullptr);
+ auto pi = const_pointer_cast<int>(std::move(pci));
+ VERIFY(pi.use_count() == 1);
+ VERIFY(pci.use_count() == 0);
+ VERIFY(pi.get() == ptr);
+ VERIFY(pci.get() == nullptr);
+
+ MyP* pptr = new MyP;
+ shared_ptr<MyP> pp(pptr);
+ auto pdp = dynamic_pointer_cast<MyDP>(std::move(pp));
+ VERIFY(pdp.use_count() == 0);
+ VERIFY(pp.use_count() == 1);
+ VERIFY(pdp.get() == nullptr);
+ VERIFY(pp.get() == pptr);
+ pptr = new MyDP;
+ pp.reset(pptr);
+ pdp = dynamic_pointer_cast<MyDP>(std::move(pp));
+ VERIFY(pdp.use_count() == 1);
+ VERIFY(pp.use_count() == 0);
+ VERIFY(pdp.get() == pptr);
+ VERIFY(pp.get() == nullptr);
+
+ ptr = new int(2);
+ pi.reset(ptr);
+ auto pl = reinterpret_pointer_cast<long>(std::move(pi));
+ VERIFY(pl.use_count() == 1);
+ VERIFY(pi.use_count() == 0);
+ VERIFY(reinterpret_cast<int*>(pl.get()) == ptr);
+ VERIFY(pi.get() == nullptr);
+}
+
+int main()
+{
+ test01();
+ test02();
+}
--- /dev/null
+// { dg-options "-std=gnu++2a" }
+// { dg-do run { target c++2a } }
+
+// Copyright (C) 2019 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
+// <http://www.gnu.org/licenses/>.
+
+// Template class shared_ptr [util.smartptr.shared]
+
+#include <memory>
+#include <testsuite_hooks.h>
+
+struct A
+{
+ A() : i() { }
+ virtual ~A() { }
+ int i;
+};
+
+struct B : A
+{
+ B() : A(), a() { }
+ virtual ~B() { }
+ A a;
+};
+
+void deletefunc(A* p) { delete p; }
+
+// 20.6.6.2.1 shared_ptr constructors [util.smartptr.shared.const]
+
+// Aliasing constructors
+
+void
+test01()
+{
+ bool test = true;
+
+ std::shared_ptr<A> a;
+ std::shared_ptr<bool> b1(std::move(a), &test);
+ VERIFY( b1.use_count() == 0 );
+ VERIFY( b1.get() == &test );
+ VERIFY( a.use_count() == 0 );
+ VERIFY( a == nullptr );
+
+ std::shared_ptr<bool> b2(b1);
+ VERIFY( b2.use_count() == 0 );
+ VERIFY( b1 == b2 );
+}
+
+void
+test02()
+{
+ std::shared_ptr<A> a(new A);
+ std::shared_ptr<int> i1(std::move(a), &a->i);
+ VERIFY( i1.use_count() == 1 );
+ VERIFY( i1 != nullptr );
+ VERIFY( a.use_count() == 0 );
+ VERIFY( a == nullptr );
+
+ std::shared_ptr<int> i2(i1);
+ VERIFY( i2.use_count() == 2 );
+ VERIFY( i2.get() == &a->i );
+}
+
+void
+test03()
+{
+ std::shared_ptr<B> b1(new B);
+ std::shared_ptr<B> b2(b1);
+ std::shared_ptr<A> a1(std::move(b1), b1.get());
+ std::shared_ptr<A> a2(b2, &b2->a);
+ VERIFY( a2.use_count() == 2 );
+ VERIFY( a1 != nullptr );
+ VERIFY( a2 != nullptr );
+ VERIFY( a1 != a2 );
+ VERIFY( b1.use_count() == 0 );
+ VERIFY( b2.use_count() == 0 );
+ VERIFY( b1 == nullptr );
+ VERIFY( b2 == nullptr );
+}
+
+int
+main()
+{
+ test01();
+ test02();
+ test03();
+}
// Aliasing constructors
-int test01()
+void
+test01()
{
bool test = true;
std::shared_ptr<bool> b2(b1);
VERIFY( b2.use_count() == 0 );
VERIFY( b1.get() == b2.get() );
-
- return 0;
}
-int
+void
test02()
{
std::shared_ptr<A> a(new A);
std::shared_ptr<int> i2(i1);
VERIFY( i2.use_count() == 3 );
VERIFY( i2.get() == &a->i );
-
- return 0;
}
-int
+void
test03()
{
std::shared_ptr<B> b(new B);
a3 = a2;
VERIFY( a3.get() == &b->a );
-
- return 0;
}
int
test01();
test02();
test03();
- return 0;
}