mirror of
https://github.com/boostorg/container.git
synced 2025-08-03 22:44:26 +02:00
Implement extract_sequence
and adopt_sequence
for flat ordered associative containers
This commit is contained in:
@@ -1213,6 +1213,11 @@ use [*Boost.Container]? There are several reasons for that:
|
||||
|
||||
[section:release_notes Release Notes]
|
||||
|
||||
[section:release_notes_boost_1_65_00 Boost 1.65 Release]
|
||||
|
||||
* Implemented `extract_sequence`, `adopt_sequence` functions for flat_[multi]map/set associative containers.
|
||||
|
||||
[endsect]
|
||||
|
||||
[section:release_notes_boost_1_64_00 Boost 1.64 Release]
|
||||
|
||||
|
@@ -28,25 +28,30 @@
|
||||
|
||||
#include <boost/container/detail/pair.hpp>
|
||||
#include <boost/container/vector.hpp>
|
||||
#include <boost/container/allocator_traits.hpp>
|
||||
|
||||
#include <boost/container/detail/value_init.hpp>
|
||||
#include <boost/container/detail/destroyers.hpp>
|
||||
#include <boost/container/detail/algorithm.hpp> //algo_equal(), algo_lexicographical_compare
|
||||
#include <boost/container/detail/iterator.hpp>
|
||||
#include <boost/container/detail/is_sorted.hpp>
|
||||
#include <boost/container/allocator_traits.hpp>
|
||||
#include <boost/container/detail/type_traits.hpp>
|
||||
#include <boost/container/detail/iterators.hpp>
|
||||
|
||||
#ifdef BOOST_CONTAINER_VECTOR_ITERATOR_IS_POINTER
|
||||
#include <boost/intrusive/pointer_traits.hpp>
|
||||
#endif
|
||||
#include <boost/container/detail/type_traits.hpp>
|
||||
#include <boost/container/detail/iterators.hpp>
|
||||
#include <boost/intrusive/detail/minimal_pair_header.hpp> //pair
|
||||
|
||||
#include <boost/move/make_unique.hpp>
|
||||
#include <boost/move/iterator.hpp>
|
||||
#include <boost/move/adl_move_swap.hpp>
|
||||
#include <boost/move/algo/adaptive_sort.hpp>
|
||||
|
||||
#if defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
|
||||
#include <boost/move/detail/fwd_macros.hpp>
|
||||
#endif
|
||||
|
||||
#include <boost/intrusive/detail/minimal_pair_header.hpp> //pair
|
||||
#include <boost/move/iterator.hpp>
|
||||
|
||||
namespace boost {
|
||||
namespace container {
|
||||
@@ -105,14 +110,17 @@ template <class Value, class KeyOfValue,
|
||||
class Compare, class Allocator>
|
||||
class flat_tree
|
||||
{
|
||||
typedef boost::container::vector<Value, Allocator> vector_t;
|
||||
public:
|
||||
typedef boost::container::vector<Value, Allocator> sequence_type;
|
||||
|
||||
private:
|
||||
typedef Allocator allocator_t;
|
||||
typedef allocator_traits<Allocator> allocator_traits_type;
|
||||
|
||||
public:
|
||||
typedef flat_tree_value_compare<Compare, Value, KeyOfValue> value_compare;
|
||||
|
||||
private:
|
||||
private:
|
||||
struct Data
|
||||
//Inherit from value_compare to do EBO
|
||||
: public value_compare
|
||||
@@ -121,48 +129,48 @@ class flat_tree
|
||||
|
||||
public:
|
||||
Data()
|
||||
: value_compare(), m_vect()
|
||||
: value_compare(), m_seq()
|
||||
{}
|
||||
|
||||
explicit Data(const Data &d)
|
||||
: value_compare(static_cast<const value_compare&>(d)), m_vect(d.m_vect)
|
||||
: value_compare(static_cast<const value_compare&>(d)), m_seq(d.m_seq)
|
||||
{}
|
||||
|
||||
Data(BOOST_RV_REF(Data) d)
|
||||
: value_compare(boost::move(static_cast<value_compare&>(d))), m_vect(boost::move(d.m_vect))
|
||||
: value_compare(boost::move(static_cast<value_compare&>(d))), m_seq(boost::move(d.m_seq))
|
||||
{}
|
||||
|
||||
Data(const Data &d, const Allocator &a)
|
||||
: value_compare(static_cast<const value_compare&>(d)), m_vect(d.m_vect, a)
|
||||
: value_compare(static_cast<const value_compare&>(d)), m_seq(d.m_seq, a)
|
||||
{}
|
||||
|
||||
Data(BOOST_RV_REF(Data) d, const Allocator &a)
|
||||
: value_compare(boost::move(static_cast<value_compare&>(d))), m_vect(boost::move(d.m_vect), a)
|
||||
: value_compare(boost::move(static_cast<value_compare&>(d))), m_seq(boost::move(d.m_seq), a)
|
||||
{}
|
||||
|
||||
explicit Data(const Compare &comp)
|
||||
: value_compare(comp), m_vect()
|
||||
: value_compare(comp), m_seq()
|
||||
{}
|
||||
|
||||
Data(const Compare &comp, const allocator_t &alloc)
|
||||
: value_compare(comp), m_vect(alloc)
|
||||
: value_compare(comp), m_seq(alloc)
|
||||
{}
|
||||
|
||||
explicit Data(const allocator_t &alloc)
|
||||
: value_compare(), m_vect(alloc)
|
||||
: value_compare(), m_seq(alloc)
|
||||
{}
|
||||
|
||||
Data& operator=(BOOST_COPY_ASSIGN_REF(Data) d)
|
||||
{
|
||||
this->value_compare::operator=(d);
|
||||
m_vect = d.m_vect;
|
||||
m_seq = d.m_seq;
|
||||
return *this;
|
||||
}
|
||||
|
||||
Data& operator=(BOOST_RV_REF(Data) d)
|
||||
{
|
||||
this->value_compare::operator=(boost::move(static_cast<value_compare &>(d)));
|
||||
m_vect = boost::move(d.m_vect);
|
||||
m_seq = boost::move(d.m_seq);
|
||||
return *this;
|
||||
}
|
||||
|
||||
@@ -170,10 +178,10 @@ class flat_tree
|
||||
{
|
||||
value_compare& mycomp = *this, & othercomp = d;
|
||||
boost::adl_move_swap(mycomp, othercomp);
|
||||
this->m_vect.swap(d.m_vect);
|
||||
this->m_seq.swap(d.m_seq);
|
||||
}
|
||||
|
||||
vector_t m_vect;
|
||||
sequence_type m_seq;
|
||||
};
|
||||
|
||||
Data m_data;
|
||||
@@ -181,23 +189,23 @@ class flat_tree
|
||||
|
||||
public:
|
||||
|
||||
typedef typename vector_t::value_type value_type;
|
||||
typedef typename vector_t::pointer pointer;
|
||||
typedef typename vector_t::const_pointer const_pointer;
|
||||
typedef typename vector_t::reference reference;
|
||||
typedef typename vector_t::const_reference const_reference;
|
||||
typedef typename KeyOfValue::type key_type;
|
||||
typedef Compare key_compare;
|
||||
typedef typename vector_t::allocator_type allocator_type;
|
||||
typedef typename vector_t::size_type size_type;
|
||||
typedef typename vector_t::difference_type difference_type;
|
||||
typedef typename vector_t::iterator iterator;
|
||||
typedef typename vector_t::const_iterator const_iterator;
|
||||
typedef typename vector_t::reverse_iterator reverse_iterator;
|
||||
typedef typename vector_t::const_reverse_iterator const_reverse_iterator;
|
||||
typedef typename sequence_type::value_type value_type;
|
||||
typedef typename sequence_type::pointer pointer;
|
||||
typedef typename sequence_type::const_pointer const_pointer;
|
||||
typedef typename sequence_type::reference reference;
|
||||
typedef typename sequence_type::const_reference const_reference;
|
||||
typedef typename KeyOfValue::type key_type;
|
||||
typedef Compare key_compare;
|
||||
typedef typename sequence_type::allocator_type allocator_type;
|
||||
typedef typename sequence_type::size_type size_type;
|
||||
typedef typename sequence_type::difference_type difference_type;
|
||||
typedef typename sequence_type::iterator iterator;
|
||||
typedef typename sequence_type::const_iterator const_iterator;
|
||||
typedef typename sequence_type::reverse_iterator reverse_iterator;
|
||||
typedef typename sequence_type::const_reverse_iterator const_reverse_iterator;
|
||||
|
||||
//!Standard extension
|
||||
typedef allocator_type stored_allocator_type;
|
||||
typedef allocator_type stored_allocator_type;
|
||||
|
||||
private:
|
||||
typedef allocator_traits<stored_allocator_type> stored_allocator_traits;
|
||||
@@ -242,8 +250,8 @@ class flat_tree
|
||||
, const allocator_type& a = allocator_type())
|
||||
: m_data(comp, a)
|
||||
{
|
||||
this->m_data.m_vect.insert(this->m_data.m_vect.end(), first, last);
|
||||
BOOST_ASSERT((is_sorted)(this->m_data.m_vect.cbegin(), this->m_data.m_vect.cend(), this->priv_value_comp()));
|
||||
this->m_data.m_seq.insert(this->m_data.m_seq.end(), first, last);
|
||||
BOOST_ASSERT((is_sorted)(this->m_data.m_seq.cbegin(), this->m_data.m_seq.cend(), this->priv_value_comp()));
|
||||
}
|
||||
|
||||
template <class InputIterator>
|
||||
@@ -252,8 +260,8 @@ class flat_tree
|
||||
, const allocator_type& a = allocator_type())
|
||||
: m_data(comp, a)
|
||||
{
|
||||
this->m_data.m_vect.insert(this->m_data.m_vect.end(), first, last);
|
||||
BOOST_ASSERT((is_sorted_and_unique)(this->m_data.m_vect.cbegin(), this->m_data.m_vect.cend(), this->priv_value_comp()));
|
||||
this->m_data.m_seq.insert(this->m_data.m_seq.end(), first, last);
|
||||
BOOST_ASSERT((is_sorted_and_unique)(this->m_data.m_seq.cbegin(), this->m_data.m_seq.cend(), this->priv_value_comp()));
|
||||
}
|
||||
|
||||
template <class InputIterator>
|
||||
@@ -312,31 +320,31 @@ class flat_tree
|
||||
{ return this->m_data; }
|
||||
|
||||
BOOST_CONTAINER_FORCEINLINE allocator_type get_allocator() const
|
||||
{ return this->m_data.m_vect.get_allocator(); }
|
||||
{ return this->m_data.m_seq.get_allocator(); }
|
||||
|
||||
BOOST_CONTAINER_FORCEINLINE const stored_allocator_type &get_stored_allocator() const
|
||||
{ return this->m_data.m_vect.get_stored_allocator(); }
|
||||
{ return this->m_data.m_seq.get_stored_allocator(); }
|
||||
|
||||
BOOST_CONTAINER_FORCEINLINE stored_allocator_type &get_stored_allocator()
|
||||
{ return this->m_data.m_vect.get_stored_allocator(); }
|
||||
{ return this->m_data.m_seq.get_stored_allocator(); }
|
||||
|
||||
BOOST_CONTAINER_FORCEINLINE iterator begin()
|
||||
{ return this->m_data.m_vect.begin(); }
|
||||
{ return this->m_data.m_seq.begin(); }
|
||||
|
||||
BOOST_CONTAINER_FORCEINLINE const_iterator begin() const
|
||||
{ return this->cbegin(); }
|
||||
|
||||
BOOST_CONTAINER_FORCEINLINE const_iterator cbegin() const
|
||||
{ return this->m_data.m_vect.begin(); }
|
||||
{ return this->m_data.m_seq.begin(); }
|
||||
|
||||
BOOST_CONTAINER_FORCEINLINE iterator end()
|
||||
{ return this->m_data.m_vect.end(); }
|
||||
{ return this->m_data.m_seq.end(); }
|
||||
|
||||
BOOST_CONTAINER_FORCEINLINE const_iterator end() const
|
||||
{ return this->cend(); }
|
||||
|
||||
BOOST_CONTAINER_FORCEINLINE const_iterator cend() const
|
||||
{ return this->m_data.m_vect.end(); }
|
||||
{ return this->m_data.m_seq.end(); }
|
||||
|
||||
BOOST_CONTAINER_FORCEINLINE reverse_iterator rbegin()
|
||||
{ return reverse_iterator(this->end()); }
|
||||
@@ -357,13 +365,13 @@ class flat_tree
|
||||
{ return const_reverse_iterator(this->cbegin()); }
|
||||
|
||||
BOOST_CONTAINER_FORCEINLINE bool empty() const
|
||||
{ return this->m_data.m_vect.empty(); }
|
||||
{ return this->m_data.m_seq.empty(); }
|
||||
|
||||
BOOST_CONTAINER_FORCEINLINE size_type size() const
|
||||
{ return this->m_data.m_vect.size(); }
|
||||
{ return this->m_data.m_seq.size(); }
|
||||
|
||||
BOOST_CONTAINER_FORCEINLINE size_type max_size() const
|
||||
{ return this->m_data.m_vect.max_size(); }
|
||||
{ return this->m_data.m_seq.max_size(); }
|
||||
|
||||
BOOST_CONTAINER_FORCEINLINE void swap(flat_tree& other)
|
||||
BOOST_NOEXCEPT_IF( allocator_traits_type::is_always_equal::value
|
||||
@@ -395,14 +403,14 @@ class flat_tree
|
||||
iterator insert_equal(const value_type& val)
|
||||
{
|
||||
iterator i = this->upper_bound(KeyOfValue()(val));
|
||||
i = this->m_data.m_vect.insert(i, val);
|
||||
i = this->m_data.m_seq.insert(i, val);
|
||||
return i;
|
||||
}
|
||||
|
||||
iterator insert_equal(BOOST_RV_REF(value_type) mval)
|
||||
{
|
||||
iterator i = this->upper_bound(KeyOfValue()(mval));
|
||||
i = this->m_data.m_vect.insert(i, boost::move(mval));
|
||||
i = this->m_data.m_seq.insert(i, boost::move(mval));
|
||||
return i;
|
||||
}
|
||||
|
||||
@@ -509,7 +517,7 @@ class flat_tree
|
||||
>::type * = 0
|
||||
#endif
|
||||
)
|
||||
{ this->m_data.m_vect.merge(first, last, static_cast<const value_compare &>(this->m_data)); }
|
||||
{ this->m_data.m_seq.merge(first, last, static_cast<const value_compare &>(this->m_data)); }
|
||||
|
||||
template <class InIt>
|
||||
void insert_unique(ordered_unique_range_t, InIt first, InIt last
|
||||
@@ -538,7 +546,7 @@ class flat_tree
|
||||
>::type * = 0
|
||||
#endif
|
||||
)
|
||||
{ this->m_data.m_vect.merge_unique(first, last, static_cast<const value_compare &>(this->m_data)); }
|
||||
{ this->m_data.m_seq.merge_unique(first, last, static_cast<const value_compare &>(this->m_data)); }
|
||||
|
||||
#if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
|
||||
|
||||
@@ -606,7 +614,7 @@ class flat_tree
|
||||
typedef typename emplace_functor_type<try_emplace_t, KeyType, Args...>::type func_t;
|
||||
typedef emplace_iterator<value_type, func_t, difference_type> it_t;
|
||||
func_t func(try_emplace_t(), ::boost::forward<KeyType>(key), ::boost::forward<Args>(args)...);
|
||||
ret.first = this->m_data.m_vect.insert(data.position, it_t(func), it_t());
|
||||
ret.first = this->m_data.m_seq.insert(data.position, it_t(func), it_t());
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
@@ -675,7 +683,7 @@ class flat_tree
|
||||
typedef typename emplace_functor_type<try_emplace_t, KeyType BOOST_MOVE_I##N BOOST_MOVE_TARG##N>::type func_t;\
|
||||
typedef emplace_iterator<value_type, func_t, difference_type> it_t;\
|
||||
func_t func(try_emplace_t(), ::boost::forward<KeyType>(key) BOOST_MOVE_I##N BOOST_MOVE_FWD##N);\
|
||||
ret.first = this->m_data.m_vect.insert(data.position, it_t(func), it_t());\
|
||||
ret.first = this->m_data.m_seq.insert(data.position, it_t(func), it_t());\
|
||||
}\
|
||||
return ret;\
|
||||
}\
|
||||
@@ -702,29 +710,29 @@ class flat_tree
|
||||
typedef typename emplace_functor_type<KeyType, M>::type func_t;
|
||||
typedef emplace_iterator<value_type, func_t, difference_type> it_t;
|
||||
func_t func(boost::forward<KeyType>(key), boost::forward<M>(obj));
|
||||
ret.first = this->m_data.m_vect.insert(data.position, it_t(func), it_t());
|
||||
ret.first = this->m_data.m_seq.insert(data.position, it_t(func), it_t());
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
BOOST_CONTAINER_FORCEINLINE iterator erase(const_iterator position)
|
||||
{ return this->m_data.m_vect.erase(position); }
|
||||
{ return this->m_data.m_seq.erase(position); }
|
||||
|
||||
size_type erase(const key_type& k)
|
||||
{
|
||||
std::pair<iterator,iterator > itp = this->equal_range(k);
|
||||
size_type ret = static_cast<size_type>(itp.second-itp.first);
|
||||
if (ret){
|
||||
this->m_data.m_vect.erase(itp.first, itp.second);
|
||||
this->m_data.m_seq.erase(itp.first, itp.second);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
BOOST_CONTAINER_FORCEINLINE iterator erase(const_iterator first, const_iterator last)
|
||||
{ return this->m_data.m_vect.erase(first, last); }
|
||||
{ return this->m_data.m_seq.erase(first, last); }
|
||||
|
||||
BOOST_CONTAINER_FORCEINLINE void clear()
|
||||
{ this->m_data.m_vect.clear(); }
|
||||
{ this->m_data.m_seq.clear(); }
|
||||
|
||||
//! <b>Effects</b>: Tries to deallocate the excess of memory created
|
||||
// with previous allocations. The size of the vector is unchanged
|
||||
@@ -733,19 +741,19 @@ class flat_tree
|
||||
//!
|
||||
//! <b>Complexity</b>: Linear to size().
|
||||
BOOST_CONTAINER_FORCEINLINE void shrink_to_fit()
|
||||
{ this->m_data.m_vect.shrink_to_fit(); }
|
||||
{ this->m_data.m_seq.shrink_to_fit(); }
|
||||
|
||||
BOOST_CONTAINER_FORCEINLINE iterator nth(size_type n) BOOST_NOEXCEPT_OR_NOTHROW
|
||||
{ return this->m_data.m_vect.nth(n); }
|
||||
{ return this->m_data.m_seq.nth(n); }
|
||||
|
||||
BOOST_CONTAINER_FORCEINLINE const_iterator nth(size_type n) const BOOST_NOEXCEPT_OR_NOTHROW
|
||||
{ return this->m_data.m_vect.nth(n); }
|
||||
{ return this->m_data.m_seq.nth(n); }
|
||||
|
||||
BOOST_CONTAINER_FORCEINLINE size_type index_of(iterator p) BOOST_NOEXCEPT_OR_NOTHROW
|
||||
{ return this->m_data.m_vect.index_of(p); }
|
||||
{ return this->m_data.m_seq.index_of(p); }
|
||||
|
||||
BOOST_CONTAINER_FORCEINLINE size_type index_of(const_iterator p) const BOOST_NOEXCEPT_OR_NOTHROW
|
||||
{ return this->m_data.m_vect.index_of(p); }
|
||||
{ return this->m_data.m_seq.index_of(p); }
|
||||
|
||||
// set operations:
|
||||
iterator find(const key_type& k)
|
||||
@@ -793,7 +801,7 @@ class flat_tree
|
||||
|
||||
void merge_unique(flat_tree& source)
|
||||
{
|
||||
this->m_data.m_vect.merge_unique
|
||||
this->m_data.m_seq.merge_unique
|
||||
( boost::make_move_iterator(source.begin())
|
||||
, boost::make_move_iterator(source.end())
|
||||
, static_cast<const value_compare &>(this->m_data));
|
||||
@@ -801,7 +809,7 @@ class flat_tree
|
||||
|
||||
void merge_equal(flat_tree& source)
|
||||
{
|
||||
this->m_data.m_vect.merge
|
||||
this->m_data.m_seq.merge
|
||||
( boost::make_move_iterator(source.begin())
|
||||
, boost::make_move_iterator(source.end())
|
||||
, static_cast<const value_compare &>(this->m_data));
|
||||
@@ -832,10 +840,61 @@ class flat_tree
|
||||
{ return this->priv_lower_bound_range(this->cbegin(), this->cend(), k); }
|
||||
|
||||
BOOST_CONTAINER_FORCEINLINE size_type capacity() const
|
||||
{ return this->m_data.m_vect.capacity(); }
|
||||
{ return this->m_data.m_seq.capacity(); }
|
||||
|
||||
BOOST_CONTAINER_FORCEINLINE void reserve(size_type cnt)
|
||||
{ this->m_data.m_vect.reserve(cnt); }
|
||||
{ this->m_data.m_seq.reserve(cnt); }
|
||||
|
||||
BOOST_CONTAINER_FORCEINLINE sequence_type extract_sequence()
|
||||
{
|
||||
return boost::move(m_data.m_seq);
|
||||
}
|
||||
|
||||
BOOST_CONTAINER_FORCEINLINE sequence_type &get_sequence_ref()
|
||||
{
|
||||
return m_data.m_seq;
|
||||
}
|
||||
|
||||
void adopt_sequence_equal(BOOST_RV_REF(sequence_type) seq)
|
||||
{
|
||||
sequence_type &tseq = m_data.m_seq;
|
||||
boost::movelib::adaptive_sort
|
||||
( container_detail::iterator_to_raw_pointer(seq.begin())
|
||||
, container_detail::iterator_to_raw_pointer(seq.end())
|
||||
, this->priv_value_comp()
|
||||
, container_detail::iterator_to_raw_pointer(tseq.begin() + tseq.size())
|
||||
, tseq.capacity() - tseq.size());
|
||||
tseq = boost::move(seq);
|
||||
}
|
||||
|
||||
void adopt_sequence_equal(ordered_range_t, BOOST_RV_REF(sequence_type) seq)
|
||||
{
|
||||
BOOST_ASSERT((is_sorted)(seq.cbegin(), seq.cend(), this->priv_value_comp()));
|
||||
sequence_type &tseq = m_data.m_seq;
|
||||
tseq = boost::move(seq);
|
||||
}
|
||||
|
||||
void adopt_sequence_unique(BOOST_RV_REF(sequence_type) seq)
|
||||
{
|
||||
sequence_type &tseq = m_data.m_seq;
|
||||
boost::movelib::adaptive_sort
|
||||
( container_detail::iterator_to_raw_pointer(seq.begin())
|
||||
, container_detail::iterator_to_raw_pointer(seq.end())
|
||||
, this->priv_value_comp()
|
||||
, container_detail::iterator_to_raw_pointer(tseq.begin() + tseq.size())
|
||||
, tseq.capacity() - tseq.size());
|
||||
seq.erase( boost::movelib::unique
|
||||
(seq.begin(), seq.end(), boost::movelib::negate<value_compare>(this->m_data.get_comp()))
|
||||
, seq.cend());
|
||||
tseq = boost::move(seq);
|
||||
}
|
||||
|
||||
void adopt_sequence_unique(ordered_unique_range_t, BOOST_RV_REF(sequence_type) seq)
|
||||
{
|
||||
BOOST_ASSERT((is_sorted_and_unique)(seq.cbegin(), seq.cend(), this->priv_value_comp()));
|
||||
sequence_type &tseq = m_data.m_seq;
|
||||
tseq = boost::move(seq);
|
||||
}
|
||||
|
||||
BOOST_CONTAINER_FORCEINLINE friend bool operator==(const flat_tree& x, const flat_tree& y)
|
||||
{
|
||||
@@ -963,7 +1022,7 @@ class flat_tree
|
||||
BOOST_CONTAINER_FORCEINLINE iterator priv_insert_commit
|
||||
(insert_commit_data &commit_data, BOOST_FWD_REF(Convertible) convertible)
|
||||
{
|
||||
return this->m_data.m_vect.insert
|
||||
return this->m_data.m_seq.insert
|
||||
( commit_data.position
|
||||
, boost::forward<Convertible>(convertible));
|
||||
}
|
||||
|
@@ -144,8 +144,10 @@ class flat_map
|
||||
<typename allocator_traits<Allocator>::pointer>::reverse_iterator reverse_iterator_impl;
|
||||
typedef typename container_detail::get_flat_tree_iterators
|
||||
<typename allocator_traits<Allocator>::pointer>::const_reverse_iterator const_reverse_iterator_impl;
|
||||
|
||||
public:
|
||||
typedef typename impl_tree_t::stored_allocator_type impl_stored_allocator_type;
|
||||
typedef typename impl_tree_t::sequence_type impl_sequence_type;
|
||||
|
||||
impl_tree_t &tree()
|
||||
{ return m_flat_tree; }
|
||||
@@ -182,6 +184,7 @@ class flat_map
|
||||
typedef BOOST_CONTAINER_IMPDEF(reverse_iterator_impl) reverse_iterator;
|
||||
typedef BOOST_CONTAINER_IMPDEF(const_reverse_iterator_impl) const_reverse_iterator;
|
||||
typedef BOOST_CONTAINER_IMPDEF(impl_value_type) movable_value_type;
|
||||
typedef typename BOOST_CONTAINER_IMPDEF(tree_t::sequence_type) sequence_type;
|
||||
|
||||
public:
|
||||
//////////////////////////////////////////////
|
||||
@@ -1243,6 +1246,39 @@ class flat_map
|
||||
std::pair<const_iterator,const_iterator> equal_range(const key_type& x) const
|
||||
{ return container_detail::force_copy<std::pair<const_iterator,const_iterator> >(m_flat_tree.lower_bound_range(x)); }
|
||||
|
||||
//! <b>Effects</b>: Extracts the internal sequence container.
|
||||
//!
|
||||
//! <b>Complexity</b>: Same as the move constructor of sequence_type, usually constant.
|
||||
//!
|
||||
//! <b>Postcondition</b>: this->empty()
|
||||
//!
|
||||
//! <b>Throws</b>: If secuence_type's move constructor throws
|
||||
sequence_type extract_sequence()
|
||||
{
|
||||
return boost::move(container_detail::force<sequence_type>(m_flat_tree.get_sequence_ref()));
|
||||
}
|
||||
|
||||
//! <b>Effects</b>: Discards the internally hold sequence container and move adopts the
|
||||
//! one passed externally using the move assignment. Erases non-unique elements.
|
||||
//!
|
||||
//! <b>Complexity</b>: Assuming O(1) move assignmet, O(NlogN) with N = seq.size()
|
||||
//!
|
||||
//! <b>Throws</b>: If the comparison or the move constructor throws
|
||||
void adopt_sequence(BOOST_RV_REF(sequence_type) seq)
|
||||
{ this->m_flat_tree.adopt_sequence_unique(boost::move(container_detail::force<impl_sequence_type>(seq))); }
|
||||
|
||||
//! <b>Requires</b>: seq shall be ordered according to this->compare()
|
||||
//! and shall contain unique elements.
|
||||
//!
|
||||
//! <b>Effects</b>: Discards the internally hold sequence container and move adopts the
|
||||
//! one passed externally using the move assignment.
|
||||
//!
|
||||
//! <b>Complexity</b>: Assuming O(1) move assignment, O(1)
|
||||
//!
|
||||
//! <b>Throws</b>: If the move constructor throws
|
||||
void adopt_sequence(ordered_unique_range_t, BOOST_RV_REF(sequence_type) seq)
|
||||
{ this->m_flat_tree.adopt_sequence_unique(ordered_unique_range_t(), boost::move(container_detail::force<impl_sequence_type>(seq))); }
|
||||
|
||||
//! <b>Effects</b>: Returns true if x and y are equal
|
||||
//!
|
||||
//! <b>Complexity</b>: Linear to the number of elements in the container.
|
||||
@@ -1401,6 +1437,7 @@ class flat_multimap
|
||||
<typename allocator_traits<Allocator>::pointer>::const_reverse_iterator const_reverse_iterator_impl;
|
||||
public:
|
||||
typedef typename impl_tree_t::stored_allocator_type impl_stored_allocator_type;
|
||||
typedef typename impl_tree_t::sequence_type impl_sequence_type;
|
||||
|
||||
impl_tree_t &tree()
|
||||
{ return m_flat_tree; }
|
||||
@@ -1437,6 +1474,7 @@ class flat_multimap
|
||||
typedef BOOST_CONTAINER_IMPDEF(reverse_iterator_impl) reverse_iterator;
|
||||
typedef BOOST_CONTAINER_IMPDEF(const_reverse_iterator_impl) const_reverse_iterator;
|
||||
typedef BOOST_CONTAINER_IMPDEF(impl_value_type) movable_value_type;
|
||||
typedef typename BOOST_CONTAINER_IMPDEF(tree_t::sequence_type) sequence_type;
|
||||
|
||||
//////////////////////////////////////////////
|
||||
//
|
||||
@@ -2219,6 +2257,38 @@ class flat_multimap
|
||||
std::pair<const_iterator,const_iterator> equal_range(const key_type& x) const
|
||||
{ return container_detail::force_copy<std::pair<const_iterator,const_iterator> >(m_flat_tree.equal_range(x)); }
|
||||
|
||||
//! <b>Effects</b>: Extracts the internal sequence container.
|
||||
//!
|
||||
//! <b>Complexity</b>: Same as the move constructor of sequence_type, usually constant.
|
||||
//!
|
||||
//! <b>Postcondition</b>: this->empty()
|
||||
//!
|
||||
//! <b>Throws</b>: If secuence_type's move constructor throws
|
||||
sequence_type extract_sequence()
|
||||
{
|
||||
return boost::move(container_detail::force<sequence_type>(m_flat_tree.get_sequence_ref()));
|
||||
}
|
||||
|
||||
//! <b>Effects</b>: Discards the internally hold sequence container and move adopts the
|
||||
//! one passed externally using the move assignment.
|
||||
//!
|
||||
//! <b>Complexity</b>: Assuming O(1) move assignmet, O(NlogN) with N = seq.size()
|
||||
//!
|
||||
//! <b>Throws</b>: If the comparison or the move constructor throws
|
||||
void adopt_sequence(BOOST_RV_REF(sequence_type) seq)
|
||||
{ this->m_flat_tree.adopt_sequence_equal(boost::move(container_detail::force<impl_sequence_type>(seq))); }
|
||||
|
||||
//! <b>Requires</b>: seq shall be ordered according to this->compare().
|
||||
//!
|
||||
//! <b>Effects</b>: Discards the internally hold sequence container and move adopts the
|
||||
//! one passed externally using the move assignment.
|
||||
//!
|
||||
//! <b>Complexity</b>: Assuming O(1) move assignment, O(1)
|
||||
//!
|
||||
//! <b>Throws</b>: If the move constructor throws
|
||||
void adopt_sequence(ordered_range_t, BOOST_RV_REF(sequence_type) seq)
|
||||
{ this->m_flat_tree.adopt_sequence_equal(ordered_range_t(), boost::move(container_detail::force<impl_sequence_type>(seq))); }
|
||||
|
||||
//! <b>Effects</b>: Returns true if x and y are equal
|
||||
//!
|
||||
//! <b>Complexity</b>: Linear to the number of elements in the container.
|
||||
|
@@ -114,6 +114,7 @@ class flat_set
|
||||
typedef typename BOOST_CONTAINER_IMPDEF(base_t::const_iterator) const_iterator;
|
||||
typedef typename BOOST_CONTAINER_IMPDEF(base_t::reverse_iterator) reverse_iterator;
|
||||
typedef typename BOOST_CONTAINER_IMPDEF(base_t::const_reverse_iterator) const_reverse_iterator;
|
||||
typedef typename BOOST_CONTAINER_IMPDEF(base_t::sequence_type) sequence_type;
|
||||
|
||||
public:
|
||||
//////////////////////////////////////////////
|
||||
@@ -844,8 +845,38 @@ class flat_set
|
||||
//! <b>Complexity</b>: Constant.
|
||||
friend void swap(flat_set& x, flat_set& y);
|
||||
|
||||
//! <b>Effects</b>: Extracts the internal sequence container.
|
||||
//!
|
||||
//! <b>Complexity</b>: Same as the move constructor of sequence_type, usually constant.
|
||||
//!
|
||||
//! <b>Postcondition</b>: this->empty()
|
||||
//!
|
||||
//! <b>Throws</b>: If secuence_type's move constructor throws
|
||||
sequence_type extract_sequence();
|
||||
|
||||
#endif //#ifdef BOOST_CONTAINER_DOXYGEN_INVOKED
|
||||
|
||||
//! <b>Effects</b>: Discards the internally hold sequence container and move adopts the
|
||||
//! one passed externally using the move assignment. Erases non-unique elements.
|
||||
//!
|
||||
//! <b>Complexity</b>: Assuming O(1) move assignmet, O(NlogN) with N = seq.size()
|
||||
//!
|
||||
//! <b>Throws</b>: If the comparison or the move constructor throws
|
||||
void adopt_sequence(BOOST_RV_REF(sequence_type) seq)
|
||||
{ this->base_t::adopt_sequence_unique(boost::move(seq)); }
|
||||
|
||||
//! <b>Requires</b>: seq shall be ordered according to this->compare()
|
||||
//! and shall contain unique elements.
|
||||
//!
|
||||
//! <b>Effects</b>: Discards the internally hold sequence container and move adopts the
|
||||
//! one passed externally using the move assignment.
|
||||
//!
|
||||
//! <b>Complexity</b>: Assuming O(1) move assignment, O(1)
|
||||
//!
|
||||
//! <b>Throws</b>: If the move constructor throws
|
||||
void adopt_sequence(ordered_unique_range_t, BOOST_RV_REF(sequence_type) seq)
|
||||
{ this->base_t::adopt_sequence_unique(ordered_unique_range_t(), boost::move(seq)); }
|
||||
|
||||
#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
|
||||
private:
|
||||
template<class KeyType>
|
||||
@@ -939,6 +970,7 @@ class flat_multiset
|
||||
typedef typename BOOST_CONTAINER_IMPDEF(base_t::const_iterator) const_iterator;
|
||||
typedef typename BOOST_CONTAINER_IMPDEF(base_t::reverse_iterator) reverse_iterator;
|
||||
typedef typename BOOST_CONTAINER_IMPDEF(base_t::const_reverse_iterator) const_reverse_iterator;
|
||||
typedef typename BOOST_CONTAINER_IMPDEF(base_t::sequence_type) sequence_type;
|
||||
|
||||
//! @copydoc ::boost::container::flat_set::flat_set()
|
||||
explicit flat_multiset() BOOST_NOEXCEPT_IF(container_detail::is_nothrow_default_constructible<Allocator>::value &&
|
||||
@@ -1392,8 +1424,37 @@ class flat_multiset
|
||||
//! <b>Complexity</b>: Constant.
|
||||
friend void swap(flat_multiset& x, flat_multiset& y);
|
||||
|
||||
//! <b>Effects</b>: Extracts the internal sequence container.
|
||||
//!
|
||||
//! <b>Complexity</b>: Same as the move constructor of sequence_type, usually constant.
|
||||
//!
|
||||
//! <b>Postcondition</b>: this->empty()
|
||||
//!
|
||||
//! <b>Throws</b>: If secuence_type's move constructor throws
|
||||
sequence_type extract_sequence();
|
||||
|
||||
#endif //#ifdef BOOST_CONTAINER_DOXYGEN_INVOKED
|
||||
|
||||
//! <b>Effects</b>: Discards the internally hold sequence container and move adopts the
|
||||
//! one passed externally using the move assignment.
|
||||
//!
|
||||
//! <b>Complexity</b>: Assuming O(1) move assignmet, O(NlogN) with N = seq.size()
|
||||
//!
|
||||
//! <b>Throws</b>: If the comparison or the move constructor throws
|
||||
void adopt_sequence(BOOST_RV_REF(sequence_type) seq)
|
||||
{ this->base_t::adopt_sequence_equal(boost::move(seq)); }
|
||||
|
||||
//! <b>Requires</b>: seq shall be ordered according to this->compare()
|
||||
//!
|
||||
//! <b>Effects</b>: Discards the internally hold sequence container and move adopts the
|
||||
//! one passed externally using the move assignment.
|
||||
//!
|
||||
//! <b>Complexity</b>: Assuming O(1) move assignment, O(1)
|
||||
//!
|
||||
//! <b>Throws</b>: If the move constructor throws
|
||||
void adopt_sequence(ordered_range_t, BOOST_RV_REF(sequence_type) seq)
|
||||
{ this->base_t::adopt_sequence_equal(ordered_range_t(), boost::move(seq)); }
|
||||
|
||||
#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
|
||||
private:
|
||||
template <class KeyType>
|
||||
|
@@ -224,6 +224,116 @@ bool flat_tree_ordered_insertion_test()
|
||||
return true;
|
||||
}
|
||||
|
||||
template< class RandomIt >
|
||||
void random_shuffle( RandomIt first, RandomIt last )
|
||||
{
|
||||
typedef typename boost::container::iterator_traits<RandomIt>::difference_type difference_type;
|
||||
difference_type n = last - first;
|
||||
for (difference_type i = n-1; i > 0; --i) {
|
||||
difference_type j = std::rand() % (i+1);
|
||||
if(j != i) {
|
||||
boost::adl_move_swap(first[i], first[j]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool flat_tree_extract_adopt_test()
|
||||
{
|
||||
using namespace boost::container;
|
||||
const std::size_t NumElements = 100;
|
||||
|
||||
//extract/adopt map
|
||||
{
|
||||
//Construction insertion
|
||||
flat_map<int, int> fmap;
|
||||
|
||||
for(std::size_t i = 0; i != NumElements; ++i){
|
||||
fmap.emplace(static_cast<int>(i), -static_cast<int>(i));
|
||||
}
|
||||
|
||||
flat_map<int, int> fmap_copy(fmap);
|
||||
flat_map<int, int>::sequence_type seq(fmap.extract_sequence());
|
||||
if(!fmap.empty())
|
||||
return false;
|
||||
if(!CheckEqualContainers(seq, fmap_copy))
|
||||
return false;
|
||||
|
||||
seq.insert(seq.end(), fmap_copy.begin(), fmap_copy.end());
|
||||
boost::container::test::random_shuffle(seq.begin(), seq.end());
|
||||
fmap.adopt_sequence(boost::move(seq));
|
||||
if(!CheckEqualContainers(fmap, fmap_copy))
|
||||
return false;
|
||||
}
|
||||
|
||||
//extract/adopt map, ordered_unique_range
|
||||
{
|
||||
//Construction insertion
|
||||
flat_map<int, int> fmap;
|
||||
|
||||
for(std::size_t i = 0; i != NumElements; ++i){
|
||||
fmap.emplace(static_cast<int>(i), -static_cast<int>(i));
|
||||
}
|
||||
|
||||
flat_map<int, int> fmap_copy(fmap);
|
||||
flat_map<int, int>::sequence_type seq(fmap.extract_sequence());
|
||||
if(!fmap.empty())
|
||||
return false;
|
||||
if(!CheckEqualContainers(seq, fmap_copy))
|
||||
return false;
|
||||
|
||||
fmap.adopt_sequence(ordered_unique_range, boost::move(seq));
|
||||
if(!CheckEqualContainers(fmap, fmap_copy))
|
||||
return false;
|
||||
}
|
||||
|
||||
//extract/adopt multimap
|
||||
{
|
||||
//Construction insertion
|
||||
flat_multimap<int, int> fmmap;
|
||||
|
||||
for(std::size_t i = 0; i != NumElements; ++i){
|
||||
fmmap.emplace(static_cast<int>(i), -static_cast<int>(i));
|
||||
fmmap.emplace(static_cast<int>(i), -static_cast<int>(i));
|
||||
}
|
||||
|
||||
flat_multimap<int, int> fmmap_copy(fmmap);
|
||||
flat_multimap<int, int>::sequence_type seq(fmmap.extract_sequence());
|
||||
if(!fmmap.empty())
|
||||
return false;
|
||||
if(!CheckEqualContainers(seq, fmmap_copy))
|
||||
return false;
|
||||
|
||||
boost::container::test::random_shuffle(seq.begin(), seq.end());
|
||||
fmmap.adopt_sequence(boost::move(seq));
|
||||
if(!CheckEqualContainers(fmmap, fmmap_copy))
|
||||
return false;
|
||||
}
|
||||
|
||||
//extract/adopt multimap, ordered_range
|
||||
{
|
||||
//Construction insertion
|
||||
flat_multimap<int, int> fmmap;
|
||||
|
||||
for(std::size_t i = 0; i != NumElements; ++i){
|
||||
fmmap.emplace(static_cast<int>(i), -static_cast<int>(i));
|
||||
fmmap.emplace(static_cast<int>(i), -static_cast<int>(i));
|
||||
}
|
||||
|
||||
flat_multimap<int, int> fmmap_copy(fmmap);
|
||||
flat_multimap<int, int>::sequence_type seq(fmmap.extract_sequence());
|
||||
if(!fmmap.empty())
|
||||
return false;
|
||||
if(!CheckEqualContainers(seq, fmmap_copy))
|
||||
return false;
|
||||
|
||||
fmmap.adopt_sequence(ordered_range, boost::move(seq));
|
||||
if(!CheckEqualContainers(fmmap, fmmap_copy))
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
}}}
|
||||
|
||||
|
||||
@@ -385,6 +495,13 @@ int main()
|
||||
return 1;
|
||||
}
|
||||
|
||||
////////////////////////////////////
|
||||
// Extract/Adopt test
|
||||
////////////////////////////////////
|
||||
if(!flat_tree_extract_adopt_test()){
|
||||
return 1;
|
||||
}
|
||||
|
||||
////////////////////////////////////
|
||||
// Testing allocator implementations
|
||||
////////////////////////////////////
|
||||
|
@@ -312,6 +312,116 @@ bool flat_tree_ordered_insertion_test()
|
||||
return true;
|
||||
}
|
||||
|
||||
template< class RandomIt >
|
||||
void random_shuffle( RandomIt first, RandomIt last )
|
||||
{
|
||||
typedef typename boost::container::iterator_traits<RandomIt>::difference_type difference_type;
|
||||
difference_type n = last - first;
|
||||
for (difference_type i = n-1; i > 0; --i) {
|
||||
difference_type j = std::rand() % (i+1);
|
||||
if(j != i) {
|
||||
boost::adl_move_swap(first[i], first[j]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool flat_tree_extract_adopt_test()
|
||||
{
|
||||
using namespace boost::container;
|
||||
const std::size_t NumElements = 100;
|
||||
|
||||
//extract/adopt set
|
||||
{
|
||||
//Construction insertion
|
||||
flat_set<int> fset;
|
||||
|
||||
for(std::size_t i = 0; i != NumElements; ++i){
|
||||
fset.insert(static_cast<int>(i));
|
||||
}
|
||||
|
||||
flat_set<int> fset_copy(fset);
|
||||
flat_set<int>::sequence_type seq(fset.extract_sequence());
|
||||
if(!fset.empty())
|
||||
return false;
|
||||
if(!CheckEqualContainers(seq, fset_copy))
|
||||
return false;
|
||||
|
||||
seq.insert(seq.end(), fset_copy.begin(), fset_copy.end());
|
||||
boost::container::test::random_shuffle(seq.begin(), seq.end());
|
||||
fset.adopt_sequence(boost::move(seq));
|
||||
if(!CheckEqualContainers(fset, fset_copy))
|
||||
return false;
|
||||
}
|
||||
|
||||
//extract/adopt set, ordered_unique_range
|
||||
{
|
||||
//Construction insertion
|
||||
flat_set<int> fset;
|
||||
|
||||
for(std::size_t i = 0; i != NumElements; ++i){
|
||||
fset.insert(static_cast<int>(i));
|
||||
}
|
||||
|
||||
flat_set<int> fset_copy(fset);
|
||||
flat_set<int>::sequence_type seq(fset.extract_sequence());
|
||||
if(!fset.empty())
|
||||
return false;
|
||||
if(!CheckEqualContainers(seq, fset_copy))
|
||||
return false;
|
||||
|
||||
fset.adopt_sequence(ordered_unique_range, boost::move(seq));
|
||||
if(!CheckEqualContainers(fset, fset_copy))
|
||||
return false;
|
||||
}
|
||||
|
||||
//extract/adopt multiset
|
||||
{
|
||||
//Construction insertion
|
||||
flat_multiset<int> fmset;
|
||||
|
||||
for(std::size_t i = 0; i != NumElements; ++i){
|
||||
fmset.insert(static_cast<int>(i));
|
||||
fmset.insert(static_cast<int>(i));
|
||||
}
|
||||
|
||||
flat_multiset<int> fmset_copy(fmset);
|
||||
flat_multiset<int>::sequence_type seq(fmset.extract_sequence());
|
||||
if(!fmset.empty())
|
||||
return false;
|
||||
if(!CheckEqualContainers(seq, fmset_copy))
|
||||
return false;
|
||||
|
||||
boost::container::test::random_shuffle(seq.begin(), seq.end());
|
||||
fmset.adopt_sequence(boost::move(seq));
|
||||
if(!CheckEqualContainers(fmset, fmset_copy))
|
||||
return false;
|
||||
}
|
||||
|
||||
//extract/adopt multiset, ordered_range
|
||||
{
|
||||
//Construction insertion
|
||||
flat_multiset<int> fmset;
|
||||
|
||||
for(std::size_t i = 0; i != NumElements; ++i){
|
||||
fmset.insert(static_cast<int>(i));
|
||||
fmset.insert(static_cast<int>(i));
|
||||
}
|
||||
|
||||
flat_multiset<int> fmset_copy(fmset);
|
||||
flat_multiset<int>::sequence_type seq(fmset.extract_sequence());
|
||||
if(!fmset.empty())
|
||||
return false;
|
||||
if(!CheckEqualContainers(seq, fmset_copy))
|
||||
return false;
|
||||
|
||||
fmset.adopt_sequence(ordered_range, boost::move(seq));
|
||||
if(!CheckEqualContainers(fmset, fmset_copy))
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
}}}
|
||||
|
||||
|
||||
@@ -491,6 +601,13 @@ int main()
|
||||
return 1;
|
||||
}
|
||||
|
||||
////////////////////////////////////
|
||||
// Extract/Adopt test
|
||||
////////////////////////////////////
|
||||
if(!flat_tree_extract_adopt_test()){
|
||||
return 1;
|
||||
}
|
||||
|
||||
////////////////////////////////////
|
||||
// Testing allocator implementations
|
||||
////////////////////////////////////
|
||||
|
Reference in New Issue
Block a user