From 2bc6f4d1a030661b3242244cd5f90260f4293620 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ion=20Gazta=C3=B1aga?= Date: Sun, 11 Nov 2018 01:10:01 +0100 Subject: [PATCH] Fixes GitHub #84 ("Allow vector to be assigned to itself"). --- doc/container.qbk | 1 + include/boost/container/vector.hpp | 16 +++++++++++----- 2 files changed, 12 insertions(+), 5 deletions(-) diff --git a/doc/container.qbk b/doc/container.qbk index 9528e83..5060c4c 100644 --- a/doc/container.qbk +++ b/doc/container.qbk @@ -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/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/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/86 GitHub #86: ['"Add missing warning re-enabling include"]]. diff --git a/include/boost/container/vector.hpp b/include/boost/container/vector.hpp index f8736d8..aa4b505 100644 --- a/include/boost/container/vector.hpp +++ b/include/boost/container/vector.hpp @@ -1131,7 +1131,6 @@ class vector BOOST_NOEXCEPT_IF(allocator_traits_type::propagate_on_container_move_assignment::value || allocator_traits_type::is_always_equal::value) { - BOOST_ASSERT(&x != this); this->priv_move_assign(boost::move(x)); return *this; } @@ -2407,7 +2406,8 @@ class vector >::type * = 0) { //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 &x_alloc = x.m_holder.alloc(); const bool propagate_alloc = allocator_traits_type::propagate_on_container_move_assignment::value; @@ -2425,7 +2425,8 @@ class vector } else if(is_propagable_from_x){ this->clear(); - this->m_holder.deallocate(this->m_holder.m_start, this->m_holder.m_capacity); + 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.steal_resources(x.m_holder); } //Else do a one by one move @@ -2489,6 +2490,9 @@ class vector this->m_holder.swap_resources(x.m_holder); } else{ + if (BOOST_UNLIKELY(&x == this)) + return; + //Else swap element by element... bool const t_smaller = this->size() < x.size(); vector &sml = t_smaller ? *this : x; @@ -2664,7 +2668,8 @@ class vector if(cp){ const size_type sz = this->size(); if(!sz){ - this->m_holder.deallocate(this->m_holder.m_start, cp); + if(BOOST_LIKELY(!!this->m_holder.m_start)) + this->m_holder.deallocate(this->m_holder.m_start, cp); this->m_holder.m_start = pointer(); this->m_holder.m_capacity = 0; } @@ -2690,7 +2695,8 @@ class vector if(cp){ const size_type sz = this->size(); if(!sz){ - this->m_holder.deallocate(this->m_holder.m_start, cp); + if(BOOST_LIKELY(!!this->m_holder.m_start)) + this->m_holder.deallocate(this->m_holder.m_start, cp); this->m_holder.m_start = pointer(); this->m_holder.m_capacity = 0; }