mirror of git://gcc.gnu.org/git/gcc.git
re PR libstdc++/59872 (Cannot move std::map with move-only mapped_type)
PR libstdc++/59872 * include/bits/stl_map.h (map::operator=(map&&)): Fix comment. * include/bits/stl_multimap.h (multimap::operator=(multimap&&)): Likewise. * include/bits/stl_multiset.h (multiset::operator=(multiset&&)): Likewise. * include/bits/stl_set.h (set::operator=(set&&)): Likewise. * include/bits/stl_tree.h (_Rb_tree::_M_move_data): New overloaded functions to perform moving or copying of elements from rvalue tree. (_Rb_tree::_Rb_tree(_Rb_tree&&)): Use _M_move_data. (_Rb_tree::_Rb_tree(_Rb_tree&&, _Node_allocator&&)): Likewise. * testsuite/23_containers/map/59872.cc: New. * testsuite/23_containers/map/56613.cc: Remove duplicate include. From-SVN: r206994
This commit is contained in:
parent
ea0f1fc8e4
commit
6a5839c841
|
|
@ -3,6 +3,20 @@
|
||||||
* doc/xml/faq.xml (a-how_to_set_paths): Expand FAQ answer.
|
* doc/xml/faq.xml (a-how_to_set_paths): Expand FAQ answer.
|
||||||
* doc/xml/manual/abi.xml (abi.versioning.history): Correct symver.
|
* doc/xml/manual/abi.xml (abi.versioning.history): Correct symver.
|
||||||
|
|
||||||
|
PR libstdc++/59872
|
||||||
|
* include/bits/stl_map.h (map::operator=(map&&)): Fix comment.
|
||||||
|
* include/bits/stl_multimap.h (multimap::operator=(multimap&&)):
|
||||||
|
Likewise.
|
||||||
|
* include/bits/stl_multiset.h (multiset::operator=(multiset&&)):
|
||||||
|
Likewise.
|
||||||
|
* include/bits/stl_set.h (set::operator=(set&&)): Likewise.
|
||||||
|
* include/bits/stl_tree.h (_Rb_tree::_M_move_data): New overloaded
|
||||||
|
functions to perform moving or copying of elements from rvalue tree.
|
||||||
|
(_Rb_tree::_Rb_tree(_Rb_tree&&)): Use _M_move_data.
|
||||||
|
(_Rb_tree::_Rb_tree(_Rb_tree&&, _Node_allocator&&)): Likewise.
|
||||||
|
* testsuite/23_containers/map/59872.cc: New.
|
||||||
|
* testsuite/23_containers/map/56613.cc: Remove duplicate include.
|
||||||
|
|
||||||
2014-01-22 Jonathan Wakely <jwakely@redhat.com>
|
2014-01-22 Jonathan Wakely <jwakely@redhat.com>
|
||||||
|
|
||||||
* include/bits/stl_deque.h (_Deque_impl): Move comment.
|
* include/bits/stl_deque.h (_Deque_impl): Move comment.
|
||||||
|
|
|
||||||
|
|
@ -301,8 +301,9 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
|
||||||
* @brief %Map move assignment operator.
|
* @brief %Map move assignment operator.
|
||||||
* @param __x A %map of identical element and allocator types.
|
* @param __x A %map of identical element and allocator types.
|
||||||
*
|
*
|
||||||
* The contents of @a __x are moved into this map (without copying).
|
* The contents of @a __x are moved into this map (without copying
|
||||||
* @a __x is a valid, but unspecified %map.
|
* if the allocators compare equal or get moved on assignment).
|
||||||
|
* Afterwards @a __x is in a valid, but unspecified state.
|
||||||
*/
|
*/
|
||||||
map&
|
map&
|
||||||
operator=(map&& __x) noexcept(_Alloc_traits::_S_nothrow_move())
|
operator=(map&& __x) noexcept(_Alloc_traits::_S_nothrow_move())
|
||||||
|
|
|
||||||
|
|
@ -295,8 +295,9 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
|
||||||
* @brief %Multimap move assignment operator.
|
* @brief %Multimap move assignment operator.
|
||||||
* @param __x A %multimap of identical element and allocator types.
|
* @param __x A %multimap of identical element and allocator types.
|
||||||
*
|
*
|
||||||
* The contents of @a __x are moved into this multimap (without copying).
|
* The contents of @a __x are moved into this multimap (without copying
|
||||||
* @a __x is a valid, but unspecified multimap.
|
* if the allocators compare equal or get moved on assignment).
|
||||||
|
* Afterwards @a __x is in a valid, but unspecified state.
|
||||||
*/
|
*/
|
||||||
multimap&
|
multimap&
|
||||||
operator=(multimap&& __x) noexcept(_Alloc_traits::_S_nothrow_move())
|
operator=(multimap&& __x) noexcept(_Alloc_traits::_S_nothrow_move())
|
||||||
|
|
|
||||||
|
|
@ -267,9 +267,9 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
|
||||||
* @brief %Multiset move assignment operator.
|
* @brief %Multiset move assignment operator.
|
||||||
* @param __x A %multiset of identical element and allocator types.
|
* @param __x A %multiset of identical element and allocator types.
|
||||||
*
|
*
|
||||||
* The contents of @a __x are moved into this %multiset
|
* The contents of @a __x are moved into this %multiset (without
|
||||||
* (without copying). @a __x is a valid, but unspecified
|
* copying if the allocators compare equal or get moved on assignment).
|
||||||
* %multiset.
|
* Afterwards @a __x is in a valid, but unspecified state.
|
||||||
*/
|
*/
|
||||||
multiset&
|
multiset&
|
||||||
operator=(multiset&& __x) noexcept(_Alloc_traits::_S_nothrow_move())
|
operator=(multiset&& __x) noexcept(_Alloc_traits::_S_nothrow_move())
|
||||||
|
|
|
||||||
|
|
@ -271,8 +271,9 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
|
||||||
* @brief %Set move assignment operator.
|
* @brief %Set move assignment operator.
|
||||||
* @param __x A %set of identical element and allocator types.
|
* @param __x A %set of identical element and allocator types.
|
||||||
*
|
*
|
||||||
* The contents of @a __x are moved into this %set (without copying).
|
* The contents of @a __x are moved into this %set (without copying
|
||||||
* @a __x is a valid, but unspecified %set.
|
* if the allocators compare equal or get moved on assignment).
|
||||||
|
* Afterwards @a __x is in a valid, but unspecified state.
|
||||||
*/
|
*/
|
||||||
set&
|
set&
|
||||||
operator=(set&& __x) noexcept(_Alloc_traits::_S_nothrow_move())
|
operator=(set&& __x) noexcept(_Alloc_traits::_S_nothrow_move())
|
||||||
|
|
|
||||||
|
|
@ -698,8 +698,11 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
|
||||||
}
|
}
|
||||||
|
|
||||||
_Rb_tree(_Rb_tree&& __x)
|
_Rb_tree(_Rb_tree&& __x)
|
||||||
: _Rb_tree(std::move(__x), std::move(__x._M_get_Node_allocator()))
|
: _M_impl(__x._M_impl._M_key_compare, __x._M_get_Node_allocator())
|
||||||
{ }
|
{
|
||||||
|
if (__x._M_root() != 0)
|
||||||
|
_M_move_data(__x, std::true_type());
|
||||||
|
}
|
||||||
|
|
||||||
_Rb_tree(_Rb_tree&& __x, const allocator_type& __a)
|
_Rb_tree(_Rb_tree&& __x, const allocator_type& __a)
|
||||||
: _Rb_tree(std::move(__x), _Node_allocator(__a))
|
: _Rb_tree(std::move(__x), _Node_allocator(__a))
|
||||||
|
|
@ -948,6 +951,16 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
|
||||||
#if __cplusplus >= 201103L
|
#if __cplusplus >= 201103L
|
||||||
bool
|
bool
|
||||||
_M_move_assign(_Rb_tree&);
|
_M_move_assign(_Rb_tree&);
|
||||||
|
|
||||||
|
private:
|
||||||
|
// Move elements from container with equal allocator.
|
||||||
|
void
|
||||||
|
_M_move_data(_Rb_tree&, std::true_type);
|
||||||
|
|
||||||
|
// Move elements from container with possibly non-equal allocator,
|
||||||
|
// which might result in a copy not a move.
|
||||||
|
void
|
||||||
|
_M_move_data(_Rb_tree&, std::false_type);
|
||||||
#endif
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -1013,30 +1026,44 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
|
||||||
_Rb_tree(_Rb_tree&& __x, _Node_allocator&& __a)
|
_Rb_tree(_Rb_tree&& __x, _Node_allocator&& __a)
|
||||||
: _M_impl(__x._M_impl._M_key_compare, std::move(__a))
|
: _M_impl(__x._M_impl._M_key_compare, std::move(__a))
|
||||||
{
|
{
|
||||||
|
using __eq = integral_constant<bool, _Alloc_traits::_S_always_equal()>;
|
||||||
if (__x._M_root() != 0)
|
if (__x._M_root() != 0)
|
||||||
|
_M_move_data(__x, __eq());
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename _Key, typename _Val, typename _KeyOfValue,
|
||||||
|
typename _Compare, typename _Alloc>
|
||||||
|
void
|
||||||
|
_Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::
|
||||||
|
_M_move_data(_Rb_tree& __x, std::true_type)
|
||||||
|
{
|
||||||
|
_M_root() = __x._M_root();
|
||||||
|
_M_leftmost() = __x._M_leftmost();
|
||||||
|
_M_rightmost() = __x._M_rightmost();
|
||||||
|
_M_root()->_M_parent = _M_end();
|
||||||
|
|
||||||
|
__x._M_root() = 0;
|
||||||
|
__x._M_leftmost() = __x._M_end();
|
||||||
|
__x._M_rightmost() = __x._M_end();
|
||||||
|
|
||||||
|
this->_M_impl._M_node_count = __x._M_impl._M_node_count;
|
||||||
|
__x._M_impl._M_node_count = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename _Key, typename _Val, typename _KeyOfValue,
|
||||||
|
typename _Compare, typename _Alloc>
|
||||||
|
void
|
||||||
|
_Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::
|
||||||
|
_M_move_data(_Rb_tree& __x, std::false_type)
|
||||||
|
{
|
||||||
|
if (_M_get_Node_allocator() == __x._M_get_Node_allocator())
|
||||||
|
_M_move_data(__x, std::true_type());
|
||||||
|
else
|
||||||
{
|
{
|
||||||
if (!_Alloc_traits::_S_always_equal()
|
_M_root() = _M_copy(__x._M_begin(), _M_end());
|
||||||
&& __x._M_get_Node_allocator() != __a)
|
_M_leftmost() = _S_minimum(_M_root());
|
||||||
{
|
_M_rightmost() = _S_maximum(_M_root());
|
||||||
_M_root() = _M_copy(__x._M_begin(), _M_end());
|
_M_impl._M_node_count = __x._M_impl._M_node_count;
|
||||||
_M_leftmost() = _S_minimum(_M_root());
|
|
||||||
_M_rightmost() = _S_maximum(_M_root());
|
|
||||||
_M_impl._M_node_count = __x._M_impl._M_node_count;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
_M_root() = __x._M_root();
|
|
||||||
_M_leftmost() = __x._M_leftmost();
|
|
||||||
_M_rightmost() = __x._M_rightmost();
|
|
||||||
_M_root()->_M_parent = _M_end();
|
|
||||||
|
|
||||||
__x._M_root() = 0;
|
|
||||||
__x._M_leftmost() = __x._M_end();
|
|
||||||
__x._M_rightmost() = __x._M_end();
|
|
||||||
|
|
||||||
this->_M_impl._M_node_count = __x._M_impl._M_node_count;
|
|
||||||
__x._M_impl._M_node_count = 0;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1052,19 +1079,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
|
||||||
{
|
{
|
||||||
clear();
|
clear();
|
||||||
if (__x._M_root() != 0)
|
if (__x._M_root() != 0)
|
||||||
{
|
_M_move_data(__x, std::true_type());
|
||||||
_M_root() = __x._M_root();
|
|
||||||
_M_leftmost() = __x._M_leftmost();
|
|
||||||
_M_rightmost() = __x._M_rightmost();
|
|
||||||
_M_root()->_M_parent = _M_end();
|
|
||||||
|
|
||||||
__x._M_root() = 0;
|
|
||||||
__x._M_leftmost() = __x._M_end();
|
|
||||||
__x._M_rightmost() = __x._M_end();
|
|
||||||
|
|
||||||
this->_M_impl._M_node_count = __x._M_impl._M_node_count;
|
|
||||||
__x._M_impl._M_node_count = 0;
|
|
||||||
}
|
|
||||||
if (_Alloc_traits::_S_propagate_on_move_assign())
|
if (_Alloc_traits::_S_propagate_on_move_assign())
|
||||||
std::__alloc_on_move(_M_get_Node_allocator(),
|
std::__alloc_on_move(_M_get_Node_allocator(),
|
||||||
__x._M_get_Node_allocator());
|
__x._M_get_Node_allocator());
|
||||||
|
|
|
||||||
|
|
@ -24,7 +24,6 @@
|
||||||
// { dg-options "-std=gnu++11" }
|
// { dg-options "-std=gnu++11" }
|
||||||
|
|
||||||
// libstdc++/56613
|
// libstdc++/56613
|
||||||
#include <map>
|
|
||||||
|
|
||||||
// A conforming C++03 allocator, should still work in C++11 mode.
|
// A conforming C++03 allocator, should still work in C++11 mode.
|
||||||
template<typename T>
|
template<typename T>
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,36 @@
|
||||||
|
// Copyright (C) 2014 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 }
|
||||||
|
// { dg-options "-std=gnu++11" }
|
||||||
|
|
||||||
|
// libstdc++/59872
|
||||||
|
|
||||||
|
#include <map>
|
||||||
|
|
||||||
|
struct MoveOnly
|
||||||
|
{
|
||||||
|
MoveOnly() = default;
|
||||||
|
MoveOnly(MoveOnly&&) = default;
|
||||||
|
MoveOnly(const MoveOnly&) = delete;
|
||||||
|
};
|
||||||
|
|
||||||
|
using test_type = std::map<int, MoveOnly>;
|
||||||
|
|
||||||
|
test_type p;
|
||||||
|
test_type q(std::move(p));
|
||||||
|
test_type r(std::move(p), test_type::allocator_type());
|
||||||
Loading…
Reference in New Issue