Fixes GitHub #84 ("Allow vector to be assigned to itself").

This commit is contained in:
Ion Gaztañaga
2018-11-11 01:10:01 +01:00
parent 059133a345
commit 2bc6f4d1a0
2 changed files with 12 additions and 5 deletions

View File

@@ -1255,6 +1255,7 @@ use [*Boost.Container]? There are several reasons for that:
* [@https://github.com/boostorg/container/issues/79 GitHub #79: ['"Mark small_vector move operations noexcept"]]. * [@https://github.com/boostorg/container/issues/79 GitHub #79: ['"Mark small_vector move operations noexcept"]].
* [@https://github.com/boostorg/container/issues/82 GitHub #82: ['"Function definition in header file"]]. * [@https://github.com/boostorg/container/issues/82 GitHub #82: ['"Function definition in header file"]].
* [@https://github.com/boostorg/container/issues/83 GitHub #83: ['"Iterator zero incrementing leads to assert on empty vector"]]. * [@https://github.com/boostorg/container/issues/83 GitHub #83: ['"Iterator zero incrementing leads to assert on empty vector"]].
* [@https://github.com/boostorg/container/pull/84 GitHub #84: ['"Allow vector to be assigned to itself"]].
* [@https://github.com/boostorg/container/pull/85 GitHub #85: ['"container: misc-typos"]]. * [@https://github.com/boostorg/container/pull/85 GitHub #85: ['"container: misc-typos"]].
* [@https://github.com/boostorg/container/pull/86 GitHub #86: ['"Add missing warning re-enabling include"]]. * [@https://github.com/boostorg/container/pull/86 GitHub #86: ['"Add missing warning re-enabling include"]].

View File

@@ -1131,7 +1131,6 @@ class vector
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(&x != this);
this->priv_move_assign(boost::move(x)); this->priv_move_assign(boost::move(x));
return *this; return *this;
} }
@@ -2407,7 +2406,8 @@ class vector
>::type * = 0) >::type * = 0)
{ {
//for move assignment, no aliasing (&x != this) is assumed. //for move assignment, no aliasing (&x != this) is assumed.
BOOST_ASSERT(this != &x); //x.size() == 0 is allowed for buggy std libraries.
BOOST_ASSERT(this != &x || x.size() == 0);
allocator_type &this_alloc = this->m_holder.alloc(); allocator_type &this_alloc = this->m_holder.alloc();
allocator_type &x_alloc = x.m_holder.alloc(); allocator_type &x_alloc = x.m_holder.alloc();
const bool propagate_alloc = allocator_traits_type::propagate_on_container_move_assignment::value; const bool propagate_alloc = allocator_traits_type::propagate_on_container_move_assignment::value;
@@ -2425,6 +2425,7 @@ class vector
} }
else if(is_propagable_from_x){ else if(is_propagable_from_x){
this->clear(); this->clear();
if(BOOST_LIKELY(!!this->m_holder.m_start))
this->m_holder.deallocate(this->m_holder.m_start, this->m_holder.m_capacity); this->m_holder.deallocate(this->m_holder.m_start, this->m_holder.m_capacity);
this->m_holder.steal_resources(x.m_holder); this->m_holder.steal_resources(x.m_holder);
} }
@@ -2489,6 +2490,9 @@ class vector
this->m_holder.swap_resources(x.m_holder); this->m_holder.swap_resources(x.m_holder);
} }
else{ else{
if (BOOST_UNLIKELY(&x == this))
return;
//Else swap element by element... //Else swap element by element...
bool const t_smaller = this->size() < x.size(); bool const t_smaller = this->size() < x.size();
vector &sml = t_smaller ? *this : x; vector &sml = t_smaller ? *this : x;
@@ -2664,6 +2668,7 @@ class vector
if(cp){ if(cp){
const size_type sz = this->size(); const size_type sz = this->size();
if(!sz){ if(!sz){
if(BOOST_LIKELY(!!this->m_holder.m_start))
this->m_holder.deallocate(this->m_holder.m_start, cp); this->m_holder.deallocate(this->m_holder.m_start, cp);
this->m_holder.m_start = pointer(); this->m_holder.m_start = pointer();
this->m_holder.m_capacity = 0; this->m_holder.m_capacity = 0;
@@ -2690,6 +2695,7 @@ class vector
if(cp){ if(cp){
const size_type sz = this->size(); const size_type sz = this->size();
if(!sz){ if(!sz){
if(BOOST_LIKELY(!!this->m_holder.m_start))
this->m_holder.deallocate(this->m_holder.m_start, cp); this->m_holder.deallocate(this->m_holder.m_start, cp);
this->m_holder.m_start = pointer(); this->m_holder.m_start = pointer();
this->m_holder.m_capacity = 0; this->m_holder.m_capacity = 0;