mirror of
https://github.com/boostorg/container.git
synced 2025-08-02 14:04:26 +02:00
* Fixed BOOST_CONTAINER_NOEXCEPT_IF(allocator_traits_type::propagate_on_container_move_assignment) missing ::value
* Optimized insert_equal(ordered_range_t,...) and insert_unique(ordered_unique_range_t, ...) for elements to be inserted in the end. * Added range insertion overload (non-standard extension) to vector taking the number of elements to avoid reiterations with std::distance.
This commit is contained in:
@@ -713,7 +713,7 @@ class deque : protected deque_base<Allocator>
|
|||||||
//! propagate_on_container_move_assignment is true or
|
//! propagate_on_container_move_assignment is true or
|
||||||
//! this->get>allocator() == x.get_allocator(). Linear otherwise.
|
//! this->get>allocator() == x.get_allocator(). Linear otherwise.
|
||||||
deque& operator= (BOOST_RV_REF(deque) x)
|
deque& operator= (BOOST_RV_REF(deque) x)
|
||||||
BOOST_CONTAINER_NOEXCEPT_IF(allocator_traits_type::propagate_on_container_move_assignment)
|
BOOST_CONTAINER_NOEXCEPT_IF(allocator_traits_type::propagate_on_container_move_assignment::value)
|
||||||
{
|
{
|
||||||
BOOST_ASSERT(this != &x);
|
BOOST_ASSERT(this != &x);
|
||||||
allocator_type &this_alloc = this->alloc();
|
allocator_type &this_alloc = this->alloc();
|
||||||
|
@@ -476,24 +476,36 @@ class flat_tree
|
|||||||
const const_iterator b(this->cbegin());
|
const const_iterator b(this->cbegin());
|
||||||
const_iterator pos(b);
|
const_iterator pos(b);
|
||||||
//Loop in burst sizes
|
//Loop in burst sizes
|
||||||
while(len){
|
bool back_insert = false;
|
||||||
const size_type burst = len < BurstSize ? len : BurstSize;
|
while(len && !back_insert){
|
||||||
|
size_type burst = len < BurstSize ? len : BurstSize;
|
||||||
const const_iterator ce(this->cend());
|
const const_iterator ce(this->cend());
|
||||||
len -= burst;
|
|
||||||
for(size_type i = 0; i != burst; ++i){
|
for(size_type i = 0; i != burst; ++i){
|
||||||
//Get the insertion position for each key, use std::iterator_traits<BidirIt>::value_type
|
//Get the insertion position for each key, use std::iterator_traits<BidirIt>::value_type
|
||||||
//because it can be different from container::value_type
|
//because it can be different from container::value_type
|
||||||
//(e.g. conversion between std::pair<A, B> -> boost::container::pair<A, B>
|
//(e.g. conversion between std::pair<A, B> -> boost::container::pair<A, B>
|
||||||
const typename std::iterator_traits<BidirIt>::value_type & val = *first;
|
const typename std::iterator_traits<BidirIt>::value_type & val = *first;
|
||||||
pos = const_cast<const flat_tree&>(*this).priv_upper_bound(pos, ce, KeyOfValue()(val));
|
pos = const_cast<const flat_tree&>(*this).priv_upper_bound(pos, ce, KeyOfValue()(val));
|
||||||
positions[i] = static_cast<size_type>(pos - b);
|
if(pos == this->cend()){ //this element and the remaining should be back inserted
|
||||||
++first;
|
burst = i;
|
||||||
|
back_insert = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
positions[i] = static_cast<size_type>(pos - b);
|
||||||
|
++first;
|
||||||
|
--len;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
//Insert all in a single step in the precalculated positions
|
//Insert all in a single step in the precalculated positions
|
||||||
this->m_data.m_vect.insert_ordered_at(burst, positions + burst, first);
|
this->m_data.m_vect.insert_ordered_at(burst, positions + burst, first);
|
||||||
//Next search position updated, iterator still valid because we've preserved the vector
|
//Next search position updated, iterator still valid because we've preserved the vector
|
||||||
pos += burst;
|
pos += burst;
|
||||||
}
|
}
|
||||||
|
if(first != last){
|
||||||
|
//The remaining range should be back inserted
|
||||||
|
this->m_data.m_vect.insert(this->m_data.m_vect.cend(), len, first, last);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class InIt>
|
template <class InIt>
|
||||||
@@ -535,7 +547,8 @@ class flat_tree
|
|||||||
const value_compare &val_cmp = this->m_data;
|
const value_compare &val_cmp = this->m_data;
|
||||||
skips[0u] = 0u;
|
skips[0u] = 0u;
|
||||||
//Loop in burst sizes
|
//Loop in burst sizes
|
||||||
while(len){
|
bool back_insert = false;
|
||||||
|
while(len && !back_insert){
|
||||||
const size_type burst = len < BurstSize ? len : BurstSize;
|
const size_type burst = len < BurstSize ? len : BurstSize;
|
||||||
size_type unique_burst = 0u;
|
size_type unique_burst = 0u;
|
||||||
const const_iterator ce(this->cend());
|
const const_iterator ce(this->cend());
|
||||||
@@ -544,20 +557,25 @@ class flat_tree
|
|||||||
//because it can be different from container::value_type
|
//because it can be different from container::value_type
|
||||||
//(e.g. conversion between std::pair<A, B> -> boost::container::pair<A, B>
|
//(e.g. conversion between std::pair<A, B> -> boost::container::pair<A, B>
|
||||||
const typename std::iterator_traits<BidirIt>::value_type & val = *first;
|
const typename std::iterator_traits<BidirIt>::value_type & val = *first;
|
||||||
++first;
|
|
||||||
--len;
|
|
||||||
pos = const_cast<const flat_tree&>(*this).priv_lower_bound(pos, ce, KeyOfValue()(val));
|
pos = const_cast<const flat_tree&>(*this).priv_lower_bound(pos, ce, KeyOfValue()(val));
|
||||||
//Check if already present
|
//Check if already present
|
||||||
if (pos != ce && !val_cmp(val, *pos)){
|
if (pos != ce){
|
||||||
if(unique_burst > 0){
|
++first;
|
||||||
++skips[unique_burst-1];
|
--len;
|
||||||
|
if(!val_cmp(val, *pos)){
|
||||||
|
if(unique_burst > 0){
|
||||||
|
++skips[unique_burst-1];
|
||||||
|
}
|
||||||
|
continue;
|
||||||
}
|
}
|
||||||
continue;
|
//If not present, calculate position
|
||||||
|
positions[unique_burst] = static_cast<size_type>(pos - b);
|
||||||
|
skips[unique_burst++] = 0u;
|
||||||
|
}
|
||||||
|
else{ //this element and the remaining should be back inserted
|
||||||
|
back_insert = true;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
//If not present, calculate position
|
|
||||||
positions[unique_burst] = static_cast<size_type>(pos - b);
|
|
||||||
skips[unique_burst++] = 0u;
|
|
||||||
}
|
}
|
||||||
if(unique_burst){
|
if(unique_burst){
|
||||||
//Insert all in a single step in the precalculated positions
|
//Insert all in a single step in the precalculated positions
|
||||||
@@ -566,6 +584,10 @@ class flat_tree
|
|||||||
pos += unique_burst;
|
pos += unique_burst;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if(first != last){
|
||||||
|
//The remaining range should be back inserted
|
||||||
|
this->m_data.m_vect.insert(this->m_data.m_vect.cend(), len, first, last);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef BOOST_CONTAINER_PERFECT_FORWARDING
|
#ifdef BOOST_CONTAINER_PERFECT_FORWARDING
|
||||||
|
@@ -283,7 +283,7 @@ class flat_map
|
|||||||
//! propagate_on_container_move_assignment is true or
|
//! propagate_on_container_move_assignment is true or
|
||||||
//! this->get>allocator() == x.get_allocator(). Linear otherwise.
|
//! this->get>allocator() == x.get_allocator(). Linear otherwise.
|
||||||
flat_map& operator=(BOOST_RV_REF(flat_map) x)
|
flat_map& operator=(BOOST_RV_REF(flat_map) x)
|
||||||
BOOST_CONTAINER_NOEXCEPT_IF(allocator_traits_type::propagate_on_container_move_assignment)
|
BOOST_CONTAINER_NOEXCEPT_IF(allocator_traits_type::propagate_on_container_move_assignment::value)
|
||||||
{ m_flat_tree = boost::move(x.m_flat_tree); return *this; }
|
{ m_flat_tree = boost::move(x.m_flat_tree); return *this; }
|
||||||
|
|
||||||
//! <b>Effects</b>: Returns a copy of the Allocator that
|
//! <b>Effects</b>: Returns a copy of the Allocator that
|
||||||
@@ -1176,7 +1176,7 @@ class flat_multimap
|
|||||||
//!
|
//!
|
||||||
//! <b>Complexity</b>: Constant.
|
//! <b>Complexity</b>: Constant.
|
||||||
flat_multimap& operator=(BOOST_RV_REF(flat_multimap) x)
|
flat_multimap& operator=(BOOST_RV_REF(flat_multimap) x)
|
||||||
BOOST_CONTAINER_NOEXCEPT_IF(allocator_traits_type::propagate_on_container_move_assignment)
|
BOOST_CONTAINER_NOEXCEPT_IF(allocator_traits_type::propagate_on_container_move_assignment::value)
|
||||||
{ m_flat_tree = boost::move(x.m_flat_tree); return *this; }
|
{ m_flat_tree = boost::move(x.m_flat_tree); return *this; }
|
||||||
|
|
||||||
//! <b>Effects</b>: Returns a copy of the Allocator that
|
//! <b>Effects</b>: Returns a copy of the Allocator that
|
||||||
|
@@ -189,7 +189,7 @@ class flat_set
|
|||||||
//! propagate_on_container_move_assignment is true or
|
//! propagate_on_container_move_assignment is true or
|
||||||
//! this->get>allocator() == x.get_allocator(). Linear otherwise.
|
//! this->get>allocator() == x.get_allocator(). Linear otherwise.
|
||||||
flat_set& operator=(BOOST_RV_REF(flat_set) x)
|
flat_set& operator=(BOOST_RV_REF(flat_set) x)
|
||||||
BOOST_CONTAINER_NOEXCEPT_IF(allocator_traits_type::propagate_on_container_move_assignment)
|
BOOST_CONTAINER_NOEXCEPT_IF(allocator_traits_type::propagate_on_container_move_assignment::value)
|
||||||
{ return static_cast<flat_set&>(this->base_t::operator=(boost::move(static_cast<base_t&>(x)))); }
|
{ return static_cast<flat_set&>(this->base_t::operator=(boost::move(static_cast<base_t&>(x)))); }
|
||||||
|
|
||||||
#ifdef BOOST_CONTAINER_DOXYGEN_INVOKED
|
#ifdef BOOST_CONTAINER_DOXYGEN_INVOKED
|
||||||
@@ -810,7 +810,7 @@ class flat_multiset
|
|||||||
|
|
||||||
//! @copydoc ::boost::container::flat_set::operator=(flat_set &&)
|
//! @copydoc ::boost::container::flat_set::operator=(flat_set &&)
|
||||||
flat_multiset& operator=(BOOST_RV_REF(flat_multiset) mx)
|
flat_multiset& operator=(BOOST_RV_REF(flat_multiset) mx)
|
||||||
BOOST_CONTAINER_NOEXCEPT_IF(allocator_traits_type::propagate_on_container_move_assignment)
|
BOOST_CONTAINER_NOEXCEPT_IF(allocator_traits_type::propagate_on_container_move_assignment::value)
|
||||||
{ return static_cast<flat_multiset&>(this->base_t::operator=(boost::move(static_cast<base_t&>(mx)))); }
|
{ return static_cast<flat_multiset&>(this->base_t::operator=(boost::move(static_cast<base_t&>(mx)))); }
|
||||||
|
|
||||||
#if defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
|
#if defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
|
||||||
|
@@ -344,7 +344,7 @@ class list
|
|||||||
//! propagate_on_container_move_assignment is true or
|
//! propagate_on_container_move_assignment is true or
|
||||||
//! this->get>allocator() == x.get_allocator(). Linear otherwise.
|
//! this->get>allocator() == x.get_allocator(). Linear otherwise.
|
||||||
list& operator=(BOOST_RV_REF(list) x)
|
list& operator=(BOOST_RV_REF(list) x)
|
||||||
BOOST_CONTAINER_NOEXCEPT_IF(allocator_traits_type::propagate_on_container_move_assignment)
|
BOOST_CONTAINER_NOEXCEPT_IF(allocator_traits_type::propagate_on_container_move_assignment::value)
|
||||||
{
|
{
|
||||||
BOOST_ASSERT(this != &x);
|
BOOST_ASSERT(this != &x);
|
||||||
NodeAlloc &this_alloc = this->node_alloc();
|
NodeAlloc &this_alloc = this->node_alloc();
|
||||||
|
@@ -240,7 +240,7 @@ class map
|
|||||||
//! propagate_on_container_move_assignment is true or
|
//! propagate_on_container_move_assignment is true or
|
||||||
//! this->get>allocator() == x.get_allocator(). Linear otherwise.
|
//! this->get>allocator() == x.get_allocator(). Linear otherwise.
|
||||||
map& operator=(BOOST_RV_REF(map) x)
|
map& operator=(BOOST_RV_REF(map) x)
|
||||||
BOOST_CONTAINER_NOEXCEPT_IF(allocator_traits_type::propagate_on_container_move_assignment)
|
BOOST_CONTAINER_NOEXCEPT_IF(allocator_traits_type::propagate_on_container_move_assignment::value)
|
||||||
{ return static_cast<map&>(this->base_t::operator=(boost::move(static_cast<base_t&>(x)))); }
|
{ return static_cast<map&>(this->base_t::operator=(boost::move(static_cast<base_t&>(x)))); }
|
||||||
|
|
||||||
#if defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
|
#if defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
|
||||||
|
@@ -192,7 +192,7 @@ class set
|
|||||||
//! propagate_on_container_move_assignment is true or
|
//! propagate_on_container_move_assignment is true or
|
||||||
//! this->get>allocator() == x.get_allocator(). Linear otherwise.
|
//! this->get>allocator() == x.get_allocator(). Linear otherwise.
|
||||||
set& operator=(BOOST_RV_REF(set) x)
|
set& operator=(BOOST_RV_REF(set) x)
|
||||||
BOOST_CONTAINER_NOEXCEPT_IF(allocator_traits_type::propagate_on_container_move_assignment)
|
BOOST_CONTAINER_NOEXCEPT_IF(allocator_traits_type::propagate_on_container_move_assignment::value)
|
||||||
{ return static_cast<set&>(this->base_t::operator=(boost::move(static_cast<base_t&>(x)))); }
|
{ return static_cast<set&>(this->base_t::operator=(boost::move(static_cast<base_t&>(x)))); }
|
||||||
|
|
||||||
#if defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
|
#if defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
|
||||||
|
@@ -365,7 +365,7 @@ class slist
|
|||||||
//! propagate_on_container_move_assignment is true or
|
//! propagate_on_container_move_assignment is true or
|
||||||
//! this->get>allocator() == x.get_allocator(). Linear otherwise.
|
//! this->get>allocator() == x.get_allocator(). Linear otherwise.
|
||||||
slist& operator= (BOOST_RV_REF(slist) x)
|
slist& operator= (BOOST_RV_REF(slist) x)
|
||||||
BOOST_CONTAINER_NOEXCEPT_IF(allocator_traits_type::propagate_on_container_move_assignment)
|
BOOST_CONTAINER_NOEXCEPT_IF(allocator_traits_type::propagate_on_container_move_assignment::value)
|
||||||
{
|
{
|
||||||
BOOST_ASSERT(this != &x);
|
BOOST_ASSERT(this != &x);
|
||||||
NodeAlloc &this_alloc = this->node_alloc();
|
NodeAlloc &this_alloc = this->node_alloc();
|
||||||
|
@@ -750,7 +750,7 @@ class stable_vector
|
|||||||
//! propagate_on_container_move_assignment is true or
|
//! propagate_on_container_move_assignment is true or
|
||||||
//! this->get>allocator() == x.get_allocator(). Linear otherwise.
|
//! this->get>allocator() == x.get_allocator(). Linear otherwise.
|
||||||
stable_vector& operator=(BOOST_RV_REF(stable_vector) x)
|
stable_vector& operator=(BOOST_RV_REF(stable_vector) x)
|
||||||
BOOST_CONTAINER_NOEXCEPT_IF(allocator_traits_type::propagate_on_container_move_assignment)
|
BOOST_CONTAINER_NOEXCEPT_IF(allocator_traits_type::propagate_on_container_move_assignment::value)
|
||||||
{
|
{
|
||||||
//for move constructor, no aliasing (&x != this) is assummed.
|
//for move constructor, no aliasing (&x != this) is assummed.
|
||||||
BOOST_ASSERT(this != &x);
|
BOOST_ASSERT(this != &x);
|
||||||
|
@@ -742,7 +742,7 @@ class basic_string
|
|||||||
//! propagate_on_container_move_assignment is true or
|
//! propagate_on_container_move_assignment is true or
|
||||||
//! this->get>allocator() == x.get_allocator(). Linear otherwise.
|
//! this->get>allocator() == x.get_allocator(). Linear otherwise.
|
||||||
basic_string& operator=(BOOST_RV_REF(basic_string) x)
|
basic_string& operator=(BOOST_RV_REF(basic_string) x)
|
||||||
BOOST_CONTAINER_NOEXCEPT_IF(allocator_traits_type::propagate_on_container_move_assignment)
|
BOOST_CONTAINER_NOEXCEPT_IF(allocator_traits_type::propagate_on_container_move_assignment::value)
|
||||||
{
|
{
|
||||||
//for move constructor, no aliasing (&x != this) is assummed.
|
//for move constructor, no aliasing (&x != this) is assummed.
|
||||||
BOOST_ASSERT(this != &x);
|
BOOST_ASSERT(this != &x);
|
||||||
|
@@ -820,7 +820,7 @@ class vector
|
|||||||
//! propagate_on_container_move_assignment is true or
|
//! propagate_on_container_move_assignment is true or
|
||||||
//! this->get>allocator() == x.get_allocator(). Linear otherwise.
|
//! this->get>allocator() == x.get_allocator(). Linear otherwise.
|
||||||
vector& operator=(BOOST_RV_REF(vector) x)
|
vector& operator=(BOOST_RV_REF(vector) x)
|
||||||
BOOST_CONTAINER_NOEXCEPT_IF(allocator_traits_type::propagate_on_container_move_assignment)
|
BOOST_CONTAINER_NOEXCEPT_IF(allocator_traits_type::propagate_on_container_move_assignment::value)
|
||||||
{
|
{
|
||||||
this->priv_move_assign(boost::move(x));
|
this->priv_move_assign(boost::move(x));
|
||||||
return *this;
|
return *this;
|
||||||
@@ -1509,6 +1509,32 @@ class vector
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
//! <b>Requires</b>: p must be a valid iterator of *this. num, must
|
||||||
|
//! be equal to std::distance(first, last)
|
||||||
|
//!
|
||||||
|
//! <b>Effects</b>: Insert a copy of the [first, last) range before pos.
|
||||||
|
//!
|
||||||
|
//! <b>Returns</b>: an iterator to the first inserted element or pos if first == last.
|
||||||
|
//!
|
||||||
|
//! <b>Throws</b>: If memory allocation throws, T's constructor from a
|
||||||
|
//! dereferenced InpIt throws or T's copy/move constructor/assignment throws.
|
||||||
|
//!
|
||||||
|
//! <b>Complexity</b>: Linear to std::distance [first, last).
|
||||||
|
//!
|
||||||
|
//! <b>Note</b>: This function avoids a linear operation to calculate std::distance[first, last)
|
||||||
|
//! for forward and bidirectional iterators, and a one by one insertion for input iterators. This is a
|
||||||
|
//! a non-standard extension.
|
||||||
|
#if !defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
|
||||||
|
template <class InIt>
|
||||||
|
iterator insert(const_iterator pos, size_type num, InIt first, InIt last)
|
||||||
|
{
|
||||||
|
BOOST_ASSERT(container_detail::is_input_iterator<InIt>::value ||
|
||||||
|
num == static_cast<size_type>(std::distance(first, last)));
|
||||||
|
container_detail::insert_range_proxy<Allocator, InIt, T*> proxy(first);
|
||||||
|
return this->priv_forward_range_insert(vector_iterator_get_ptr(pos), num, proxy, alloc_version());
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
//! <b>Effects</b>: Removes the last element from the vector.
|
//! <b>Effects</b>: Removes the last element from the vector.
|
||||||
//!
|
//!
|
||||||
//! <b>Throws</b>: Nothing.
|
//! <b>Throws</b>: Nothing.
|
||||||
@@ -1649,7 +1675,7 @@ class vector
|
|||||||
void insert_ordered_at(size_type element_count, BiDirPosConstIt last_position_it, BiDirValueIt last_value_it)
|
void insert_ordered_at(size_type element_count, BiDirPosConstIt last_position_it, BiDirValueIt last_value_it)
|
||||||
{
|
{
|
||||||
const size_type *dummy = 0;
|
const size_type *dummy = 0;
|
||||||
this->priv_insert_ordered_at(element_count, last_position_it, false, &dummy[0], last_value_it);
|
this->priv_insert_ordered_at(element_count, last_position_it, false, dummy, last_value_it);
|
||||||
}
|
}
|
||||||
|
|
||||||
//Absolutely experimental. This function might change, disappear or simply crash!
|
//Absolutely experimental. This function might change, disappear or simply crash!
|
||||||
|
Reference in New Issue
Block a user