From 5013f3fd69ff41f3d8b5e0622aede9bc14637aed Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ion=20Gazta=C3=B1aga?= Date: Mon, 21 Apr 2014 21:23:24 +0200 Subject: [PATCH] Fixes #9931 ("flat_map::insert(ordered_unique_range_t...) fails with move_iterators") --- doc/container.qbk | 1 + include/boost/container/detail/flat_tree.hpp | 24 ++++++++++++-------- 2 files changed, 15 insertions(+), 10 deletions(-) diff --git a/doc/container.qbk b/doc/container.qbk index bd54711..03d7d77 100644 --- a/doc/container.qbk +++ b/doc/container.qbk @@ -965,6 +965,7 @@ use [*Boost.Container]? There are several reasons for that: * [@https://svn.boost.org/trac/boost/ticket/9648 #9648: ['"string construction optimization - char_traits::copy could be used ..."]]. * [@https://svn.boost.org/trac/boost/ticket/9915 #9915: ['"Documentation issues regarding vector constructors and resize methods - value/default initialization"]]. * [@https://svn.boost.org/trac/boost/ticket/9916 #9916: ['"Allocator propagation incorrect in the assignment operator of most"]]. + * [@https://svn.boost.org/trac/boost/ticket/9931 #9931: ['"flat_map::insert(ordered_unique_range_t...) fails with move_iterators"]]. * [@https://svn.boost.org/trac/boost/ticket/9932 #9932: ['"Missing assignment operator from related static_vector"]]. [endsect] diff --git a/include/boost/container/detail/flat_tree.hpp b/include/boost/container/detail/flat_tree.hpp index d3f9ee6..2988ebb 100644 --- a/include/boost/container/detail/flat_tree.hpp +++ b/include/boost/container/detail/flat_tree.hpp @@ -481,14 +481,17 @@ class flat_tree const const_iterator ce(this->cend()); len -= burst; for(size_type i = 0; i != burst; ++i){ - //Get the insertion position for each key - pos = const_cast(*this).priv_upper_bound(pos, ce, KeyOfValue()(*first)); + //Get the insertion position for each key, use std::iterator_traits::value_type + //because it can be different from container::value_type + //(e.g. conversion between std::pair -> boost::container::pair + const typename std::iterator_traits::value_type & val = *first; + pos = const_cast(*this).priv_upper_bound(pos, ce, KeyOfValue()(val)); positions[i] = static_cast(pos - b); ++first; } //Insert all in a single step in the precalculated positions this->m_data.m_vect.insert_ordered_at(burst, positions + burst, first); - //Next search position updated + //Next search position updated, iterator still valid because we've preserved the vector pos += burst; } } @@ -537,15 +540,16 @@ class flat_tree size_type unique_burst = 0u; const const_iterator ce(this->cend()); while(unique_burst < burst && len > 0){ - //Get the insertion position for each key - const value_type & val = *first++; + //Get the insertion position for each key, use std::iterator_traits::value_type + //because it can be different from container::value_type + //(e.g. conversion between std::pair -> boost::container::pair + const typename std::iterator_traits::value_type & val = *first; + ++first; --len; pos = const_cast(*this).priv_lower_bound(pos, ce, KeyOfValue()(val)); //Check if already present - if(pos != ce && !val_cmp(val, *pos)){ - if(unique_burst > 0){ - ++skips[unique_burst-1]; - } + if (pos != ce && !val_cmp(val, *pos)){ + skips[unique_burst-1] += static_cast(unique_burst > 0); continue; } @@ -556,7 +560,7 @@ class flat_tree if(unique_burst){ //Insert all in a single step in the precalculated positions this->m_data.m_vect.insert_ordered_at(unique_burst, positions + unique_burst, skips + unique_burst, first); - //Next search position updated + //Next search position updated, iterator still valid because we've preserved the vector pos += unique_burst; } }