forked from boostorg/container
Fixes #88 ("Implement C++17 MoveAssignable requirements for self-move assignments")
This commit is contained in:
@@ -1267,9 +1267,9 @@ use [*Boost.Container]? There are several reasons for that:
|
|||||||
[section:release_notes Release Notes]
|
[section:release_notes Release Notes]
|
||||||
|
|
||||||
[section:release_notes_boost_1_71_00 Boost 1.71 Release]
|
[section:release_notes_boost_1_71_00 Boost 1.71 Release]
|
||||||
|
* [@https://github.com/boostorg/container/issues/88 GitHub #88: ['"Implement C++17 MoveAssignable requirements for self-move assignments"]].
|
||||||
* [@https://github.com/boostorg/container/pull/109 GitHub #109: ['"Get rid of integer overflow in copy_move_algo.hpp (-fsanitize=integer)"]].
|
* [@https://github.com/boostorg/container/pull/109 GitHub #109: ['"Get rid of integer overflow in copy_move_algo.hpp (-fsanitize=integer)"]].
|
||||||
* [@https://github.com/boostorg/container/pull/110 GitHub #110: ['"Avoid gcc 9 deprecated copy warnings in new_allocator.hpp"]].
|
* [@https://github.com/boostorg/container/pull/110 GitHub #110: ['"Avoid gcc 9 deprecated copy warnings in new_allocator.hpp"]].
|
||||||
* [@https://github.com/boostorg/container/issues/112 GitHub #112: ['"vector::resize() compilation error with msvc-10..12: data is not a member of boost::detail::aligned_storage"]].
|
* [@https://github.com/boostorg/container/issues/112 GitHub #112: ['"vector::resize() compilation error with msvc-10..12: data is not a member of boost::detail::aligned_storage"]].
|
||||||
* [@https://github.com/boostorg/container/issues/114 GitHub #114: ['"Fix small_vector noexcept specification"]].
|
* [@https://github.com/boostorg/container/issues/114 GitHub #114: ['"Fix small_vector noexcept specification"]].
|
||||||
* [@https://github.com/boostorg/container/issues/116 GitHub #116: ['"MSVC + boost 1.70 compilation error when windows.h is already included (detail/thread_mutex.hpp)"]].
|
* [@https://github.com/boostorg/container/issues/116 GitHub #116: ['"MSVC + boost 1.70 compilation error when windows.h is already included (detail/thread_mutex.hpp)"]].
|
||||||
|
@@ -811,7 +811,7 @@ class deque : protected deque_base<typename real_allocator<T, Allocator>::type,
|
|||||||
//! <b>Complexity</b>: Linear to the number of elements in x.
|
//! <b>Complexity</b>: Linear to the number of elements in x.
|
||||||
deque& operator= (BOOST_COPY_ASSIGN_REF(deque) x)
|
deque& operator= (BOOST_COPY_ASSIGN_REF(deque) x)
|
||||||
{
|
{
|
||||||
if (&x != this){
|
if (BOOST_LIKELY(&x != this)){
|
||||||
allocator_type &this_alloc = this->alloc();
|
allocator_type &this_alloc = this->alloc();
|
||||||
const allocator_type &x_alloc = x.alloc();
|
const allocator_type &x_alloc = x.alloc();
|
||||||
dtl::bool_<allocator_traits_type::
|
dtl::bool_<allocator_traits_type::
|
||||||
@@ -839,28 +839,29 @@ class deque : protected deque_base<typename real_allocator<T, Allocator>::type,
|
|||||||
BOOST_NOEXCEPT_IF(allocator_traits_type::propagate_on_container_move_assignment::value
|
BOOST_NOEXCEPT_IF(allocator_traits_type::propagate_on_container_move_assignment::value
|
||||||
|| allocator_traits_type::is_always_equal::value)
|
|| allocator_traits_type::is_always_equal::value)
|
||||||
{
|
{
|
||||||
BOOST_ASSERT(this != &x);
|
if (BOOST_LIKELY(this != &x)) {
|
||||||
allocator_type &this_alloc = this->alloc();
|
allocator_type &this_alloc = this->alloc();
|
||||||
allocator_type &x_alloc = x.alloc();
|
allocator_type &x_alloc = x.alloc();
|
||||||
const bool propagate_alloc = allocator_traits_type::
|
const bool propagate_alloc = allocator_traits_type::
|
||||||
propagate_on_container_move_assignment::value;
|
propagate_on_container_move_assignment::value;
|
||||||
dtl::bool_<propagate_alloc> flag;
|
dtl::bool_<propagate_alloc> flag;
|
||||||
const bool allocators_equal = this_alloc == x_alloc; (void)allocators_equal;
|
const bool allocators_equal = this_alloc == x_alloc; (void)allocators_equal;
|
||||||
//Resources can be transferred if both allocators are
|
//Resources can be transferred if both allocators are
|
||||||
//going to be equal after this function (either propagated or already equal)
|
//going to be equal after this function (either propagated or already equal)
|
||||||
if(propagate_alloc || allocators_equal){
|
if(propagate_alloc || allocators_equal){
|
||||||
//Destroy objects but retain memory in case x reuses it in the future
|
//Destroy objects but retain memory in case x reuses it in the future
|
||||||
this->clear();
|
this->clear();
|
||||||
//Move allocator if needed
|
//Move allocator if needed
|
||||||
dtl::move_alloc(this_alloc, x_alloc, flag);
|
dtl::move_alloc(this_alloc, x_alloc, flag);
|
||||||
dtl::move_alloc(this->ptr_alloc(), x.ptr_alloc(), flag);
|
dtl::move_alloc(this->ptr_alloc(), x.ptr_alloc(), flag);
|
||||||
//Nothrow swap
|
//Nothrow swap
|
||||||
this->swap_members(x);
|
this->swap_members(x);
|
||||||
}
|
}
|
||||||
//Else do a one by one move
|
//Else do a one by one move
|
||||||
else{
|
else{
|
||||||
this->assign( boost::make_move_iterator(x.begin())
|
this->assign( boost::make_move_iterator(x.begin())
|
||||||
, boost::make_move_iterator(x.end()));
|
, boost::make_move_iterator(x.end()));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
@@ -788,7 +788,7 @@ class tree
|
|||||||
|
|
||||||
tree& operator=(BOOST_COPY_ASSIGN_REF(tree) x)
|
tree& operator=(BOOST_COPY_ASSIGN_REF(tree) x)
|
||||||
{
|
{
|
||||||
if (&x != this){
|
if (BOOST_LIKELY(this != &x)) {
|
||||||
NodeAlloc &this_alloc = this->get_stored_allocator();
|
NodeAlloc &this_alloc = this->get_stored_allocator();
|
||||||
const NodeAlloc &x_alloc = x.get_stored_allocator();
|
const NodeAlloc &x_alloc = x.get_stored_allocator();
|
||||||
dtl::bool_<allocator_traits<NodeAlloc>::
|
dtl::bool_<allocator_traits<NodeAlloc>::
|
||||||
@@ -822,39 +822,40 @@ class tree
|
|||||||
allocator_traits_type::is_always_equal::value) &&
|
allocator_traits_type::is_always_equal::value) &&
|
||||||
boost::container::dtl::is_nothrow_move_assignable<Compare>::value)
|
boost::container::dtl::is_nothrow_move_assignable<Compare>::value)
|
||||||
{
|
{
|
||||||
BOOST_ASSERT(this != &x);
|
if (BOOST_LIKELY(this != &x)) {
|
||||||
NodeAlloc &this_alloc = this->node_alloc();
|
NodeAlloc &this_alloc = this->node_alloc();
|
||||||
NodeAlloc &x_alloc = x.node_alloc();
|
NodeAlloc &x_alloc = x.node_alloc();
|
||||||
const bool propagate_alloc = allocator_traits<NodeAlloc>::
|
const bool propagate_alloc = allocator_traits<NodeAlloc>::
|
||||||
propagate_on_container_move_assignment::value;
|
propagate_on_container_move_assignment::value;
|
||||||
const bool allocators_equal = this_alloc == x_alloc; (void)allocators_equal;
|
const bool allocators_equal = this_alloc == x_alloc; (void)allocators_equal;
|
||||||
//Resources can be transferred if both allocators are
|
//Resources can be transferred if both allocators are
|
||||||
//going to be equal after this function (either propagated or already equal)
|
//going to be equal after this function (either propagated or already equal)
|
||||||
if(propagate_alloc || allocators_equal){
|
if(propagate_alloc || allocators_equal){
|
||||||
//Destroy
|
//Destroy
|
||||||
this->clear();
|
this->clear();
|
||||||
//Move allocator if needed
|
//Move allocator if needed
|
||||||
this->AllocHolder::move_assign_alloc(x);
|
this->AllocHolder::move_assign_alloc(x);
|
||||||
//Obtain resources
|
//Obtain resources
|
||||||
this->icont() = boost::move(x.icont());
|
this->icont() = boost::move(x.icont());
|
||||||
}
|
}
|
||||||
//Else do a one by one move
|
//Else do a one by one move
|
||||||
else{
|
else{
|
||||||
//Transfer all the nodes to a temporary tree
|
//Transfer all the nodes to a temporary tree
|
||||||
//If anything goes wrong, all the nodes will be destroyed
|
//If anything goes wrong, all the nodes will be destroyed
|
||||||
//automatically
|
//automatically
|
||||||
Icont other_tree(::boost::move(this->icont()));
|
Icont other_tree(::boost::move(this->icont()));
|
||||||
|
|
||||||
//Now recreate the source tree reusing nodes stored by other_tree
|
//Now recreate the source tree reusing nodes stored by other_tree
|
||||||
this->icont().clone_from
|
this->icont().clone_from
|
||||||
(::boost::move(x.icont())
|
(::boost::move(x.icont())
|
||||||
, RecyclingCloner<AllocHolder, true>(*this, other_tree)
|
, RecyclingCloner<AllocHolder, true>(*this, other_tree)
|
||||||
, Destroyer(this->node_alloc()));
|
, Destroyer(this->node_alloc()));
|
||||||
|
|
||||||
//If there are remaining nodes, destroy them
|
//If there are remaining nodes, destroy them
|
||||||
NodePtr p;
|
NodePtr p;
|
||||||
while((p = other_tree.unlink_leftmost_without_rebalance())){
|
while((p = other_tree.unlink_leftmost_without_rebalance())){
|
||||||
AllocHolder::destroy_node(p);
|
AllocHolder::destroy_node(p);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return *this;
|
return *this;
|
||||||
|
@@ -367,7 +367,7 @@ class list
|
|||||||
//! <b>Complexity</b>: Linear to the number of elements in x.
|
//! <b>Complexity</b>: Linear to the number of elements in x.
|
||||||
list& operator=(BOOST_COPY_ASSIGN_REF(list) x)
|
list& operator=(BOOST_COPY_ASSIGN_REF(list) x)
|
||||||
{
|
{
|
||||||
if (&x != this){
|
if (BOOST_LIKELY(this != &x)) {
|
||||||
NodeAlloc &this_alloc = this->node_alloc();
|
NodeAlloc &this_alloc = this->node_alloc();
|
||||||
const NodeAlloc &x_alloc = x.node_alloc();
|
const NodeAlloc &x_alloc = x.node_alloc();
|
||||||
dtl::bool_<allocator_traits_type::
|
dtl::bool_<allocator_traits_type::
|
||||||
@@ -396,26 +396,27 @@ class list
|
|||||||
BOOST_NOEXCEPT_IF(allocator_traits_type::propagate_on_container_move_assignment::value
|
BOOST_NOEXCEPT_IF(allocator_traits_type::propagate_on_container_move_assignment::value
|
||||||
|| allocator_traits_type::is_always_equal::value)
|
|| allocator_traits_type::is_always_equal::value)
|
||||||
{
|
{
|
||||||
BOOST_ASSERT(this != &x);
|
if (BOOST_LIKELY(this != &x)) {
|
||||||
NodeAlloc &this_alloc = this->node_alloc();
|
NodeAlloc &this_alloc = this->node_alloc();
|
||||||
NodeAlloc &x_alloc = x.node_alloc();
|
NodeAlloc &x_alloc = x.node_alloc();
|
||||||
const bool propagate_alloc = allocator_traits_type::
|
const bool propagate_alloc = allocator_traits_type::
|
||||||
propagate_on_container_move_assignment::value;
|
propagate_on_container_move_assignment::value;
|
||||||
const bool allocators_equal = this_alloc == x_alloc; (void)allocators_equal;
|
const bool allocators_equal = this_alloc == x_alloc; (void)allocators_equal;
|
||||||
//Resources can be transferred if both allocators are
|
//Resources can be transferred if both allocators are
|
||||||
//going to be equal after this function (either propagated or already equal)
|
//going to be equal after this function (either propagated or already equal)
|
||||||
if(propagate_alloc || allocators_equal){
|
if(propagate_alloc || allocators_equal){
|
||||||
//Destroy
|
//Destroy
|
||||||
this->clear();
|
this->clear();
|
||||||
//Move allocator if needed
|
//Move allocator if needed
|
||||||
this->AllocHolder::move_assign_alloc(x);
|
this->AllocHolder::move_assign_alloc(x);
|
||||||
//Obtain resources
|
//Obtain resources
|
||||||
this->icont() = boost::move(x.icont());
|
this->icont() = boost::move(x.icont());
|
||||||
}
|
}
|
||||||
//Else do a one by one move
|
//Else do a one by one move
|
||||||
else{
|
else{
|
||||||
this->assign( boost::make_move_iterator(x.begin())
|
this->assign( boost::make_move_iterator(x.begin())
|
||||||
, boost::make_move_iterator(x.end()));
|
, boost::make_move_iterator(x.end()));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
@@ -395,7 +395,7 @@ class slist
|
|||||||
//! <b>Complexity</b>: Linear to the number of elements in x.
|
//! <b>Complexity</b>: Linear to the number of elements in x.
|
||||||
slist& operator= (BOOST_COPY_ASSIGN_REF(slist) x)
|
slist& operator= (BOOST_COPY_ASSIGN_REF(slist) x)
|
||||||
{
|
{
|
||||||
if (&x != this){
|
if (BOOST_LIKELY(this != &x)) {
|
||||||
NodeAlloc &this_alloc = this->node_alloc();
|
NodeAlloc &this_alloc = this->node_alloc();
|
||||||
const NodeAlloc &x_alloc = x.node_alloc();
|
const NodeAlloc &x_alloc = x.node_alloc();
|
||||||
dtl::bool_<allocator_traits_type::
|
dtl::bool_<allocator_traits_type::
|
||||||
@@ -424,26 +424,27 @@ class slist
|
|||||||
BOOST_NOEXCEPT_IF(allocator_traits_type::propagate_on_container_move_assignment::value
|
BOOST_NOEXCEPT_IF(allocator_traits_type::propagate_on_container_move_assignment::value
|
||||||
|| allocator_traits_type::is_always_equal::value)
|
|| allocator_traits_type::is_always_equal::value)
|
||||||
{
|
{
|
||||||
BOOST_ASSERT(this != &x);
|
if (BOOST_LIKELY(this != &x)) {
|
||||||
NodeAlloc &this_alloc = this->node_alloc();
|
NodeAlloc &this_alloc = this->node_alloc();
|
||||||
NodeAlloc &x_alloc = x.node_alloc();
|
NodeAlloc &x_alloc = x.node_alloc();
|
||||||
const bool propagate_alloc = allocator_traits_type::
|
const bool propagate_alloc = allocator_traits_type::
|
||||||
propagate_on_container_move_assignment::value;
|
propagate_on_container_move_assignment::value;
|
||||||
const bool allocators_equal = this_alloc == x_alloc; (void)allocators_equal;
|
const bool allocators_equal = this_alloc == x_alloc; (void)allocators_equal;
|
||||||
//Resources can be transferred if both allocators are
|
//Resources can be transferred if both allocators are
|
||||||
//going to be equal after this function (either propagated or already equal)
|
//going to be equal after this function (either propagated or already equal)
|
||||||
if(propagate_alloc || allocators_equal){
|
if(propagate_alloc || allocators_equal){
|
||||||
//Destroy
|
//Destroy
|
||||||
this->clear();
|
this->clear();
|
||||||
//Move allocator if needed
|
//Move allocator if needed
|
||||||
this->AllocHolder::move_assign_alloc(x);
|
this->AllocHolder::move_assign_alloc(x);
|
||||||
//Obtain resources
|
//Obtain resources
|
||||||
this->icont() = boost::move(x.icont());
|
this->icont() = boost::move(x.icont());
|
||||||
}
|
}
|
||||||
//Else do a one by one move
|
//Else do a one by one move
|
||||||
else{
|
else{
|
||||||
this->assign( boost::make_move_iterator(x.begin())
|
this->assign( boost::make_move_iterator(x.begin())
|
||||||
, boost::make_move_iterator(x.end()));
|
, boost::make_move_iterator(x.end()));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
@@ -823,7 +823,7 @@ class stable_vector
|
|||||||
stable_vector& operator=(BOOST_COPY_ASSIGN_REF(stable_vector) x)
|
stable_vector& operator=(BOOST_COPY_ASSIGN_REF(stable_vector) x)
|
||||||
{
|
{
|
||||||
STABLE_VECTOR_CHECK_INVARIANT;
|
STABLE_VECTOR_CHECK_INVARIANT;
|
||||||
if (&x != this){
|
if (BOOST_LIKELY(this != &x)) {
|
||||||
node_allocator_type &this_alloc = this->priv_node_alloc();
|
node_allocator_type &this_alloc = this->priv_node_alloc();
|
||||||
const node_allocator_type &x_alloc = x.priv_node_alloc();
|
const node_allocator_type &x_alloc = x.priv_node_alloc();
|
||||||
dtl::bool_<allocator_traits_type::
|
dtl::bool_<allocator_traits_type::
|
||||||
@@ -855,29 +855,30 @@ class stable_vector
|
|||||||
|| allocator_traits_type::is_always_equal::value)
|
|| allocator_traits_type::is_always_equal::value)
|
||||||
{
|
{
|
||||||
//for move constructor, no aliasing (&x != this) is assumed.
|
//for move constructor, no aliasing (&x != this) is assumed.
|
||||||
BOOST_ASSERT(this != &x);
|
if (BOOST_LIKELY(this != &x)) {
|
||||||
node_allocator_type &this_alloc = this->priv_node_alloc();
|
node_allocator_type &this_alloc = this->priv_node_alloc();
|
||||||
node_allocator_type &x_alloc = x.priv_node_alloc();
|
node_allocator_type &x_alloc = x.priv_node_alloc();
|
||||||
const bool propagate_alloc = allocator_traits_type::
|
const bool propagate_alloc = allocator_traits_type::
|
||||||
propagate_on_container_move_assignment::value;
|
propagate_on_container_move_assignment::value;
|
||||||
dtl::bool_<propagate_alloc> flag;
|
dtl::bool_<propagate_alloc> flag;
|
||||||
const bool allocators_equal = this_alloc == x_alloc; (void)allocators_equal;
|
const bool allocators_equal = this_alloc == x_alloc; (void)allocators_equal;
|
||||||
//Resources can be transferred if both allocators are
|
//Resources can be transferred if both allocators are
|
||||||
//going to be equal after this function (either propagated or already equal)
|
//going to be equal after this function (either propagated or already equal)
|
||||||
if(propagate_alloc || allocators_equal){
|
if(propagate_alloc || allocators_equal){
|
||||||
STABLE_VECTOR_CHECK_INVARIANT
|
STABLE_VECTOR_CHECK_INVARIANT
|
||||||
//Destroy objects but retain memory in case x reuses it in the future
|
//Destroy objects but retain memory in case x reuses it in the future
|
||||||
this->clear();
|
this->clear();
|
||||||
//Move allocator if needed
|
//Move allocator if needed
|
||||||
dtl::move_alloc(this_alloc, x_alloc, flag);
|
dtl::move_alloc(this_alloc, x_alloc, flag);
|
||||||
//Take resources
|
//Take resources
|
||||||
this->index.swap(x.index);
|
this->index.swap(x.index);
|
||||||
this->priv_swap_members(x);
|
this->priv_swap_members(x);
|
||||||
}
|
}
|
||||||
//Else do a one by one move
|
//Else do a one by one move
|
||||||
else{
|
else{
|
||||||
this->assign( boost::make_move_iterator(x.begin())
|
this->assign( boost::make_move_iterator(x.begin())
|
||||||
, boost::make_move_iterator(x.end()));
|
, boost::make_move_iterator(x.end()));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
@@ -865,7 +865,7 @@ class basic_string
|
|||||||
//! <b>Complexity</b>: Linear to the elements x contains.
|
//! <b>Complexity</b>: Linear to the elements x contains.
|
||||||
basic_string& operator=(BOOST_COPY_ASSIGN_REF(basic_string) x)
|
basic_string& operator=(BOOST_COPY_ASSIGN_REF(basic_string) x)
|
||||||
{
|
{
|
||||||
if (&x != this){
|
if (BOOST_LIKELY(this != &x)) {
|
||||||
allocator_type &this_alloc = this->alloc();
|
allocator_type &this_alloc = this->alloc();
|
||||||
const allocator_type &x_alloc = x.alloc();
|
const allocator_type &x_alloc = x.alloc();
|
||||||
dtl::bool_<allocator_traits_type::
|
dtl::bool_<allocator_traits_type::
|
||||||
@@ -896,27 +896,27 @@ class basic_string
|
|||||||
BOOST_NOEXCEPT_IF(allocator_traits_type::propagate_on_container_move_assignment::value
|
BOOST_NOEXCEPT_IF(allocator_traits_type::propagate_on_container_move_assignment::value
|
||||||
|| allocator_traits_type::is_always_equal::value)
|
|| allocator_traits_type::is_always_equal::value)
|
||||||
{
|
{
|
||||||
//for move constructor, no aliasing (&x != this) is assumed.
|
if (BOOST_LIKELY(this != &x)) {
|
||||||
BOOST_ASSERT(this != &x);
|
allocator_type &this_alloc = this->alloc();
|
||||||
allocator_type &this_alloc = this->alloc();
|
allocator_type &x_alloc = x.alloc();
|
||||||
allocator_type &x_alloc = x.alloc();
|
const bool propagate_alloc = allocator_traits_type::
|
||||||
const bool propagate_alloc = allocator_traits_type::
|
propagate_on_container_move_assignment::value;
|
||||||
propagate_on_container_move_assignment::value;
|
dtl::bool_<propagate_alloc> flag;
|
||||||
dtl::bool_<propagate_alloc> flag;
|
const bool allocators_equal = this_alloc == x_alloc; (void)allocators_equal;
|
||||||
const bool allocators_equal = this_alloc == x_alloc; (void)allocators_equal;
|
//Resources can be transferred if both allocators are
|
||||||
//Resources can be transferred if both allocators are
|
//going to be equal after this function (either propagated or already equal)
|
||||||
//going to be equal after this function (either propagated or already equal)
|
if(propagate_alloc || allocators_equal){
|
||||||
if(propagate_alloc || allocators_equal){
|
//Destroy objects but retain memory in case x reuses it in the future
|
||||||
//Destroy objects but retain memory in case x reuses it in the future
|
this->clear();
|
||||||
this->clear();
|
//Move allocator if needed
|
||||||
//Move allocator if needed
|
dtl::move_alloc(this_alloc, x_alloc, flag);
|
||||||
dtl::move_alloc(this_alloc, x_alloc, flag);
|
//Nothrow swap
|
||||||
//Nothrow swap
|
this->swap_data(x);
|
||||||
this->swap_data(x);
|
}
|
||||||
}
|
//Else do a one by one move
|
||||||
//Else do a one by one move
|
else{
|
||||||
else{
|
this->assign( x.begin(), x.end());
|
||||||
this->assign( x.begin(), x.end());
|
}
|
||||||
}
|
}
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user