mirror of
https://github.com/boostorg/container.git
synced 2025-08-02 14:04:26 +02:00
Add improved range insertion to flat associative containers and improve merge operation for vector.
This commit is contained in:
@@ -1237,6 +1237,8 @@ use [*Boost.Container]? There are several reasons for that:
|
|||||||
* ['vector] can now have options, using [classref boost::container::vector_options vector_options].
|
* ['vector] can now have options, using [classref boost::container::vector_options vector_options].
|
||||||
The growth factor and the stored size type can be specified.
|
The growth factor and the stored size type can be specified.
|
||||||
|
|
||||||
|
* Improved range insertion in ['flat_[multi]map/set] containers overall complexity is reduced to O(NlogN).
|
||||||
|
|
||||||
* Fixed bugs:
|
* Fixed bugs:
|
||||||
* [@https://github.com/boostorg/container/pull/64 GitHub #64: ['"Fix splice for slist"]].
|
* [@https://github.com/boostorg/container/pull/64 GitHub #64: ['"Fix splice for slist"]].
|
||||||
|
|
||||||
|
@@ -116,6 +116,56 @@ namespace dtl {
|
|||||||
|
|
||||||
BOOST_INTRUSIVE_INSTANTIATE_DEFAULT_TYPE_TMPLT(stored_allocator_type)
|
BOOST_INTRUSIVE_INSTANTIATE_DEFAULT_TYPE_TMPLT(stored_allocator_type)
|
||||||
|
|
||||||
|
///////////////////////////////////////
|
||||||
|
//
|
||||||
|
// flat_tree_container_inplace_merge
|
||||||
|
//
|
||||||
|
///////////////////////////////////////
|
||||||
|
template<class SequenceContainer, class Compare>
|
||||||
|
void flat_tree_container_inplace_merge //is_contiguous_container == true
|
||||||
|
(SequenceContainer& dest, typename SequenceContainer::iterator it, Compare comp , dtl::true_)
|
||||||
|
{
|
||||||
|
typedef typename SequenceContainer::value_type value_type;
|
||||||
|
value_type *const braw = boost::movelib::iterator_to_raw_pointer(dest.begin());
|
||||||
|
value_type *const iraw = boost::movelib::iterator_to_raw_pointer(it);
|
||||||
|
value_type *const eraw = boost::movelib::iterator_to_raw_pointer(dest.end());
|
||||||
|
boost::movelib::adaptive_merge(braw, iraw, eraw, comp, eraw, dest.capacity()- dest.size());
|
||||||
|
}
|
||||||
|
|
||||||
|
template<class SequenceContainer, class Compare>
|
||||||
|
void flat_tree_container_inplace_merge //is_contiguous_container == false
|
||||||
|
(SequenceContainer& dest, typename SequenceContainer::iterator it, Compare comp, dtl::false_)
|
||||||
|
{
|
||||||
|
boost::movelib::adaptive_merge(dest.begin(), it, dest.end(), comp);
|
||||||
|
}
|
||||||
|
|
||||||
|
///////////////////////////////////////
|
||||||
|
//
|
||||||
|
// flat_tree_container_inplace_sort_ending
|
||||||
|
//
|
||||||
|
///////////////////////////////////////
|
||||||
|
template<class SequenceContainer, class Compare>
|
||||||
|
void flat_tree_container_inplace_sort_ending //is_contiguous_container == true
|
||||||
|
(SequenceContainer& dest, typename SequenceContainer::iterator it, Compare comp, dtl::true_)
|
||||||
|
{
|
||||||
|
typedef typename SequenceContainer::value_type value_type;
|
||||||
|
value_type *const iraw = boost::movelib::iterator_to_raw_pointer(it);
|
||||||
|
value_type *const eraw = boost::movelib::iterator_to_raw_pointer(dest.end());
|
||||||
|
boost::movelib::adaptive_sort(iraw, eraw, comp, eraw, dest.capacity()- dest.size());
|
||||||
|
}
|
||||||
|
|
||||||
|
template<class SequenceContainer, class Compare>
|
||||||
|
void flat_tree_container_inplace_sort_ending //is_contiguous_container == false
|
||||||
|
(SequenceContainer& dest, typename SequenceContainer::iterator it, Compare comp , dtl::false_)
|
||||||
|
{
|
||||||
|
boost::movelib::adaptive_sort(it, dest.end(), comp);
|
||||||
|
}
|
||||||
|
|
||||||
|
///////////////////////////////////////
|
||||||
|
//
|
||||||
|
// flat_tree_merge
|
||||||
|
//
|
||||||
|
///////////////////////////////////////
|
||||||
template<class SequenceContainer, class Iterator, class Compare>
|
template<class SequenceContainer, class Iterator, class Compare>
|
||||||
BOOST_CONTAINER_FORCEINLINE void flat_tree_merge_equal
|
BOOST_CONTAINER_FORCEINLINE void flat_tree_merge_equal
|
||||||
(SequenceContainer& dest, Iterator first, Iterator last, Compare comp, dtl::true_)
|
(SequenceContainer& dest, Iterator first, Iterator last, Compare comp, dtl::true_)
|
||||||
@@ -123,43 +173,21 @@ BOOST_CONTAINER_FORCEINLINE void flat_tree_merge_equal
|
|||||||
dest.merge(first, last, comp);
|
dest.merge(first, last, comp);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<class SequenceContainer, class Iterator, class Compare>
|
|
||||||
void aux_flat_tree_merge_equal_non_merge_member //is_contiguous_container == true
|
|
||||||
(SequenceContainer& dest, Iterator first, Iterator last, Compare comp, dtl::true_)
|
|
||||||
{
|
|
||||||
typedef typename SequenceContainer::iterator iterator;
|
|
||||||
typedef typename SequenceContainer::value_type value_type;
|
|
||||||
typedef typename SequenceContainer::size_type size_type;
|
|
||||||
|
|
||||||
iterator const it = dest.insert( dest.end(), first, last );
|
|
||||||
value_type *const braw = boost::movelib::iterator_to_raw_pointer(dest.begin());
|
|
||||||
value_type *const iraw = boost::movelib::iterator_to_raw_pointer(it);
|
|
||||||
value_type *const eraw = boost::movelib::iterator_to_raw_pointer(dest.end());
|
|
||||||
value_type *const sraw = boost::movelib::iterator_to_raw_pointer(dest.begin())+dest.size();
|
|
||||||
size_type const sraw_size = dest.capacity()- dest.size();
|
|
||||||
boost::movelib::adaptive_sort(iraw, eraw, comp, sraw, sraw_size);
|
|
||||||
boost::movelib::adaptive_merge(braw, iraw, eraw, comp, sraw, sraw_size);
|
|
||||||
}
|
|
||||||
|
|
||||||
template<class SequenceContainer, class Iterator, class Compare>
|
|
||||||
void aux_flat_tree_merge_equal_non_merge_member //is_contiguous_container == false
|
|
||||||
(SequenceContainer& dest, Iterator first, Iterator last, Compare comp, dtl::false_)
|
|
||||||
{
|
|
||||||
typedef typename SequenceContainer::iterator iterator;
|
|
||||||
|
|
||||||
iterator const it = dest.insert( dest.end(), first, last );
|
|
||||||
boost::movelib::adaptive_sort(it, dest.end(), comp);
|
|
||||||
boost::movelib::adaptive_merge(dest.begin(), it, dest.end(), comp);
|
|
||||||
}
|
|
||||||
|
|
||||||
template<class SequenceContainer, class Iterator, class Compare>
|
template<class SequenceContainer, class Iterator, class Compare>
|
||||||
BOOST_CONTAINER_FORCEINLINE void flat_tree_merge_equal //has_merge_unique == false
|
BOOST_CONTAINER_FORCEINLINE void flat_tree_merge_equal //has_merge_unique == false
|
||||||
(SequenceContainer& dest, Iterator first, Iterator last, Compare comp, dtl::false_)
|
(SequenceContainer& dest, Iterator first, Iterator last, Compare comp, dtl::false_)
|
||||||
{
|
{
|
||||||
(aux_flat_tree_merge_equal_non_merge_member)
|
typedef typename SequenceContainer::iterator iterator;
|
||||||
( dest, first, last, comp, dtl::bool_<is_contiguous_container<SequenceContainer>::value>());
|
iterator const it = dest.insert( dest.end(), first, last );
|
||||||
|
dtl::bool_<is_contiguous_container<SequenceContainer>::value> contiguous_tag;
|
||||||
|
(flat_tree_container_inplace_merge)(dest, it, comp, contiguous_tag);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
///////////////////////////////////////
|
||||||
|
//
|
||||||
|
// flat_tree_merge_unique
|
||||||
|
//
|
||||||
|
///////////////////////////////////////
|
||||||
template<class SequenceContainer, class Iterator, class Compare>
|
template<class SequenceContainer, class Iterator, class Compare>
|
||||||
BOOST_CONTAINER_FORCEINLINE void flat_tree_merge_unique //has_merge_unique == true
|
BOOST_CONTAINER_FORCEINLINE void flat_tree_merge_unique //has_merge_unique == true
|
||||||
(SequenceContainer& dest, Iterator first, Iterator last, Compare comp, dtl::true_)
|
(SequenceContainer& dest, Iterator first, Iterator last, Compare comp, dtl::true_)
|
||||||
@@ -171,11 +199,22 @@ template<class SequenceContainer, class Iterator, class Compare>
|
|||||||
BOOST_CONTAINER_FORCEINLINE void flat_tree_merge_unique //has_merge_unique == false
|
BOOST_CONTAINER_FORCEINLINE void flat_tree_merge_unique //has_merge_unique == false
|
||||||
(SequenceContainer& dest, Iterator first, Iterator last, Compare comp, dtl::false_)
|
(SequenceContainer& dest, Iterator first, Iterator last, Compare comp, dtl::false_)
|
||||||
{
|
{
|
||||||
(flat_tree_merge_equal)(dest, first, last, comp, dtl::false_());
|
typedef typename SequenceContainer::iterator iterator;
|
||||||
dest.erase(boost::movelib::unique
|
typedef typename SequenceContainer::size_type size_type;
|
||||||
(dest.begin(), dest.end(), boost::movelib::negate<Compare>(comp)), dest.cend());
|
|
||||||
|
size_type const old_sz = dest.size();
|
||||||
|
iterator const first_new = dest.insert(dest.cend(), first, last );
|
||||||
|
iterator e = boost::movelib::inplace_set_difference(first_new, dest.end(), dest.begin(), first_new, comp);
|
||||||
|
dest.erase(e, dest.end());
|
||||||
|
dtl::bool_<is_contiguous_container<SequenceContainer>::value> contiguous_tag;
|
||||||
|
(flat_tree_container_inplace_merge)(dest, dest.begin()+old_sz, comp, contiguous_tag);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
///////////////////////////////////////
|
||||||
|
//
|
||||||
|
// flat_tree_index_of
|
||||||
|
//
|
||||||
|
///////////////////////////////////////
|
||||||
template<class SequenceContainer, class Iterator>
|
template<class SequenceContainer, class Iterator>
|
||||||
BOOST_CONTAINER_FORCEINLINE typename SequenceContainer::size_type
|
BOOST_CONTAINER_FORCEINLINE typename SequenceContainer::size_type
|
||||||
flat_tree_index_of // has_index_of == true
|
flat_tree_index_of // has_index_of == true
|
||||||
@@ -193,6 +232,11 @@ BOOST_CONTAINER_FORCEINLINE typename SequenceContainer::size_type
|
|||||||
return static_cast<size_type>(p - cont.begin());
|
return static_cast<size_type>(p - cont.begin());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
///////////////////////////////////////
|
||||||
|
//
|
||||||
|
// flat_tree_nth
|
||||||
|
//
|
||||||
|
///////////////////////////////////////
|
||||||
template<class Iterator, class SequenceContainer>
|
template<class Iterator, class SequenceContainer>
|
||||||
BOOST_CONTAINER_FORCEINLINE Iterator
|
BOOST_CONTAINER_FORCEINLINE Iterator
|
||||||
flat_tree_nth // has_nth == true
|
flat_tree_nth // has_nth == true
|
||||||
@@ -209,6 +253,11 @@ BOOST_CONTAINER_FORCEINLINE Iterator
|
|||||||
return cont.begin()+ n;
|
return cont.begin()+ n;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
///////////////////////////////////////
|
||||||
|
//
|
||||||
|
// flat_tree_get_stored_allocator
|
||||||
|
//
|
||||||
|
///////////////////////////////////////
|
||||||
template<class SequenceContainer>
|
template<class SequenceContainer>
|
||||||
BOOST_CONTAINER_FORCEINLINE typename SequenceContainer::stored_allocator_type &
|
BOOST_CONTAINER_FORCEINLINE typename SequenceContainer::stored_allocator_type &
|
||||||
flat_tree_get_stored_allocator // has_get_stored_allocator == true
|
flat_tree_get_stored_allocator // has_get_stored_allocator == true
|
||||||
@@ -233,17 +282,39 @@ BOOST_CONTAINER_FORCEINLINE typename SequenceContainer::allocator_type
|
|||||||
return cont.get_allocator();
|
return cont.get_allocator();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
///////////////////////////////////////
|
||||||
|
//
|
||||||
|
// flat_tree_adopt_sequence_equal
|
||||||
|
//
|
||||||
|
///////////////////////////////////////
|
||||||
template<class SequenceContainer, class Compare>
|
template<class SequenceContainer, class Compare>
|
||||||
void flat_tree_adopt_sequence_equal // is_contiguous_container == true
|
void flat_tree_sort_contiguous_to_adopt // is_contiguous_container == true
|
||||||
(SequenceContainer &tseq, BOOST_RV_REF(SequenceContainer) seq, Compare comp, dtl::true_)
|
(SequenceContainer &tseq, BOOST_RV_REF(SequenceContainer) seq, Compare comp)
|
||||||
{
|
{
|
||||||
|
if(tseq.capacity() >= (seq.capacity() - seq.size())) {
|
||||||
tseq.clear();
|
tseq.clear();
|
||||||
boost::movelib::adaptive_sort
|
boost::movelib::adaptive_sort
|
||||||
(boost::movelib::iterator_to_raw_pointer(seq.begin())
|
(boost::movelib::iterator_to_raw_pointer(seq.begin())
|
||||||
, boost::movelib::iterator_to_raw_pointer(seq.end())
|
, boost::movelib::iterator_to_raw_pointer(seq.end())
|
||||||
, comp
|
, comp
|
||||||
, boost::movelib::iterator_to_raw_pointer(tseq.begin() + tseq.size())
|
, boost::movelib::iterator_to_raw_pointer(tseq.begin())
|
||||||
, tseq.capacity() - tseq.size());
|
, tseq.capacity());
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
boost::movelib::adaptive_sort
|
||||||
|
(boost::movelib::iterator_to_raw_pointer(seq.begin())
|
||||||
|
, boost::movelib::iterator_to_raw_pointer(seq.end())
|
||||||
|
, comp
|
||||||
|
, boost::movelib::iterator_to_raw_pointer(seq.end())
|
||||||
|
, seq.capacity() - seq.size());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
template<class SequenceContainer, class Compare>
|
||||||
|
void flat_tree_adopt_sequence_equal // is_contiguous_container == true
|
||||||
|
(SequenceContainer &tseq, BOOST_RV_REF(SequenceContainer) seq, Compare comp, dtl::true_)
|
||||||
|
{
|
||||||
|
flat_tree_sort_contiguous_to_adopt(tseq, boost::move(seq), comp);
|
||||||
tseq = boost::move(seq);
|
tseq = boost::move(seq);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -255,10 +326,16 @@ void flat_tree_adopt_sequence_equal // is_contiguous_container == false
|
|||||||
tseq = boost::move(seq);
|
tseq = boost::move(seq);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
///////////////////////////////////////
|
||||||
|
//
|
||||||
|
// flat_tree_adopt_sequence_unique
|
||||||
|
//
|
||||||
|
///////////////////////////////////////
|
||||||
template<class SequenceContainer, class Compare>
|
template<class SequenceContainer, class Compare>
|
||||||
void flat_tree_adopt_sequence_unique// is_contiguous_container == true
|
void flat_tree_adopt_sequence_unique// is_contiguous_container == true
|
||||||
(SequenceContainer &tseq, BOOST_RV_REF(SequenceContainer) seq, Compare comp, dtl::true_)
|
(SequenceContainer &tseq, BOOST_RV_REF(SequenceContainer) seq, Compare comp, dtl::true_)
|
||||||
{
|
{
|
||||||
|
tseq.clear();
|
||||||
boost::movelib::adaptive_sort
|
boost::movelib::adaptive_sort
|
||||||
( boost::movelib::iterator_to_raw_pointer(seq.begin())
|
( boost::movelib::iterator_to_raw_pointer(seq.begin())
|
||||||
, boost::movelib::iterator_to_raw_pointer(seq.end())
|
, boost::movelib::iterator_to_raw_pointer(seq.end())
|
||||||
@@ -281,6 +358,11 @@ void flat_tree_adopt_sequence_unique// is_contiguous_container == false
|
|||||||
tseq = boost::move(seq);
|
tseq = boost::move(seq);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
///////////////////////////////////////
|
||||||
|
//
|
||||||
|
// flat_tree_reserve
|
||||||
|
//
|
||||||
|
///////////////////////////////////////
|
||||||
template<class SequenceContainer>
|
template<class SequenceContainer>
|
||||||
BOOST_CONTAINER_FORCEINLINE void // has_reserve == true
|
BOOST_CONTAINER_FORCEINLINE void // has_reserve == true
|
||||||
flat_tree_reserve(SequenceContainer &tseq, typename SequenceContainer::size_type cap, dtl::true_)
|
flat_tree_reserve(SequenceContainer &tseq, typename SequenceContainer::size_type cap, dtl::true_)
|
||||||
@@ -294,6 +376,11 @@ BOOST_CONTAINER_FORCEINLINE void // has_reserve == false
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
///////////////////////////////////////
|
||||||
|
//
|
||||||
|
// flat_tree_capacity
|
||||||
|
//
|
||||||
|
///////////////////////////////////////
|
||||||
template<class SequenceContainer> // has_capacity == true
|
template<class SequenceContainer> // has_capacity == true
|
||||||
BOOST_CONTAINER_FORCEINLINE typename SequenceContainer::size_type
|
BOOST_CONTAINER_FORCEINLINE typename SequenceContainer::size_type
|
||||||
flat_tree_capacity(const SequenceContainer &tseq, dtl::true_)
|
flat_tree_capacity(const SequenceContainer &tseq, dtl::true_)
|
||||||
@@ -784,108 +871,50 @@ class flat_tree
|
|||||||
template <class InIt>
|
template <class InIt>
|
||||||
void insert_unique(InIt first, InIt last)
|
void insert_unique(InIt first, InIt last)
|
||||||
{
|
{
|
||||||
for ( ; first != last; ++first){
|
dtl::bool_<is_contiguous_container<container_type>::value> contiguous_tag;
|
||||||
this->insert_unique(*first);
|
container_type &seq = this->m_data.m_seq;
|
||||||
}
|
value_compare &val_cmp = this->priv_value_comp();
|
||||||
|
|
||||||
|
//Step 1: put new elements in the back
|
||||||
|
typename container_type::iterator const it = seq.insert(seq.cend(), first, last);
|
||||||
|
|
||||||
|
//Step 2: sort them
|
||||||
|
(flat_tree_container_inplace_sort_ending)(seq, it, val_cmp, contiguous_tag);
|
||||||
|
|
||||||
|
//Step 3: only left unique values from the back not already present in the original range
|
||||||
|
typename container_type::iterator const e = boost::movelib::inplace_set_unique_difference
|
||||||
|
(it, seq.end(), seq.begin(), it, val_cmp);
|
||||||
|
seq.erase(e, seq.cend());
|
||||||
|
|
||||||
|
//Step 4: merge both ranges
|
||||||
|
(flat_tree_container_inplace_merge)(seq, it, this->priv_value_comp(), contiguous_tag);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class InIt>
|
template <class InIt>
|
||||||
void insert_equal(InIt first, InIt last
|
void insert_equal(InIt first, InIt last)
|
||||||
#if !defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
|
|
||||||
, typename dtl::enable_if_c
|
|
||||||
< dtl::is_input_iterator<InIt>::value
|
|
||||||
>::type * = 0
|
|
||||||
#endif
|
|
||||||
)
|
|
||||||
{ this->priv_insert_equal_loop(first, last); }
|
|
||||||
|
|
||||||
template <class InIt>
|
|
||||||
void insert_equal(InIt first, InIt last
|
|
||||||
#if !defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
|
|
||||||
, typename dtl::enable_if_c
|
|
||||||
< !dtl::is_input_iterator<InIt>::value
|
|
||||||
>::type * = 0
|
|
||||||
#endif
|
|
||||||
)
|
|
||||||
{
|
{
|
||||||
const size_type len = static_cast<size_type>(boost::container::iterator_distance(first, last));
|
dtl::bool_<is_contiguous_container<container_type>::value> contiguous_tag;
|
||||||
this->reserve(this->size()+len);
|
container_type &seq = this->m_data.m_seq;
|
||||||
this->priv_insert_equal_loop(first, last);
|
typename container_type::iterator const it = seq.insert(seq.cend(), first, last);
|
||||||
|
(flat_tree_container_inplace_sort_ending)(seq, it, this->priv_value_comp(), contiguous_tag);
|
||||||
|
(flat_tree_container_inplace_merge) (seq, it, this->priv_value_comp(), contiguous_tag);
|
||||||
}
|
}
|
||||||
|
|
||||||
//Ordered
|
//Ordered
|
||||||
|
|
||||||
template <class InIt>
|
template <class InIt>
|
||||||
void insert_equal(ordered_range_t, InIt first, InIt last
|
void insert_equal(ordered_range_t, InIt first, InIt last)
|
||||||
#if !defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
|
|
||||||
, typename dtl::enable_if_c
|
|
||||||
< dtl::is_input_iterator<InIt>::value
|
|
||||||
>::type * = 0
|
|
||||||
#endif
|
|
||||||
)
|
|
||||||
{ this->priv_insert_equal_loop_ordered(first, last); }
|
|
||||||
|
|
||||||
template <class FwdIt>
|
|
||||||
void insert_equal(ordered_range_t, FwdIt first, FwdIt last
|
|
||||||
#if !defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
|
|
||||||
, typename dtl::enable_if_c
|
|
||||||
< !dtl::is_input_iterator<FwdIt>::value &&
|
|
||||||
dtl::is_forward_iterator<FwdIt>::value
|
|
||||||
>::type * = 0
|
|
||||||
#endif
|
|
||||||
)
|
|
||||||
{
|
|
||||||
const size_type len = static_cast<size_type>(boost::container::iterator_distance(first, last));
|
|
||||||
this->reserve(this->size()+len);
|
|
||||||
this->priv_insert_equal_loop_ordered(first, last);
|
|
||||||
}
|
|
||||||
|
|
||||||
template <class BidirIt>
|
|
||||||
void insert_equal(ordered_range_t, BidirIt first, BidirIt last
|
|
||||||
#if !defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
|
|
||||||
, typename dtl::disable_if_or
|
|
||||||
< void
|
|
||||||
, dtl::is_input_iterator<BidirIt>
|
|
||||||
, dtl::is_forward_iterator<BidirIt>
|
|
||||||
>::type * = 0
|
|
||||||
#endif
|
|
||||||
)
|
|
||||||
{
|
{
|
||||||
const bool value = boost::container::dtl::
|
const bool value = boost::container::dtl::
|
||||||
has_member_function_callable_with_merge_unique<container_type, iterator, iterator, value_compare>::value;
|
has_member_function_callable_with_merge_unique<container_type, InIt, InIt, value_compare>::value;
|
||||||
(flat_tree_merge_equal)(this->m_data.m_seq, first, last, this->priv_value_comp(), dtl::bool_<value>());
|
(flat_tree_merge_equal)(this->m_data.m_seq, first, last, this->priv_value_comp(), dtl::bool_<value>());
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class InIt>
|
template <class InIt>
|
||||||
void insert_unique(ordered_unique_range_t, InIt first, InIt last
|
void insert_unique(ordered_unique_range_t, InIt first, InIt last)
|
||||||
#if !defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
|
|
||||||
, typename dtl::enable_if_or
|
|
||||||
< void
|
|
||||||
, dtl::is_input_iterator<InIt>
|
|
||||||
, dtl::is_forward_iterator<InIt>
|
|
||||||
>::type * = 0
|
|
||||||
#endif
|
|
||||||
)
|
|
||||||
{
|
|
||||||
const_iterator pos(this->cend());
|
|
||||||
for ( ; first != last; ++first){
|
|
||||||
pos = this->insert_unique(pos, *first);
|
|
||||||
++pos;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
template <class BidirIt>
|
|
||||||
void insert_unique(ordered_unique_range_t, BidirIt first, BidirIt last
|
|
||||||
#if !defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
|
|
||||||
, typename dtl::enable_if_c
|
|
||||||
< !(dtl::is_input_iterator<BidirIt>::value ||
|
|
||||||
dtl::is_forward_iterator<BidirIt>::value)
|
|
||||||
>::type * = 0
|
|
||||||
#endif
|
|
||||||
)
|
|
||||||
{
|
{
|
||||||
const bool value = boost::container::dtl::
|
const bool value = boost::container::dtl::
|
||||||
has_member_function_callable_with_merge_unique<container_type, iterator, iterator, value_compare>::value;
|
has_member_function_callable_with_merge_unique<container_type, InIt, InIt, value_compare>::value;
|
||||||
(flat_tree_merge_unique)(this->m_data.m_seq, first, last, this->priv_value_comp(), dtl::bool_<value>());
|
(flat_tree_merge_unique)(this->m_data.m_seq, first, last, this->priv_value_comp(), dtl::bool_<value>());
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1287,14 +1316,10 @@ class flat_tree
|
|||||||
//for the constructor
|
//for the constructor
|
||||||
//Call end() every iteration as reallocation might have invalidated iterators
|
//Call end() every iteration as reallocation might have invalidated iterators
|
||||||
if(unique_insertion){
|
if(unique_insertion){
|
||||||
for ( ; first != last; ++first){
|
this->insert_unique(first, last);
|
||||||
this->insert_unique(this->cend(), *first);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else{
|
else{
|
||||||
for ( ; first != last; ++first){
|
this->insert_equal (first, last);
|
||||||
this->insert_equal(this->cend(), *first);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1491,27 +1516,6 @@ class flat_tree
|
|||||||
}
|
}
|
||||||
return std::pair<RanIt, RanIt>(lb, ub);
|
return std::pair<RanIt, RanIt>(lb, ub);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<class InIt>
|
|
||||||
void priv_insert_equal_loop(InIt first, InIt last)
|
|
||||||
{
|
|
||||||
for ( ; first != last; ++first){
|
|
||||||
this->insert_equal(*first);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
template<class InIt>
|
|
||||||
void priv_insert_equal_loop_ordered(InIt first, InIt last)
|
|
||||||
{
|
|
||||||
const_iterator pos(this->cend());
|
|
||||||
for ( ; first != last; ++first){
|
|
||||||
//If ordered, then try hint version
|
|
||||||
//to achieve constant-time complexity per insertion
|
|
||||||
//in some cases
|
|
||||||
pos = this->insert_equal(pos, *first);
|
|
||||||
++pos;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
} //namespace dtl {
|
} //namespace dtl {
|
||||||
|
@@ -22,6 +22,7 @@
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include <boost/intrusive/detail/iterator.hpp>
|
#include <boost/intrusive/detail/iterator.hpp>
|
||||||
|
#include <boost/move/utility_core.hpp>
|
||||||
|
|
||||||
namespace boost {
|
namespace boost {
|
||||||
namespace container {
|
namespace container {
|
||||||
@@ -34,6 +35,35 @@ using ::boost::intrusive::iterator_enable_if_tag;
|
|||||||
using ::boost::intrusive::iterator_disable_if_tag;
|
using ::boost::intrusive::iterator_disable_if_tag;
|
||||||
using ::boost::intrusive::iterator_arrow_result;
|
using ::boost::intrusive::iterator_arrow_result;
|
||||||
|
|
||||||
|
template <class Container>
|
||||||
|
class back_emplacer
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
Container& container;
|
||||||
|
|
||||||
|
public:
|
||||||
|
typedef std::output_iterator_tag iterator_category;
|
||||||
|
typedef void value_type;
|
||||||
|
typedef void difference_type;
|
||||||
|
typedef void pointer;
|
||||||
|
typedef void reference;
|
||||||
|
|
||||||
|
back_emplacer(Container& x)
|
||||||
|
: container(x)
|
||||||
|
{}
|
||||||
|
|
||||||
|
template<class U>
|
||||||
|
back_emplacer& operator=(BOOST_FWD_REF(U) value)
|
||||||
|
{
|
||||||
|
container.emplace_back(boost::forward<U>(value));
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
back_emplacer& operator*() { return *this; }
|
||||||
|
back_emplacer& operator++() { return *this; }
|
||||||
|
back_emplacer& operator++(int){ return *this; }
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
} //namespace container {
|
} //namespace container {
|
||||||
} //namespace boost {
|
} //namespace boost {
|
||||||
|
|
||||||
|
@@ -1113,8 +1113,7 @@ class flat_map
|
|||||||
//! <b>Effects</b>: inserts each element from the range [first,last) if and only
|
//! <b>Effects</b>: inserts each element from the range [first,last) if and only
|
||||||
//! if there is no element with key equivalent to the key of that element.
|
//! if there is no element with key equivalent to the key of that element.
|
||||||
//!
|
//!
|
||||||
//! <b>Complexity</b>: At most N log(size()+N) (N is the distance from first to last)
|
//! <b>Complexity</b>: N log(size()+N).
|
||||||
//! search time plus N*size() insertion time.
|
|
||||||
//!
|
//!
|
||||||
//! <b>Note</b>: If an element is inserted it might invalidate elements.
|
//! <b>Note</b>: If an element is inserted it might invalidate elements.
|
||||||
template <class InputIterator>
|
template <class InputIterator>
|
||||||
@@ -1130,8 +1129,7 @@ class flat_map
|
|||||||
//! if there is no element with key equivalent to the key of that element. This
|
//! if there is no element with key equivalent to the key of that element. This
|
||||||
//! function is more efficient than the normal range creation for ordered ranges.
|
//! function is more efficient than the normal range creation for ordered ranges.
|
||||||
//!
|
//!
|
||||||
//! <b>Complexity</b>: At most N log(size()+N) (N is the distance from first to last)
|
//! <b>Complexity</b>: Linear.
|
||||||
//! search time plus N*size() insertion time.
|
|
||||||
//!
|
//!
|
||||||
//! <b>Note</b>: If an element is inserted it might invalidate elements.
|
//! <b>Note</b>: If an element is inserted it might invalidate elements.
|
||||||
//!
|
//!
|
||||||
@@ -1144,8 +1142,7 @@ class flat_map
|
|||||||
//! <b>Effects</b>: inserts each element from the range [il.begin(), il.end()) if and only
|
//! <b>Effects</b>: inserts each element from the range [il.begin(), il.end()) if and only
|
||||||
//! if there is no element with key equivalent to the key of that element.
|
//! if there is no element with key equivalent to the key of that element.
|
||||||
//!
|
//!
|
||||||
//! <b>Complexity</b>: At most N log(size()+N) (N is the distance from il.first() to il.end())
|
//! <b>Complexity</b>: N log(N).
|
||||||
//! search time plus N*size() insertion time.
|
|
||||||
//!
|
//!
|
||||||
//! <b>Note</b>: If an element is inserted it might invalidate elements.
|
//! <b>Note</b>: If an element is inserted it might invalidate elements.
|
||||||
BOOST_CONTAINER_FORCEINLINE void insert(std::initializer_list<value_type> il)
|
BOOST_CONTAINER_FORCEINLINE void insert(std::initializer_list<value_type> il)
|
||||||
@@ -1161,8 +1158,7 @@ class flat_map
|
|||||||
//! if there is no element with key equivalent to the key of that element. This
|
//! if there is no element with key equivalent to the key of that element. This
|
||||||
//! function is more efficient than the normal range creation for ordered ranges.
|
//! function is more efficient than the normal range creation for ordered ranges.
|
||||||
//!
|
//!
|
||||||
//! <b>Complexity</b>: At most N log(size()+N) (N is the distance from first to last)
|
//! <b>Complexity</b>: Linear.
|
||||||
//! search time plus N*size() insertion time.
|
|
||||||
//!
|
//!
|
||||||
//! <b>Note</b>: If an element is inserted it might invalidate elements.
|
//! <b>Note</b>: If an element is inserted it might invalidate elements.
|
||||||
//!
|
//!
|
||||||
@@ -2262,8 +2258,7 @@ class flat_multimap
|
|||||||
//!
|
//!
|
||||||
//! <b>Effects</b>: inserts each element from the range [first,last) .
|
//! <b>Effects</b>: inserts each element from the range [first,last) .
|
||||||
//!
|
//!
|
||||||
//! <b>Complexity</b>: At most N log(size()+N) (N is the distance from first to last)
|
//! <b>Complexity</b>: N log(N).
|
||||||
//! search time plus N*size() insertion time.
|
|
||||||
//!
|
//!
|
||||||
//! <b>Note</b>: If an element is inserted it might invalidate elements.
|
//! <b>Note</b>: If an element is inserted it might invalidate elements.
|
||||||
template <class InputIterator>
|
template <class InputIterator>
|
||||||
@@ -2278,8 +2273,7 @@ class flat_multimap
|
|||||||
//! if there is no element with key equivalent to the key of that element. This
|
//! if there is no element with key equivalent to the key of that element. This
|
||||||
//! function is more efficient than the normal range creation for ordered ranges.
|
//! function is more efficient than the normal range creation for ordered ranges.
|
||||||
//!
|
//!
|
||||||
//! <b>Complexity</b>: At most N log(size()+N) (N is the distance from first to last)
|
//! <b>Complexity</b>: Linear.
|
||||||
//! search time plus N*size() insertion time.
|
|
||||||
//!
|
//!
|
||||||
//! <b>Note</b>: If an element is inserted it might invalidate elements.
|
//! <b>Note</b>: If an element is inserted it might invalidate elements.
|
||||||
//!
|
//!
|
||||||
@@ -2291,8 +2285,7 @@ class flat_multimap
|
|||||||
#if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
|
#if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
|
||||||
//! <b>Effects</b>: inserts each element from the range [il.begin(), il.end()) .
|
//! <b>Effects</b>: inserts each element from the range [il.begin(), il.end()) .
|
||||||
//!
|
//!
|
||||||
//! <b>Complexity</b>: At most N log(size()+N) (N is the distance from first to last)
|
//! <b>Complexity</b>: N log(N).
|
||||||
//! search time plus N*size() insertion time.
|
|
||||||
//!
|
//!
|
||||||
//! <b>Note</b>: If an element is inserted it might invalidate elements.
|
//! <b>Note</b>: If an element is inserted it might invalidate elements.
|
||||||
BOOST_CONTAINER_FORCEINLINE void insert(std::initializer_list<value_type> il)
|
BOOST_CONTAINER_FORCEINLINE void insert(std::initializer_list<value_type> il)
|
||||||
@@ -2307,8 +2300,7 @@ class flat_multimap
|
|||||||
//! if there is no element with key equivalent to the key of that element. This
|
//! if there is no element with key equivalent to the key of that element. This
|
||||||
//! function is more efficient than the normal range creation for ordered ranges.
|
//! function is more efficient than the normal range creation for ordered ranges.
|
||||||
//!
|
//!
|
||||||
//! <b>Complexity</b>: At most N log(size()+N) (N is the distance from first to last)
|
//! <b>Complexity</b>: Linear.
|
||||||
//! search time plus N*size() insertion time.
|
|
||||||
//!
|
//!
|
||||||
//! <b>Note</b>: If an element is inserted it might invalidate elements.
|
//! <b>Note</b>: If an element is inserted it might invalidate elements.
|
||||||
//!
|
//!
|
||||||
|
@@ -687,8 +687,7 @@ class flat_set
|
|||||||
//! <b>Effects</b>: inserts each element from the range [first,last) if and only
|
//! <b>Effects</b>: inserts each element from the range [first,last) if and only
|
||||||
//! if there is no element with key equivalent to the key of that element.
|
//! if there is no element with key equivalent to the key of that element.
|
||||||
//!
|
//!
|
||||||
//! <b>Complexity</b>: At most N log(size()+N) (N is the distance from first to last)
|
//! <b>Complexity</b>: N log(N).
|
||||||
//! search time plus N*size() insertion time.
|
|
||||||
//!
|
//!
|
||||||
//! <b>Note</b>: If an element is inserted it might invalidate elements.
|
//! <b>Note</b>: If an element is inserted it might invalidate elements.
|
||||||
template <class InputIterator>
|
template <class InputIterator>
|
||||||
@@ -702,8 +701,7 @@ class flat_set
|
|||||||
//! <b>Effects</b>: inserts each element from the range [first,last) .This function
|
//! <b>Effects</b>: inserts each element from the range [first,last) .This function
|
||||||
//! is more efficient than the normal range creation for ordered ranges.
|
//! is more efficient than the normal range creation for ordered ranges.
|
||||||
//!
|
//!
|
||||||
//! <b>Complexity</b>: At most N log(size()+N) (N is the distance from first to last)
|
//! <b>Complexity</b>: Linear.
|
||||||
//! search time plus N*size() insertion time.
|
|
||||||
//!
|
//!
|
||||||
//! <b>Note</b>: Non-standard extension. If an element is inserted it might invalidate elements.
|
//! <b>Note</b>: Non-standard extension. If an element is inserted it might invalidate elements.
|
||||||
template <class InputIterator>
|
template <class InputIterator>
|
||||||
@@ -714,8 +712,7 @@ class flat_set
|
|||||||
//! <b>Effects</b>: inserts each element from the range [il.begin(), il.end()) if and only
|
//! <b>Effects</b>: inserts each element from the range [il.begin(), il.end()) if and only
|
||||||
//! if there is no element with key equivalent to the key of that element.
|
//! if there is no element with key equivalent to the key of that element.
|
||||||
//!
|
//!
|
||||||
//! <b>Complexity</b>: At most N log(size()+N) (N is the distance from il.begin() to il.end())
|
//! <b>Complexity</b>: N log(N).
|
||||||
//! search time plus N*size() insertion time.
|
|
||||||
//!
|
//!
|
||||||
//! <b>Note</b>: If an element is inserted it might invalidate elements.
|
//! <b>Note</b>: If an element is inserted it might invalidate elements.
|
||||||
BOOST_CONTAINER_FORCEINLINE void insert(std::initializer_list<value_type> il)
|
BOOST_CONTAINER_FORCEINLINE void insert(std::initializer_list<value_type> il)
|
||||||
@@ -727,8 +724,7 @@ class flat_set
|
|||||||
//! <b>Effects</b>: inserts each element from the range [il.begin(), il.end()) .This function
|
//! <b>Effects</b>: inserts each element from the range [il.begin(), il.end()) .This function
|
||||||
//! is more efficient than the normal range creation for ordered ranges.
|
//! is more efficient than the normal range creation for ordered ranges.
|
||||||
//!
|
//!
|
||||||
//! <b>Complexity</b>: At most N log(size()+N) (N is the distance from il.begin() to il.end())
|
//! <b>Complexity</b>: Linear.
|
||||||
//! search time plus N*size() insertion time.
|
|
||||||
//!
|
//!
|
||||||
//! <b>Note</b>: Non-standard extension. If an element is inserted it might invalidate elements.
|
//! <b>Note</b>: Non-standard extension. If an element is inserted it might invalidate elements.
|
||||||
BOOST_CONTAINER_FORCEINLINE void insert(ordered_unique_range_t, std::initializer_list<value_type> il)
|
BOOST_CONTAINER_FORCEINLINE void insert(ordered_unique_range_t, std::initializer_list<value_type> il)
|
||||||
@@ -1456,8 +1452,7 @@ class flat_multiset
|
|||||||
//!
|
//!
|
||||||
//! <b>Effects</b>: inserts each element from the range [first,last) .
|
//! <b>Effects</b>: inserts each element from the range [first,last) .
|
||||||
//!
|
//!
|
||||||
//! <b>Complexity</b>: At most N log(size()+N) (N is the distance from first to last)
|
//! <b>Complexity</b>: N log(N).
|
||||||
//! search time plus N*size() insertion time.
|
|
||||||
//!
|
//!
|
||||||
//! <b>Note</b>: If an element is inserted it might invalidate elements.
|
//! <b>Note</b>: If an element is inserted it might invalidate elements.
|
||||||
template <class InputIterator>
|
template <class InputIterator>
|
||||||
@@ -1470,8 +1465,7 @@ class flat_multiset
|
|||||||
//! <b>Effects</b>: inserts each element from the range [first,last) .This function
|
//! <b>Effects</b>: inserts each element from the range [first,last) .This function
|
||||||
//! is more efficient than the normal range creation for ordered ranges.
|
//! is more efficient than the normal range creation for ordered ranges.
|
||||||
//!
|
//!
|
||||||
//! <b>Complexity</b>: At most N log(size()+N) (N is the distance from first to last)
|
//! <b>Complexity</b>: Linear.
|
||||||
//! search time plus N*size() insertion time.
|
|
||||||
//!
|
//!
|
||||||
//! <b>Note</b>: Non-standard extension. If an element is inserted it might invalidate elements.
|
//! <b>Note</b>: Non-standard extension. If an element is inserted it might invalidate elements.
|
||||||
template <class InputIterator>
|
template <class InputIterator>
|
||||||
@@ -1481,8 +1475,7 @@ class flat_multiset
|
|||||||
#if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
|
#if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
|
||||||
//! <b>Effects</b>: inserts each element from the range [il.begin(), il.end()).
|
//! <b>Effects</b>: inserts each element from the range [il.begin(), il.end()).
|
||||||
//!
|
//!
|
||||||
//! <b>Complexity</b>: At most N log(size()+N) (N is the distance from first to last)
|
//! <b>Complexity</b>: N log(N).
|
||||||
//! search time plus N*size() insertion time.
|
|
||||||
//!
|
//!
|
||||||
//! <b>Note</b>: If an element is inserted it might invalidate elements.
|
//! <b>Note</b>: If an element is inserted it might invalidate elements.
|
||||||
BOOST_CONTAINER_FORCEINLINE void insert(std::initializer_list<value_type> il)
|
BOOST_CONTAINER_FORCEINLINE void insert(std::initializer_list<value_type> il)
|
||||||
@@ -1493,8 +1486,7 @@ class flat_multiset
|
|||||||
//! <b>Effects</b>: inserts each element from the range [il.begin(), il.end()). This function
|
//! <b>Effects</b>: inserts each element from the range [il.begin(), il.end()). This function
|
||||||
//! is more efficient than the normal range creation for ordered ranges.
|
//! is more efficient than the normal range creation for ordered ranges.
|
||||||
//!
|
//!
|
||||||
//! <b>Complexity</b>: At most N log(size()+N) (N is the distance from il.begin() to il.end())
|
//! <b>Complexity</b>: Linear.
|
||||||
//! search time plus N*size() insertion time.
|
|
||||||
//!
|
//!
|
||||||
//! <b>Note</b>: Non-standard extension. If an element is inserted it might invalidate elements.
|
//! <b>Note</b>: Non-standard extension. If an element is inserted it might invalidate elements.
|
||||||
BOOST_CONTAINER_FORCEINLINE void insert(ordered_range_t, std::initializer_list<value_type> il)
|
BOOST_CONTAINER_FORCEINLINE void insert(ordered_range_t, std::initializer_list<value_type> il)
|
||||||
|
@@ -60,6 +60,7 @@
|
|||||||
#include <boost/move/algo/adaptive_merge.hpp>
|
#include <boost/move/algo/adaptive_merge.hpp>
|
||||||
#include <boost/move/algo/unique.hpp>
|
#include <boost/move/algo/unique.hpp>
|
||||||
#include <boost/move/algo/predicate.hpp>
|
#include <boost/move/algo/predicate.hpp>
|
||||||
|
#include <boost/move/algo/detail/set_difference.hpp>
|
||||||
// other
|
// other
|
||||||
#include <boost/core/no_exceptions_support.hpp>
|
#include <boost/core/no_exceptions_support.hpp>
|
||||||
#include <boost/assert.hpp>
|
#include <boost/assert.hpp>
|
||||||
@@ -75,6 +76,7 @@ namespace container {
|
|||||||
|
|
||||||
#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
|
#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
|
||||||
|
|
||||||
|
|
||||||
template <class Pointer, bool IsConst>
|
template <class Pointer, bool IsConst>
|
||||||
class vec_iterator
|
class vec_iterator
|
||||||
{
|
{
|
||||||
@@ -210,40 +212,6 @@ struct vector_insert_ordered_cursor
|
|||||||
BiDirValueIt last_value_it;
|
BiDirValueIt last_value_it;
|
||||||
};
|
};
|
||||||
|
|
||||||
template<class T, class SizeType, class BiDirValueIt, class Comp>
|
|
||||||
struct vector_merge_cursor
|
|
||||||
{
|
|
||||||
typedef SizeType size_type;
|
|
||||||
typedef typename iterator_traits<BiDirValueIt>::reference reference;
|
|
||||||
|
|
||||||
BOOST_CONTAINER_FORCEINLINE vector_merge_cursor(T *pbeg, T *plast, BiDirValueIt valueit, Comp &cmp)
|
|
||||||
: m_pbeg(pbeg), m_pcur(--plast), m_valueit(valueit), m_cmp(cmp)
|
|
||||||
{}
|
|
||||||
|
|
||||||
void operator --()
|
|
||||||
{
|
|
||||||
--m_valueit;
|
|
||||||
const T &t = *m_valueit;
|
|
||||||
while((m_pcur + 1) != m_pbeg){
|
|
||||||
if(!m_cmp(t, *m_pcur)){
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
--m_pcur;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
BOOST_CONTAINER_FORCEINLINE size_type get_pos() const
|
|
||||||
{ return static_cast<size_type>((m_pcur + 1) - m_pbeg); }
|
|
||||||
|
|
||||||
BOOST_CONTAINER_FORCEINLINE reference get_val()
|
|
||||||
{ return *m_valueit; }
|
|
||||||
|
|
||||||
T *const m_pbeg;
|
|
||||||
T *m_pcur;
|
|
||||||
BiDirValueIt m_valueit;
|
|
||||||
Comp &m_cmp;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct initial_capacity_t{};
|
struct initial_capacity_t{};
|
||||||
|
|
||||||
template<class Pointer, bool IsConst>
|
template<class Pointer, bool IsConst>
|
||||||
@@ -508,10 +476,14 @@ struct vector_alloc_holder
|
|||||||
BOOST_CONTAINER_FORCEINLINE const Allocator &alloc() const BOOST_NOEXCEPT_OR_NOTHROW
|
BOOST_CONTAINER_FORCEINLINE const Allocator &alloc() const BOOST_NOEXCEPT_OR_NOTHROW
|
||||||
{ return *this; }
|
{ return *this; }
|
||||||
|
|
||||||
const pointer &start() const BOOST_NOEXCEPT_OR_NOTHROW { return m_start; }
|
BOOST_CONTAINER_FORCEINLINE const pointer &start() const BOOST_NOEXCEPT_OR_NOTHROW
|
||||||
size_type capacity() const BOOST_NOEXCEPT_OR_NOTHROW { return m_capacity; }
|
{ return m_start; }
|
||||||
void start(const pointer &p) BOOST_NOEXCEPT_OR_NOTHROW { m_start = p; }
|
BOOST_CONTAINER_FORCEINLINE size_type capacity() const BOOST_NOEXCEPT_OR_NOTHROW
|
||||||
void capacity(const size_type &c) BOOST_NOEXCEPT_OR_NOTHROW { BOOST_ASSERT( c <= stored_size_type(-1)); m_capacity = c; }
|
{ return m_capacity; }
|
||||||
|
BOOST_CONTAINER_FORCEINLINE void start(const pointer &p) BOOST_NOEXCEPT_OR_NOTHROW
|
||||||
|
{ m_start = p; }
|
||||||
|
BOOST_CONTAINER_FORCEINLINE void capacity(const size_type &c) BOOST_NOEXCEPT_OR_NOTHROW
|
||||||
|
{ BOOST_ASSERT( c <= stored_size_type(-1)); m_capacity = c; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void priv_first_allocation(size_type cap)
|
void priv_first_allocation(size_type cap)
|
||||||
@@ -2191,21 +2163,45 @@ class vector
|
|||||||
return this->priv_insert_ordered_at(element_count, inserter_t(last_position_it, last_value_it));
|
return this->priv_insert_ordered_at(element_count, inserter_t(last_position_it, last_value_it));
|
||||||
}
|
}
|
||||||
|
|
||||||
template<class BidirIt>
|
template<class InputIt>
|
||||||
BOOST_CONTAINER_FORCEINLINE void merge(BidirIt first, BidirIt last)
|
BOOST_CONTAINER_FORCEINLINE void merge(InputIt first, InputIt last)
|
||||||
{ this->merge(first, last, value_less_t()); }
|
{ this->merge(first, last, value_less_t()); }
|
||||||
|
|
||||||
template<class BidirIt, class Compare>
|
template<class InputIt, class Compare>
|
||||||
BOOST_CONTAINER_FORCEINLINE void merge(BidirIt first, BidirIt last, Compare comp)
|
BOOST_CONTAINER_FORCEINLINE void merge(InputIt first, InputIt last, Compare comp)
|
||||||
{ this->priv_merge(dtl::false_type(), first, last, comp); }
|
{
|
||||||
|
size_type const s = this->size();
|
||||||
|
size_type const c = this->capacity();
|
||||||
|
size_type n = 0;
|
||||||
|
size_type const free_cap = c - s;
|
||||||
|
//If not input iterator and new elements don't fit in the remaining capacity, merge in new buffer
|
||||||
|
if(!dtl::is_input_iterator<InputIt>::value &&
|
||||||
|
free_cap < (n = static_cast<size_type>(boost::container::iterator_distance(first, last)))){
|
||||||
|
this->priv_merge_in_new_buffer(first, n, comp, alloc_version());
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
iterator pos(this->insert(this->cend(), first, last));
|
||||||
|
T *const raw_beg = this->priv_raw_begin();
|
||||||
|
T *const raw_end = this->priv_raw_end();
|
||||||
|
T *const raw_pos = raw_beg + s;
|
||||||
|
boost::movelib::adaptive_merge(raw_beg, raw_pos, raw_end, comp, raw_end, free_cap - n);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
template<class BidirIt>
|
template<class InputIt>
|
||||||
BOOST_CONTAINER_FORCEINLINE void merge_unique(BidirIt first, BidirIt last)
|
BOOST_CONTAINER_FORCEINLINE void merge_unique(InputIt first, InputIt last)
|
||||||
{ this->priv_merge(dtl::true_type(), first, last, value_less_t()); }
|
{ this->merge_unique(first, last, value_less_t()); }
|
||||||
|
|
||||||
template<class BidirIt, class Compare>
|
template<class InputIt, class Compare>
|
||||||
BOOST_CONTAINER_FORCEINLINE void merge_unique(BidirIt first, BidirIt last, Compare comp)
|
BOOST_CONTAINER_FORCEINLINE void merge_unique(InputIt first, InputIt last, Compare comp)
|
||||||
{ this->priv_merge(dtl::true_type(), first, last, comp); }
|
{
|
||||||
|
size_type const s = this->size();
|
||||||
|
this->priv_set_difference_back(first, last, comp);
|
||||||
|
T *const raw_beg = this->priv_raw_begin();
|
||||||
|
T *const raw_end = this->priv_raw_end();
|
||||||
|
T *raw_pos = raw_beg + s;
|
||||||
|
boost::movelib::adaptive_merge(raw_beg, raw_pos, raw_end, comp, raw_end, this->capacity() - this->size());
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
template<class PositionValue>
|
template<class PositionValue>
|
||||||
@@ -2265,43 +2261,48 @@ class vector
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
template<class UniqueBool, class BidirIt, class Compare>
|
template<class InputIt, class Compare>
|
||||||
void priv_merge(UniqueBool, BidirIt first, BidirIt last, Compare comp)
|
void priv_set_difference_back(InputIt first1, InputIt last1, Compare comp)
|
||||||
{
|
{
|
||||||
size_type const n = static_cast<size_type>(boost::container::iterator_distance(first, last));
|
T * old_first2 = this->priv_raw_begin();
|
||||||
size_type const s = this->size();
|
T * first2 = old_first2;
|
||||||
if(BOOST_LIKELY(s)){
|
T * last2 = this->priv_raw_end();
|
||||||
size_type const c = this->capacity();
|
|
||||||
size_type const free_c = (c - s);
|
while (first1 != last1) {
|
||||||
//Use a new buffer if current one is too small for new elements
|
if (first2 == last2){
|
||||||
if(free_c < n){
|
this->insert(this->cend(), first1, last1);
|
||||||
this->priv_merge_in_new_buffer(UniqueBool(), first, n, comp, alloc_version());
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (comp(*first1, *first2)) {
|
||||||
|
this->emplace_back(*first1);
|
||||||
|
//Reallocation happened, update range
|
||||||
|
T * const raw_begin = this->priv_raw_begin();
|
||||||
|
if(old_first2 != raw_begin){
|
||||||
|
first2 = raw_begin + (first2 - old_first2);
|
||||||
|
last2 = first2 + (last2 - old_first2);
|
||||||
|
old_first2 = raw_begin;
|
||||||
|
}
|
||||||
|
|
||||||
|
++first1;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
T *raw_pos = boost::movelib::iterator_to_raw_pointer(this->insert(this->cend(), first, last));
|
if (!comp(*first2, *first1)) {
|
||||||
T *raw_beg = this->priv_raw_begin();
|
++first1;
|
||||||
T *raw_end = this->priv_raw_end();
|
|
||||||
boost::movelib::adaptive_merge(raw_beg, raw_pos, raw_end, comp, raw_end, free_c - n);
|
|
||||||
if(UniqueBool::value){
|
|
||||||
size_type const count =
|
|
||||||
static_cast<size_type>(raw_end - boost::movelib::unique(raw_beg, raw_end, boost::movelib::negate<Compare>(comp)));
|
|
||||||
this->priv_destroy_last_n(count);
|
|
||||||
}
|
}
|
||||||
|
++first2;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else{
|
|
||||||
this->insert(this->cend(), n, first, last);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
template<class UniqueBool, class FwdIt, class Compare>
|
template<class FwdIt, class Compare>
|
||||||
BOOST_CONTAINER_FORCEINLINE void priv_merge_in_new_buffer(UniqueBool, FwdIt, size_type, Compare, version_0)
|
BOOST_CONTAINER_FORCEINLINE void priv_merge_in_new_buffer(FwdIt, size_type, Compare, version_0)
|
||||||
{
|
{
|
||||||
throw_bad_alloc();
|
throw_bad_alloc();
|
||||||
}
|
}
|
||||||
|
|
||||||
template<class UniqueBool, class FwdIt, class Compare, class Version>
|
template<class FwdIt, class Compare, class Version>
|
||||||
void priv_merge_in_new_buffer(UniqueBool, FwdIt first, size_type n, Compare comp, Version)
|
void priv_merge_in_new_buffer(FwdIt first, size_type n, Compare comp, Version)
|
||||||
{
|
{
|
||||||
size_type const new_size = this->size() + n;
|
size_type const new_size = this->size() + n;
|
||||||
size_type new_cap = new_size;
|
size_type new_cap = new_size;
|
||||||
@@ -2335,11 +2336,6 @@ class vector
|
|||||||
--n;
|
--n;
|
||||||
++d_first;
|
++d_first;
|
||||||
}
|
}
|
||||||
else if(UniqueBool::value && !comp(*pbeg, *first)){
|
|
||||||
++first;
|
|
||||||
--n;
|
|
||||||
--added;
|
|
||||||
}
|
|
||||||
else{
|
else{
|
||||||
allocator_traits_type::construct( this->m_holder.alloc(), d_first, boost::move(*pbeg) );
|
allocator_traits_type::construct( this->m_holder.alloc(), d_first, boost::move(*pbeg) );
|
||||||
new_values_destroyer.increment_size(1u);
|
new_values_destroyer.increment_size(1u);
|
||||||
|
@@ -316,6 +316,25 @@ bool flat_tree_ordered_insertion_test()
|
|||||||
int_set4.insert(int_even_set.begin(), int_even_set.end());
|
int_set4.insert(int_even_set.begin(), int_even_set.end());
|
||||||
if(!CheckEqualContainers(int_set4, fset))
|
if(!CheckEqualContainers(int_set4, fset))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
//add even/odd values with not enough capacity
|
||||||
|
flat_set<int>().swap(fset);
|
||||||
|
int_set4.clear();
|
||||||
|
int_set.clear();
|
||||||
|
|
||||||
|
fset.reserve(int_even_set.size());
|
||||||
|
fset.insert(ordered_unique_range, int_even_set.begin(), int_even_set.end());
|
||||||
|
int_set4.insert(int_even_set.begin(), int_even_set.end());
|
||||||
|
|
||||||
|
for(std::size_t i = 0; i < NumElements*2; i+=2){
|
||||||
|
int_set.insert(static_cast<int>(i));
|
||||||
|
int_set.insert(static_cast<int>(i+1));
|
||||||
|
}
|
||||||
|
|
||||||
|
fset.insert(ordered_unique_range, int_set.begin(), int_set.end());
|
||||||
|
int_set4.insert(int_set.begin(), int_set.end());
|
||||||
|
if(!CheckEqualContainers(int_set4, fset))
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
@@ -388,12 +388,12 @@ int set_test ()
|
|||||||
|
|
||||||
boostset.insert(boost::make_move_iterator(&aux_vect[0]), boost::make_move_iterator(&aux_vect[0] + 50));
|
boostset.insert(boost::make_move_iterator(&aux_vect[0]), boost::make_move_iterator(&aux_vect[0] + 50));
|
||||||
stdset.insert(&aux_vect2[0], &aux_vect2[0] + 50);
|
stdset.insert(&aux_vect2[0], &aux_vect2[0] + 50);
|
||||||
boostmultiset.insert(boost::make_move_iterator(&aux_vect3[0]), boost::make_move_iterator(aux_vect3 + 50));
|
|
||||||
stdmultiset.insert(&aux_vect2[0], &aux_vect2[0] + 50);
|
|
||||||
if(!CheckEqualContainers(boostset, stdset)){
|
if(!CheckEqualContainers(boostset, stdset)){
|
||||||
std::cout << "Error in boostset.insert(boost::make_move_iterator(&aux_vect[0])..." << std::endl;
|
std::cout << "Error in boostset.insert(boost::make_move_iterator(&aux_vect3[0])..." << std::endl;
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
boostmultiset.insert(boost::make_move_iterator(&aux_vect3[0]), boost::make_move_iterator(aux_vect3 + 50));
|
||||||
|
stdmultiset.insert(&aux_vect2[0], &aux_vect2[0] + 50);
|
||||||
if(!CheckEqualContainers(boostmultiset, stdmultiset)){
|
if(!CheckEqualContainers(boostmultiset, stdmultiset)){
|
||||||
std::cout << "Error in boostmultiset.insert(boost::make_move_iterator(&aux_vect3[0]), ..." << std::endl;
|
std::cout << "Error in boostmultiset.insert(boost::make_move_iterator(&aux_vect3[0]), ..." << std::endl;
|
||||||
return 1;
|
return 1;
|
||||||
@@ -447,14 +447,14 @@ int set_test ()
|
|||||||
boostset.insert(boost::make_move_iterator(&aux_vect3[0]), boost::make_move_iterator(&aux_vect3[0] + 50));
|
boostset.insert(boost::make_move_iterator(&aux_vect3[0]), boost::make_move_iterator(&aux_vect3[0] + 50));
|
||||||
stdset.insert(&aux_vect2[0], &aux_vect2[0] + 50);
|
stdset.insert(&aux_vect2[0], &aux_vect2[0] + 50);
|
||||||
stdset.insert(&aux_vect2[0], &aux_vect2[0] + 50);
|
stdset.insert(&aux_vect2[0], &aux_vect2[0] + 50);
|
||||||
boostmultiset.insert(boost::make_move_iterator(&aux_vect4[0]), boost::make_move_iterator(&aux_vect4[0] + 50));
|
|
||||||
boostmultiset.insert(boost::make_move_iterator(&aux_vect5[0]), boost::make_move_iterator(&aux_vect5[0] + 50));
|
|
||||||
stdmultiset.insert(&aux_vect2[0], &aux_vect2[0] + 50);
|
|
||||||
stdmultiset.insert(&aux_vect2[0], &aux_vect2[0] + 50);
|
|
||||||
if(!CheckEqualContainers(boostset, stdset)){
|
if(!CheckEqualContainers(boostset, stdset)){
|
||||||
std::cout << "Error in boostset.insert(boost::make_move_iterator(&aux_vect3[0])..." << std::endl;
|
std::cout << "Error in boostset.insert(boost::make_move_iterator(&aux_vect3[0])..." << std::endl;
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
boostmultiset.insert(boost::make_move_iterator(&aux_vect4[0]), boost::make_move_iterator(&aux_vect4[0] + 50));
|
||||||
|
boostmultiset.insert(boost::make_move_iterator(&aux_vect5[0]), boost::make_move_iterator(&aux_vect5[0] + 50));
|
||||||
|
stdmultiset.insert(&aux_vect2[0], &aux_vect2[0] + 50);
|
||||||
|
stdmultiset.insert(&aux_vect2[0], &aux_vect2[0] + 50);
|
||||||
if(!CheckEqualContainers(boostmultiset, stdmultiset)){
|
if(!CheckEqualContainers(boostmultiset, stdmultiset)){
|
||||||
std::cout << "Error in boostmultiset.insert(boost::make_move_iterator(&aux_vect5[0])..." << std::endl;
|
std::cout << "Error in boostmultiset.insert(boost::make_move_iterator(&aux_vect5[0])..." << std::endl;
|
||||||
return 1;
|
return 1;
|
||||||
@@ -462,12 +462,12 @@ int set_test ()
|
|||||||
|
|
||||||
boostset.erase(*boostset.begin());
|
boostset.erase(*boostset.begin());
|
||||||
stdset.erase(*stdset.begin());
|
stdset.erase(*stdset.begin());
|
||||||
boostmultiset.erase(*boostmultiset.begin());
|
|
||||||
stdmultiset.erase(*stdmultiset.begin());
|
|
||||||
if(!CheckEqualContainers(boostset, stdset)){
|
if(!CheckEqualContainers(boostset, stdset)){
|
||||||
std::cout << "Error in boostset.erase(*boostset.begin())" << std::endl;
|
std::cout << "Error in boostset.erase(*boostset.begin())" << std::endl;
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
boostmultiset.erase(*boostmultiset.begin());
|
||||||
|
stdmultiset.erase(*stdmultiset.begin());
|
||||||
if(!CheckEqualContainers(boostmultiset, stdmultiset)){
|
if(!CheckEqualContainers(boostmultiset, stdmultiset)){
|
||||||
std::cout << "Error in boostmultiset.erase(*boostmultiset.begin())" << std::endl;
|
std::cout << "Error in boostmultiset.erase(*boostmultiset.begin())" << std::endl;
|
||||||
return 1;
|
return 1;
|
||||||
|
Reference in New Issue
Block a user