From f1f97518d338c7f7351308aa1785ebae5f2ddde7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ion=20Gazta=C3=B1aga?= Date: Wed, 9 Sep 2015 09:48:09 +0200 Subject: [PATCH] Fixed Track #11627 and #11628 --- doc/container.qbk | 13 +++ .../boost/container/detail/copy_move_algo.hpp | 8 +- include/boost/container/vector.hpp | 17 ++-- test/small_vector_test.cpp | 86 ++++++++++++++----- 4 files changed, 89 insertions(+), 35 deletions(-) diff --git a/doc/container.qbk b/doc/container.qbk index a92b783..9253485 100644 --- a/doc/container.qbk +++ b/doc/container.qbk @@ -1216,6 +1216,19 @@ use [*Boost.Container]? There are several reasons for that: [section:release_notes_boost_1_60_00 Boost 1.60 Release] * Implemented [link container.extended_functionality.polymorphic_memory_resources Polymorphic Memory Resources]. +* Fixed bugs: + * [@https://svn.boost.org/trac/boost/ticket/11627 Trac #11627: ['"small_vector::swap() appears to be broken"]]. + * [@https://svn.boost.org/trac/boost/ticket/11628 Trac #11628: ['"small_vector iterates over elements in destructor"]]. + +[endsect] + +[section:release_notes_boost_1_60_00 Boost 1.60 Release] + +* [@https://github.com/boostorg/container/pull/26 GitHub #26: ['Fix bug in stable_vector::capacity()]]. Thanks to timsong-cpp/Arindam Mukerjee. +* [@https://github.com/boostorg/container/pull/27 GitHub #27: ['fix stable_vector's index_of's doxygen comment]]. Thanks to kariya-mitsuru. +* [@https://svn.boost.org/trac/boost/ticket/11380 Trac #11380: ['"Container library std forward declarations incorrect in std_fwd.hpp on libc++ with gcc"]]. +* [@https://svn.boost.org/trac/boost/ticket/11388 Trac #11388: ['"boost::container::list::emplace_back broken on Visual Studio 2010"]]. +* [@https://svn.boost.org/trac/boost/ticket/11339 Trac #11339: ['"VC12 LNK2005 error with boost::container::adaptive_pool"]]. [endsect] diff --git a/include/boost/container/detail/copy_move_algo.hpp b/include/boost/container/detail/copy_move_algo.hpp index 23fa730..f590a8a 100644 --- a/include/boost/container/detail/copy_move_algo.hpp +++ b/include/boost/container/detail/copy_move_algo.hpp @@ -252,15 +252,15 @@ struct disable_if_memzero_initializable template struct enable_if_trivially_destructible - : enable_if_c < false/*container_detail::is_trivially_destructible - ::value_type>::value*/ + : enable_if_c < container_detail::is_trivially_destructible + ::value_type>::value , R> {}; template struct disable_if_trivially_destructible - : enable_if_c ::value_type>::value*/ + : enable_if_c ::value_type>::value , R> {}; diff --git a/include/boost/container/vector.hpp b/include/boost/container/vector.hpp index 1cf44c8..e3aed38 100644 --- a/include/boost/container/vector.hpp +++ b/include/boost/container/vector.hpp @@ -346,18 +346,17 @@ struct vector_alloc_holder static bool is_propagable_from(const allocator_type &from_alloc, pointer p, const allocator_type &to_alloc, bool const propagate_allocator) { (void)propagate_allocator; (void)p; (void)to_alloc; (void)from_alloc; - return (!allocator_traits_type::is_partially_propagable::value || - !allocator_traits_type::storage_is_unpropagable(from_alloc, p)) && - (propagate_allocator || allocator_traits_type::equal(from_alloc, to_alloc)); + const bool all_storage_propagable = !allocator_traits_type::is_partially_propagable::value || + !allocator_traits_type::storage_is_unpropagable(from_alloc, p); + return all_storage_propagable && (propagate_allocator || allocator_traits_type::equal(from_alloc, to_alloc)); } static bool are_swap_propagable(const allocator_type &l_a, pointer l_p, const allocator_type &r_a, pointer r_p, bool const propagate_allocator) { (void)propagate_allocator; (void)l_p; (void)r_p; (void)l_a; (void)r_a; - return (!allocator_traits_type::is_partially_propagable::value || - (!allocator_traits_type::storage_is_unpropagable(r_a, r_p) && - !allocator_traits_type::storage_is_unpropagable(l_a, l_p)) - ) && (propagate_allocator || allocator_traits_type::equal(l_a, r_a)); + const bool all_storage_propagable = !allocator_traits_type::is_partially_propagable::value || + !(allocator_traits_type::storage_is_unpropagable(l_a, l_p) || allocator_traits_type::storage_is_unpropagable(r_a, r_p)); + return all_storage_propagable && (propagate_allocator || allocator_traits_type::equal(l_a, r_a)); } //Constructor, does not throw @@ -2452,7 +2451,7 @@ class vector { const bool propagate_alloc = allocator_traits_type::propagate_on_container_swap::value; if(are_swap_propagable( this->get_stored_allocator(), this->m_holder.start() - , x.get_stored_allocator(), this->m_holder.start(), propagate_alloc)){ + , x.get_stored_allocator(), x.m_holder.start(), propagate_alloc)){ //Just swap internals this->m_holder.swap_resources(x.m_holder); } @@ -2471,6 +2470,8 @@ class vector , boost::make_move_iterator(container_detail::iterator_to_raw_pointer(big.nth(common_elements))) , boost::make_move_iterator(container_detail::iterator_to_raw_pointer(big.end())) ); + //Destroy remaining elements + big.erase(big.nth(common_elements), big.cend()); } //And now swap the allocator container_detail::swap_alloc(this->m_holder.alloc(), x.m_holder.alloc(), container_detail::bool_()); diff --git a/test/small_vector_test.cpp b/test/small_vector_test.cpp index 5dacb7d..ab03435 100644 --- a/test/small_vector_test.cpp +++ b/test/small_vector_test.cpp @@ -108,40 +108,80 @@ bool test_small_vector_base_test() return true; } +//small vector has internal storage so some special swap cases must be tested +bool test_swap() +{ + typedef boost::container::small_vector vec; + { //v bigger than static capacity, w empty + vec v; + for(std::size_t i = 0, max = v.capacity()+1; i != max; ++i){ + v.push_back(int(i)); + } + vec w; + const std::size_t v_size = v.size(); + const std::size_t w_size = w.size(); + v.swap(w); + if(v.size() != w_size || w.size() != v_size) + return false; + } + { //v smaller than static capacity, w empty + vec v; + for(std::size_t i = 0, max = v.capacity()-1; i != max; ++i){ + v.push_back(int(i)); + } + vec w; + const std::size_t v_size = v.size(); + const std::size_t w_size = w.size(); + v.swap(w); + if(v.size() != w_size || w.size() != v_size) + return false; + } + { //v & w smaller than static capacity + vec v; + for(std::size_t i = 0, max = v.capacity()-1; i != max; ++i){ + v.push_back(int(i)); + } + vec w; + for(std::size_t i = 0, max = v.capacity()/2; i != max; ++i){ + w.push_back(int(i)); + } + const std::size_t v_size = v.size(); + const std::size_t w_size = w.size(); + v.swap(w); + if(v.size() != w_size || w.size() != v_size) + return false; + } + { //v & w bigger than static capacity + vec v; + for(std::size_t i = 0, max = v.capacity()+1; i != max; ++i){ + v.push_back(int(i)); + } + vec w; + for(std::size_t i = 0, max = v.capacity()*2; i != max; ++i){ + w.push_back(int(i)); + } + const std::size_t v_size = v.size(); + const std::size_t w_size = w.size(); + v.swap(w); + if(v.size() != w_size || w.size() != v_size) + return false; + } + return true; +} + int main() { using namespace boost::container; -/* - typedef small_vector::storage_test storage_test; - std::cout << "needed_extra_storages: " << storage_test::needed_extra_storages << '\n'; - std::cout << "needed_bytes: " << storage_test::needed_bytes << '\n'; - std::cout << "header_bytes: " << storage_test::header_bytes << '\n'; - std::cout << "s_start: " << storage_test::s_start << '\n'; - //char - std::cout << "sizeof(small_vector): " << sizeof(small_vector) << " extra: " << small_vector::needed_extra_storages << " internal storage: " << small_vector::internal_capacity() << '\n'; - std::cout << "sizeof(small_vector): " << sizeof(small_vector) << " extra: " << small_vector::needed_extra_storages << " internal storage: " << small_vector::internal_capacity() << '\n'; - std::cout << "sizeof(small_vector): " << sizeof(small_vector) << " extra: " << small_vector::needed_extra_storages << " internal storage: " << small_vector::internal_capacity() << '\n'; - std::cout << "sizeof(small_vector): " << sizeof(small_vector) << " extra: " << small_vector::needed_extra_storages << " internal storage: " << small_vector::internal_capacity() << '\n'; - std::cout << "sizeof(small_vector): " << sizeof(small_vector) << " extra: " << small_vector::needed_extra_storages << " internal storage: " << small_vector::internal_capacity() << '\n'; - std::cout << "sizeof(small_vector): " << sizeof(small_vector) << " extra: " << small_vector::needed_extra_storages << " internal storage: " << small_vector::internal_capacity() << '\n'; - std::cout << "\n"; + if(!test_swap()) + return 1; - //short - std::cout << "sizeof(small_vector): " << sizeof(small_vector) << " extra: " << small_vector::needed_extra_storages << " internal storage: " << small_vector::internal_capacity() << '\n'; - std::cout << "sizeof(small_vector): " << sizeof(small_vector) << " extra: " << small_vector::needed_extra_storages << " internal storage: " << small_vector::internal_capacity() << '\n'; - std::cout << "sizeof(small_vector): " << sizeof(small_vector) << " extra: " << small_vector::needed_extra_storages << " internal storage: " << small_vector::internal_capacity() << '\n'; - std::cout << "sizeof(small_vector): " << sizeof(small_vector) << " extra: " << small_vector::needed_extra_storages << " internal storage: " << small_vector::internal_capacity() << '\n'; - std::cout << "sizeof(small_vector): " << sizeof(small_vector) << " extra: " << small_vector::needed_extra_storages << " internal storage: " << small_vector::internal_capacity() << '\n'; - std::cout << "sizeof(small_vector): " << sizeof(small_vector) << " extra: " << small_vector::needed_extra_storages << " internal storage: " << small_vector::internal_capacity() << '\n'; -*/ if(test::vector_test< small_vector >()) return 1; if(test::vector_test< small_vector >()) return 1; - //////////////////////////////////// // Default init test ////////////////////////////////////