Support move-only deleters in std::shared_ptr (LWG 2802)
* doc/xml/manual/intro.xml: Document LWG 2802, 2873 and 2942 changes. * include/bits/shared_ptr.h (shared_ptr): Use rvalues for deleters (LWG 2802). * include/bits/shared_ptr_base.h (_Sp_ebo_helper, _Sp_counted_deleter (_Sp_counted_deleter::_Impl, __shared_count, __shared_ptr): Likewise. * testsuite/20_util/shared_ptr/cons/lwg2802.cc: New. From-SVN: r249061
This commit is contained in:
parent
37f30285a9
commit
53d01fd9e9
5 changed files with 96 additions and 13 deletions
|
@ -1,5 +1,12 @@
|
|||
2017-06-09 Jonathan Wakely <jwakely@redhat.com>
|
||||
|
||||
* doc/xml/manual/intro.xml: Document LWG 2802, 2873 and 2942 changes.
|
||||
* include/bits/shared_ptr.h (shared_ptr): Use rvalues for deleters
|
||||
(LWG 2802).
|
||||
* include/bits/shared_ptr_base.h (_Sp_ebo_helper, _Sp_counted_deleter
|
||||
(_Sp_counted_deleter::_Impl, __shared_count, __shared_ptr): Likewise.
|
||||
* testsuite/20_util/shared_ptr/cons/lwg2802.cc: New.
|
||||
|
||||
* include/bits/forward_list.h (forward_list): Add deduction guide.
|
||||
* include/bits/stl_deque.h (deque): Likewise.
|
||||
* include/bits/stl_list.h (list): Likewise.
|
||||
|
|
|
@ -1119,6 +1119,29 @@ requirements of the license of GCC.
|
|||
arguments and store them directly as the target object.
|
||||
</para></listitem></varlistentry>
|
||||
|
||||
<varlistentry><term><link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="&DR;#2802">2802</link>:
|
||||
<emphasis>Add noexcept to several <code>shared_ptr</code> related
|
||||
functions
|
||||
</emphasis>
|
||||
</term>
|
||||
<listitem><para>Add noexcept.
|
||||
</para></listitem></varlistentry>
|
||||
|
||||
<varlistentry><term><link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="&DR;#2873">2873</link>:
|
||||
<emphasis><code>shared_ptr</code> constructor requirements for a deleter
|
||||
</emphasis>
|
||||
</term>
|
||||
<listitem><para>Use rvalues for deleters.
|
||||
</para></listitem></varlistentry>
|
||||
|
||||
<varlistentry><term><link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="&DR;#2942">2942</link>:
|
||||
<emphasis>LWG 2873's resolution missed
|
||||
<code>weak_ptr::owner_before</code>
|
||||
</emphasis>
|
||||
</term>
|
||||
<listitem><para>Add noexcept.
|
||||
</para></listitem></varlistentry>
|
||||
|
||||
</variablelist>
|
||||
|
||||
</section>
|
||||
|
|
|
@ -144,7 +144,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
|
|||
template<typename _Yp, typename _Deleter,
|
||||
typename = _Constructible<_Yp*, _Deleter>>
|
||||
shared_ptr(_Yp* __p, _Deleter __d)
|
||||
: __shared_ptr<_Tp>(__p, __d) { }
|
||||
: __shared_ptr<_Tp>(__p, std::move(__d)) { }
|
||||
|
||||
/**
|
||||
* @brief Construct a %shared_ptr that owns a null pointer
|
||||
|
@ -161,7 +161,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
|
|||
*/
|
||||
template<typename _Deleter>
|
||||
shared_ptr(nullptr_t __p, _Deleter __d)
|
||||
: __shared_ptr<_Tp>(__p, __d) { }
|
||||
: __shared_ptr<_Tp>(__p, std::move(__d)) { }
|
||||
|
||||
/**
|
||||
* @brief Construct a %shared_ptr that owns the pointer @a __p
|
||||
|
@ -181,7 +181,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
|
|||
template<typename _Yp, typename _Deleter, typename _Alloc,
|
||||
typename = _Constructible<_Yp*, _Deleter, _Alloc>>
|
||||
shared_ptr(_Yp* __p, _Deleter __d, _Alloc __a)
|
||||
: __shared_ptr<_Tp>(__p, __d, std::move(__a)) { }
|
||||
: __shared_ptr<_Tp>(__p, std::move(__d), std::move(__a)) { }
|
||||
|
||||
/**
|
||||
* @brief Construct a %shared_ptr that owns a null pointer
|
||||
|
@ -200,7 +200,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
|
|||
*/
|
||||
template<typename _Deleter, typename _Alloc>
|
||||
shared_ptr(nullptr_t __p, _Deleter __d, _Alloc __a)
|
||||
: __shared_ptr<_Tp>(__p, __d, std::move(__a)) { }
|
||||
: __shared_ptr<_Tp>(__p, std::move(__d), std::move(__a)) { }
|
||||
|
||||
// Aliasing constructor
|
||||
|
||||
|
|
|
@ -418,6 +418,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
|
|||
struct _Sp_ebo_helper<_Nm, _Tp, true> : private _Tp
|
||||
{
|
||||
explicit _Sp_ebo_helper(const _Tp& __tp) : _Tp(__tp) { }
|
||||
explicit _Sp_ebo_helper(_Tp&& __tp) : _Tp(std::move(__tp)) { }
|
||||
|
||||
static _Tp&
|
||||
_S_get(_Sp_ebo_helper& __eboh) { return static_cast<_Tp&>(__eboh); }
|
||||
|
@ -428,6 +429,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
|
|||
struct _Sp_ebo_helper<_Nm, _Tp, false>
|
||||
{
|
||||
explicit _Sp_ebo_helper(const _Tp& __tp) : _M_tp(__tp) { }
|
||||
explicit _Sp_ebo_helper(_Tp&& __tp) : _M_tp(std::move(__tp)) { }
|
||||
|
||||
static _Tp&
|
||||
_S_get(_Sp_ebo_helper& __eboh)
|
||||
|
@ -448,7 +450,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
|
|||
|
||||
public:
|
||||
_Impl(_Ptr __p, _Deleter __d, const _Alloc& __a) noexcept
|
||||
: _M_ptr(__p), _Del_base(__d), _Alloc_base(__a)
|
||||
: _M_ptr(__p), _Del_base(std::move(__d)), _Alloc_base(__a)
|
||||
{ }
|
||||
|
||||
_Deleter& _M_del() noexcept { return _Del_base::_S_get(*this); }
|
||||
|
@ -462,11 +464,11 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
|
|||
|
||||
// __d(__p) must not throw.
|
||||
_Sp_counted_deleter(_Ptr __p, _Deleter __d) noexcept
|
||||
: _M_impl(__p, __d, _Alloc()) { }
|
||||
: _M_impl(__p, std::move(__d), _Alloc()) { }
|
||||
|
||||
// __d(__p) must not throw.
|
||||
_Sp_counted_deleter(_Ptr __p, _Deleter __d, const _Alloc& __a) noexcept
|
||||
: _M_impl(__p, __d, __a) { }
|
||||
: _M_impl(__p, std::move(__d), __a) { }
|
||||
|
||||
~_Sp_counted_deleter() noexcept { }
|
||||
|
||||
|
@ -1111,7 +1113,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
|
|||
|
||||
template<typename _Yp, typename _Deleter, typename = _SafeConv<_Yp>>
|
||||
__shared_ptr(_Yp* __p, _Deleter __d)
|
||||
: _M_ptr(__p), _M_refcount(__p, __d)
|
||||
: _M_ptr(__p), _M_refcount(__p, std::move(__d))
|
||||
{
|
||||
static_assert(__is_invocable<_Deleter&, _Yp*&>::value,
|
||||
"deleter expression d(p) is well-formed");
|
||||
|
@ -1121,7 +1123,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
|
|||
template<typename _Yp, typename _Deleter, typename _Alloc,
|
||||
typename = _SafeConv<_Yp>>
|
||||
__shared_ptr(_Yp* __p, _Deleter __d, _Alloc __a)
|
||||
: _M_ptr(__p), _M_refcount(__p, __d, std::move(__a))
|
||||
: _M_ptr(__p), _M_refcount(__p, std::move(__d), std::move(__a))
|
||||
{
|
||||
static_assert(__is_invocable<_Deleter&, _Yp*&>::value,
|
||||
"deleter expression d(p) is well-formed");
|
||||
|
@ -1130,12 +1132,12 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
|
|||
|
||||
template<typename _Deleter>
|
||||
__shared_ptr(nullptr_t __p, _Deleter __d)
|
||||
: _M_ptr(0), _M_refcount(__p, __d)
|
||||
: _M_ptr(0), _M_refcount(__p, std::move(__d))
|
||||
{ }
|
||||
|
||||
template<typename _Deleter, typename _Alloc>
|
||||
__shared_ptr(nullptr_t __p, _Deleter __d, _Alloc __a)
|
||||
: _M_ptr(0), _M_refcount(__p, __d, std::move(__a))
|
||||
: _M_ptr(0), _M_refcount(__p, std::move(__d), std::move(__a))
|
||||
{ }
|
||||
|
||||
template<typename _Yp>
|
||||
|
@ -1278,12 +1280,12 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
|
|||
template<typename _Yp, typename _Deleter>
|
||||
_SafeConv<_Yp>
|
||||
reset(_Yp* __p, _Deleter __d)
|
||||
{ __shared_ptr(__p, __d).swap(*this); }
|
||||
{ __shared_ptr(__p, std::move(__d)).swap(*this); }
|
||||
|
||||
template<typename _Yp, typename _Deleter, typename _Alloc>
|
||||
_SafeConv<_Yp>
|
||||
reset(_Yp* __p, _Deleter __d, _Alloc __a)
|
||||
{ __shared_ptr(__p, __d, std::move(__a)).swap(*this); }
|
||||
{ __shared_ptr(__p, std::move(__d), std::move(__a)).swap(*this); }
|
||||
|
||||
element_type*
|
||||
get() const noexcept
|
||||
|
|
51
libstdc++-v3/testsuite/20_util/shared_ptr/cons/lwg2802.cc
Normal file
51
libstdc++-v3/testsuite/20_util/shared_ptr/cons/lwg2802.cc
Normal file
|
@ -0,0 +1,51 @@
|
|||
// Copyright (C) 2017 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/>.
|
||||
|
||||
// { dg-do compile { target c++11 } }
|
||||
|
||||
#include <memory>
|
||||
|
||||
// LWG 2802. shared_ptr constructor requirements for a deleter
|
||||
|
||||
struct D
|
||||
{
|
||||
D() { }
|
||||
D(D&&) { }
|
||||
void operator()(int* p) const { delete p; }
|
||||
};
|
||||
|
||||
std::allocator<int> a;
|
||||
|
||||
std::shared_ptr<int> s1((int*)nullptr, D());
|
||||
std::shared_ptr<int> s2((int*)nullptr, D(), a);
|
||||
std::shared_ptr<int> s3(nullptr, D());
|
||||
std::shared_ptr<int> s4(nullptr, D(), a);
|
||||
|
||||
void test01()
|
||||
{
|
||||
s1.reset((int*)nullptr, D());
|
||||
s1.reset((int*)nullptr, D(), a);
|
||||
}
|
||||
|
||||
struct D2 final
|
||||
{
|
||||
D2() { }
|
||||
D2(D2&&) { }
|
||||
void operator()(int* p) const { delete p; }
|
||||
};
|
||||
|
||||
std::shared_ptr<int> s5(nullptr, D2());
|
Loading…
Add table
Reference in a new issue