Modify flat associative containers to be adaptors if the allocator argument is a container. This allows using stable_vector, small_vector, static_vector as underlying containers.

This commit is contained in:
Ion Gaztañaga
2017-08-27 12:40:15 +02:00
parent 6530b7870f
commit 2297f6af72
16 changed files with 1008 additions and 474 deletions

View File

@@ -426,11 +426,10 @@ functions), implemented on top of std::vector. AssocVector differs from a map in
its erase functions (AssocVector::erase invalidates all iterators into the object) and in the
complexity guarantees of insert and erase (linear as opposed to constant). ]]
[*Boost.Container] `flat_[multi]map/set` containers are ordered-vector based associative containers
based on Austern's and Alexandrescu's guidelines. These ordered vector containers have also
benefited recently with the addition of `move semantics` to C++, speeding up insertion
and erasure times considerably. Flat associative containers have the following
attributes:
[*Boost.Container] `flat_[multi]map/set` containers are ordered, vector-like container based, associative
containers following Austern's and Alexandrescu's guidelines. These ordered vector containers have also
benefited with the addition of `move semantics` to C++11, speeding up insertion and
erasure times considerably. Flat associative containers have the following attributes:
* Faster lookup than standard associative containers
* Much faster iteration than standard associative containers.
@@ -1213,6 +1212,14 @@ use [*Boost.Container]? There are several reasons for that:
[section:release_notes Release Notes]
[section:release_notes_boost_1_66_00 Boost 1.66 Release]
* ['flat_[multi]map/set] can now work as container adaptors, as proposed in [@http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2017/p0429r1.pdf P0429R1].
The allocator argument is checked for ['size()] and ['empty()] members. If so, the argument is interpreted as the required underlying container.
This means that ['static_vector], ['stable_vector] and ['small_vector] can be used now with flat associative containers.
[endsect]
[section:release_notes_boost_1_65_00 Boost 1.65 Release]
* Implemented `extract_sequence`, `adopt_sequence` functions for flat_[multi]map/set associative containers.
@@ -1246,7 +1253,6 @@ use [*Boost.Container]? There are several reasons for that:
[endsect]
https://svn.boost.org/trac/boost/ticket/12577#comment:1
[section:release_notes_boost_1_62_00 Boost 1.62 Release]
* Fixed bugs:

View File

@@ -163,7 +163,7 @@ struct insert_copy_proxy
void copy_n_and_update(Allocator &, Iterator p, size_type n) const
{
BOOST_ASSERT(n == 1); (void)n;
*p =v_;
*p = v_;
}
const value_type &v_;

View File

@@ -270,12 +270,12 @@ class scoped_destructor
};
template<class Allocator>
template<class Allocator, class Value = typename Allocator::value_type>
class value_destructor
{
typedef boost::container::allocator_traits<Allocator> AllocTraits;
public:
typedef typename Allocator::value_type value_type;
typedef Value value_type;
value_destructor(Allocator &a, value_type &rv)
: rv_(rv), a_(a)
{}

View File

@@ -37,10 +37,10 @@
#include <boost/container/detail/is_sorted.hpp>
#include <boost/container/detail/type_traits.hpp>
#include <boost/container/detail/iterators.hpp>
#include <boost/container/detail/mpl.hpp>
#include <boost/container/detail/is_contiguous_container.hpp>
#include <boost/container/detail/is_container.hpp>
#ifdef BOOST_CONTAINER_VECTOR_ITERATOR_IS_POINTER
#include <boost/intrusive/pointer_traits.hpp>
#endif
#include <boost/intrusive/detail/minimal_pair_header.hpp> //pair
#include <boost/move/make_unique.hpp>
@@ -52,11 +52,152 @@
#include <boost/move/detail/fwd_macros.hpp>
#endif
#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
//merge_unique
#define BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_FUNCNAME merge_unique
#define BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_NS_BEG namespace boost { namespace container { namespace container_detail {
#define BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_NS_END }}}
#define BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_MIN 3
#define BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_MAX 3
#include <boost/intrusive/detail/has_member_function_callable_with.hpp>
//merge_equal
#define BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_FUNCNAME merge
#define BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_NS_BEG namespace boost { namespace container { namespace container_detail {
#define BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_NS_END }}}
#define BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_MIN 3
#define BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_MAX 3
#include <boost/intrusive/detail/has_member_function_callable_with.hpp>
//index_of
#define BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_FUNCNAME index_of
#define BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_NS_BEG namespace boost { namespace container { namespace container_detail {
#define BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_NS_END }}}
#define BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_MIN 1
#define BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_MAX 1
#include <boost/intrusive/detail/has_member_function_callable_with.hpp>
//nth
#define BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_FUNCNAME nth
#define BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_NS_BEG namespace boost { namespace container { namespace container_detail {
#define BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_NS_END }}}
#define BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_MIN 1
#define BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_MAX 1
#include <boost/intrusive/detail/has_member_function_callable_with.hpp>
#endif //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
namespace boost {
namespace container {
namespace container_detail {
template<class SequenceContainer, class Iterator, class Compare>
BOOST_CONTAINER_FORCEINLINE void flat_tree_merge_equal
(SequenceContainer& dest, Iterator begin, Iterator end, Compare comp, container_detail::false_)
{
typedef typename SequenceContainer::iterator iterator;
typedef typename SequenceContainer::value_type value_type;
iterator it = dest.insert( dest.end(), boost::make_move_iterator(begin), boost::make_move_iterator(end) );
if (is_contiguous_container<SequenceContainer>::value){
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());
boost::movelib::adaptive_sort(iraw, eraw, comp, sraw, dest.capacity());
boost::movelib::adaptive_merge(braw, iraw, eraw, comp, sraw, dest.capacity()- dest.size());
}
else{
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>
BOOST_CONTAINER_FORCEINLINE void flat_tree_merge_unique
(SequenceContainer& dest, Iterator begin, Iterator end, Compare comp, container_detail::false_)
{
(flat_tree_merge_equal)(dest, begin, end, comp, container_detail::false_());
dest.erase(boost::movelib::unique
(dest.begin(), dest.end(), boost::movelib::negate<Compare>(comp)), dest.cend());
}
template<class SequenceContainer, class Iterator, class Compare>
BOOST_CONTAINER_FORCEINLINE void flat_tree_merge_equal
(SequenceContainer& dest, Iterator begin, Iterator end, Compare comp, container_detail::true_)
{
dest.merge(begin, end, comp);
}
template<class SequenceContainer, class Iterator, class Compare>
BOOST_CONTAINER_FORCEINLINE void flat_tree_merge_unique
(SequenceContainer& dest, Iterator begin, Iterator end, Compare comp, container_detail::true_)
{
dest.merge_unique(begin, end, comp);
}
BOOST_INTRUSIVE_INSTANTIATE_DEFAULT_TYPE_TMPLT(stored_allocator_type)
template<class SequenceContainer, class Iterator>
BOOST_CONTAINER_FORCEINLINE typename SequenceContainer::size_type
flat_tree_index_of
(SequenceContainer& cont, Iterator p, container_detail::true_)
{
return cont.index_of(p);
}
template<class SequenceContainer, class Iterator>
BOOST_CONTAINER_FORCEINLINE typename SequenceContainer::size_type
flat_tree_index_of
(SequenceContainer& cont, Iterator p, container_detail::false_)
{
typedef typename SequenceContainer::size_type size_type;
return static_cast<size_type>(p - cont.begin());
}
template<class Iterator, class SequenceContainer>
BOOST_CONTAINER_FORCEINLINE Iterator
flat_tree_nth
(SequenceContainer& cont, typename SequenceContainer::size_type n, container_detail::true_)
{
return cont.nth(n);
}
template<class Iterator, class SequenceContainer>
BOOST_CONTAINER_FORCEINLINE Iterator
flat_tree_nth
(SequenceContainer& cont, typename SequenceContainer::size_type n, container_detail::false_)
{
return cont.begin()+ n;
}
template<class SequenceContainer>
BOOST_CONTAINER_FORCEINLINE typename SequenceContainer::stored_allocator_type &
flat_tree_get_stored_allocator
(SequenceContainer& cont, container_detail::true_)
{
return cont.get_stored_allocator();
}
template<class SequenceContainer>
BOOST_CONTAINER_FORCEINLINE const typename SequenceContainer::stored_allocator_type &
flat_tree_get_stored_allocator
(const SequenceContainer& cont, container_detail::true_)
{
return cont.get_stored_allocator();
}
template<class SequenceContainer>
BOOST_CONTAINER_FORCEINLINE typename SequenceContainer::allocator_type
flat_tree_get_stored_allocator
(SequenceContainer& cont, container_detail::false_)
{
return cont.get_allocator();
}
template<class Compare, class Value, class KeyOfValue>
class flat_tree_value_compare
: private Compare
@@ -85,37 +226,43 @@ class flat_tree_value_compare
Compare &get_comp()
{ return *this; }
};
/*
template<class Pointer>
struct get_flat_tree_iterators
{
#ifdef BOOST_CONTAINER_VECTOR_ITERATOR_IS_POINTER
typedef Pointer iterator;
typedef typename boost::intrusive::
pointer_traits<Pointer>::element_type iterator_element_type;
typedef typename boost::intrusive::
pointer_traits<Pointer>:: template
rebind_pointer<const iterator_element_type>::type const_iterator;
#else //BOOST_CONTAINER_VECTOR_ITERATOR_IS_POINTER
typedef typename boost::container::container_detail::
vec_iterator<Pointer, false> iterator;
typedef typename boost::container::container_detail::
vec_iterator<Pointer, true > const_iterator;
#endif //BOOST_CONTAINER_VECTOR_ITERATOR_IS_POINTER
typedef boost::container::reverse_iterator<iterator> reverse_iterator;
typedef boost::container::reverse_iterator<const_iterator> const_reverse_iterator;
};
*/
template < class Value, class AllocatorOrContainer
, bool = boost::container::container_detail::is_container<AllocatorOrContainer>::value >
struct select_container_type
{
typedef AllocatorOrContainer type;
};
template <class Value, class AllocatorOrContainer>
struct select_container_type<Value, AllocatorOrContainer, false>
{
typedef boost::container::vector<Value, AllocatorOrContainer> type;
};
template <class Value, class KeyOfValue,
class Compare, class Allocator>
class Compare, class AllocatorOrContainer>
class flat_tree
{
public:
typedef boost::container::vector<Value, Allocator> sequence_type;
typedef typename select_container_type<Value, AllocatorOrContainer>::type container_type;
typedef container_type sequence_type; //For backwards compatibility
private:
typedef Allocator allocator_t;
typedef allocator_traits<Allocator> allocator_traits_type;
typedef typename container_type::allocator_type allocator_t;
typedef allocator_traits<allocator_t> allocator_traits_type;
public:
typedef flat_tree_value_compare<Compare, Value, KeyOfValue> value_compare;
@@ -152,11 +299,11 @@ class flat_tree
: value_compare(boost::move(static_cast<value_compare&>(d))), m_seq(boost::move(d.m_seq))
{}
Data(const Data &d, const Allocator &a)
Data(const Data &d, const allocator_t &a)
: value_compare(static_cast<const value_compare&>(d)), m_seq(d.m_seq, a)
{}
Data(BOOST_RV_REF(Data) d, const Allocator &a)
Data(BOOST_RV_REF(Data) d, const allocator_t &a)
: value_compare(boost::move(static_cast<value_compare&>(d))), m_seq(boost::move(d.m_seq), a)
{}
@@ -181,7 +328,7 @@ class flat_tree
this->m_seq.swap(d.m_seq);
}
sequence_type m_seq;
container_type m_seq;
};
Data m_data;
@@ -189,26 +336,36 @@ class flat_tree
public:
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 container_type::value_type value_type;
typedef typename container_type::pointer pointer;
typedef typename container_type::const_pointer const_pointer;
typedef typename container_type::reference reference;
typedef typename container_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;
typedef typename container_type::allocator_type allocator_type;
typedef typename container_type::size_type size_type;
typedef typename container_type::difference_type difference_type;
typedef typename container_type::iterator iterator;
typedef typename container_type::const_iterator const_iterator;
typedef typename container_type::reverse_iterator reverse_iterator;
typedef typename container_type::const_reverse_iterator const_reverse_iterator;
//!Standard extension
typedef allocator_type stored_allocator_type;
typedef BOOST_INTRUSIVE_OBTAIN_TYPE_WITH_DEFAULT
(boost::container::container_detail::, container_type
,stored_allocator_type, allocator_type) stored_allocator_type;
static const bool has_stored_allocator_type =
BOOST_INTRUSIVE_HAS_TYPE(boost::container::container_detail::, container_type, stored_allocator_type);
private:
typedef allocator_traits<stored_allocator_type> stored_allocator_traits;
typedef typename container_detail::if_c
<has_stored_allocator_type, const stored_allocator_type &, allocator_type>::type get_stored_allocator_const_return_t;
typedef typename container_detail::if_c
<has_stored_allocator_type, stored_allocator_type &, allocator_type>::type get_stored_allocator_noconst_return_t;
public:
BOOST_CONTAINER_FORCEINLINE flat_tree()
@@ -357,6 +514,11 @@ class flat_tree
BOOST_CONTAINER_FORCEINLINE key_compare &priv_key_comp()
{ return this->priv_value_comp().get_comp(); }
struct insert_commit_data
{
const_iterator position;
};
public:
// accessors:
BOOST_CONTAINER_FORCEINLINE Compare key_comp() const
@@ -368,11 +530,15 @@ class flat_tree
BOOST_CONTAINER_FORCEINLINE allocator_type get_allocator() const
{ return this->m_data.m_seq.get_allocator(); }
BOOST_CONTAINER_FORCEINLINE const stored_allocator_type &get_stored_allocator() const
{ return this->m_data.m_seq.get_stored_allocator(); }
BOOST_CONTAINER_FORCEINLINE get_stored_allocator_const_return_t get_stored_allocator() const
{
return flat_tree_get_stored_allocator(this->m_data.m_seq, container_detail::bool_<has_stored_allocator_type>());
}
BOOST_CONTAINER_FORCEINLINE stored_allocator_type &get_stored_allocator()
{ return this->m_data.m_seq.get_stored_allocator(); }
BOOST_CONTAINER_FORCEINLINE get_stored_allocator_noconst_return_t get_stored_allocator()
{
return flat_tree_get_stored_allocator(this->m_data.m_seq, container_detail::bool_<has_stored_allocator_type>());
}
BOOST_CONTAINER_FORCEINLINE iterator begin()
{ return this->m_data.m_seq.begin(); }
@@ -432,7 +598,8 @@ class flat_tree
insert_commit_data data;
ret.second = this->priv_insert_unique_prepare(KeyOfValue()(val), data);
ret.first = ret.second ? this->priv_insert_commit(data, val)
: iterator(vector_iterator_get_ptr(data.position));
: this->begin() + (data.position - this->cbegin());
//: iterator(vector_iterator_get_ptr(data.position));
return ret;
}
@@ -442,7 +609,8 @@ class flat_tree
insert_commit_data data;
ret.second = this->priv_insert_unique_prepare(KeyOfValue()(val), data);
ret.first = ret.second ? this->priv_insert_commit(data, boost::move(val))
: iterator(vector_iterator_get_ptr(data.position));
: this->begin() + (data.position - this->cbegin());
//: iterator(vector_iterator_get_ptr(data.position));
return ret;
}
@@ -466,7 +634,8 @@ class flat_tree
insert_commit_data data;
return this->priv_insert_unique_prepare(hint, KeyOfValue()(val), data)
? this->priv_insert_commit(data, val)
: iterator(vector_iterator_get_ptr(data.position));
: this->begin() + (data.position - this->cbegin());
//: iterator(vector_iterator_get_ptr(data.position));
}
iterator insert_unique(const_iterator hint, BOOST_RV_REF(value_type) val)
@@ -475,7 +644,8 @@ class flat_tree
insert_commit_data data;
return this->priv_insert_unique_prepare(hint, KeyOfValue()(val), data)
? this->priv_insert_commit(data, boost::move(val))
: iterator(vector_iterator_get_ptr(data.position));
: this->begin() + (data.position - this->cbegin());
//: iterator(vector_iterator_get_ptr(data.position));
}
iterator insert_equal(const_iterator hint, const value_type& val)
@@ -563,7 +733,11 @@ class flat_tree
>::type * = 0
#endif
)
{ this->m_data.m_seq.merge(first, last, static_cast<const value_compare &>(this->m_data)); }
{
const bool value = boost::container::container_detail::
has_member_function_callable_with_merge_unique<container_type, iterator, iterator, value_compare>::value;
(flat_tree_merge_equal)(this->m_data.m_seq, first, last, this->priv_value_comp(), container_detail::bool_<value>());
}
template <class InIt>
void insert_unique(ordered_unique_range_t, InIt first, InIt last
@@ -592,7 +766,11 @@ class flat_tree
>::type * = 0
#endif
)
{ this->m_data.m_seq.merge_unique(first, last, static_cast<const value_compare &>(this->m_data)); }
{
const bool value = boost::container::container_detail::
has_member_function_callable_with_merge_unique<container_type, iterator, iterator, value_compare>::value;
(flat_tree_merge_unique)(this->m_data.m_seq, first, last, this->priv_value_comp(), container_detail::bool_<value>());
}
#if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
@@ -601,9 +779,9 @@ class flat_tree
{
typename aligned_storage<sizeof(value_type), alignment_of<value_type>::value>::type v;
value_type &val = *static_cast<value_type *>(static_cast<void *>(&v));
stored_allocator_type &a = this->get_stored_allocator();
get_stored_allocator_noconst_return_t a = this->get_stored_allocator();
stored_allocator_traits::construct(a, &val, ::boost::forward<Args>(args)... );
value_destructor<stored_allocator_type> d(a, val);
value_destructor<stored_allocator_type, value_type> d(a, val);
return this->insert_unique(::boost::move(val));
}
@@ -613,9 +791,9 @@ class flat_tree
//hint checked in insert_unique
typename aligned_storage<sizeof(value_type), alignment_of<value_type>::value>::type v;
value_type &val = *static_cast<value_type *>(static_cast<void *>(&v));
stored_allocator_type &a = this->get_stored_allocator();
get_stored_allocator_noconst_return_t a = this->get_stored_allocator();
stored_allocator_traits::construct(a, &val, ::boost::forward<Args>(args)... );
value_destructor<stored_allocator_type> d(a, val);
value_destructor<stored_allocator_type, value_type> d(a, val);
return this->insert_unique(hint, ::boost::move(val));
}
@@ -624,9 +802,9 @@ class flat_tree
{
typename aligned_storage<sizeof(value_type), alignment_of<value_type>::value>::type v;
value_type &val = *static_cast<value_type *>(static_cast<void *>(&v));
stored_allocator_type &a = this->get_stored_allocator();
get_stored_allocator_noconst_return_t a = this->get_stored_allocator();
stored_allocator_traits::construct(a, &val, ::boost::forward<Args>(args)... );
value_destructor<stored_allocator_type> d(a, val);
value_destructor<stored_allocator_type, value_type> d(a, val);
return this->insert_equal(::boost::move(val));
}
@@ -636,9 +814,9 @@ class flat_tree
//hint checked in insert_equal
typename aligned_storage<sizeof(value_type), alignment_of<value_type>::value>::type v;
value_type &val = *static_cast<value_type *>(static_cast<void *>(&v));
stored_allocator_type &a = this->get_stored_allocator();
get_stored_allocator_noconst_return_t a = this->get_stored_allocator();
stored_allocator_traits::construct(a, &val, ::boost::forward<Args>(args)... );
value_destructor<stored_allocator_type> d(a, val);
value_destructor<stored_allocator_type, value_type> d(a, val);
return this->insert_equal(hint, ::boost::move(val));
}
@@ -673,9 +851,9 @@ class flat_tree
{\
typename aligned_storage<sizeof(value_type), alignment_of<value_type>::value>::type v;\
value_type &val = *static_cast<value_type *>(static_cast<void *>(&v));\
stored_allocator_type &a = this->get_stored_allocator();\
get_stored_allocator_noconst_return_t a = this->get_stored_allocator();\
stored_allocator_traits::construct(a, &val BOOST_MOVE_I##N BOOST_MOVE_FWD##N);\
value_destructor<stored_allocator_type> d(a, val);\
value_destructor<stored_allocator_type, value_type> d(a, val);\
return this->insert_unique(::boost::move(val));\
}\
\
@@ -684,9 +862,9 @@ class flat_tree
{\
typename aligned_storage<sizeof(value_type), alignment_of<value_type>::value>::type v;\
value_type &val = *static_cast<value_type *>(static_cast<void *>(&v));\
stored_allocator_type &a = this->get_stored_allocator();\
get_stored_allocator_noconst_return_t a = this->get_stored_allocator();\
stored_allocator_traits::construct(a, &val BOOST_MOVE_I##N BOOST_MOVE_FWD##N);\
value_destructor<stored_allocator_type> d(a, val);\
value_destructor<stored_allocator_type, value_type> d(a, val);\
return this->insert_unique(hint, ::boost::move(val));\
}\
\
@@ -695,9 +873,9 @@ class flat_tree
{\
typename aligned_storage<sizeof(value_type), alignment_of<value_type>::value>::type v;\
value_type &val = *static_cast<value_type *>(static_cast<void *>(&v));\
stored_allocator_type &a = this->get_stored_allocator();\
get_stored_allocator_noconst_return_t a = this->get_stored_allocator();\
stored_allocator_traits::construct(a, &val BOOST_MOVE_I##N BOOST_MOVE_FWD##N);\
value_destructor<stored_allocator_type> d(a, val);\
value_destructor<stored_allocator_type, value_type> d(a, val);\
return this->insert_equal(::boost::move(val));\
}\
\
@@ -706,9 +884,9 @@ class flat_tree
{\
typename aligned_storage <sizeof(value_type), alignment_of<value_type>::value>::type v;\
value_type &val = *static_cast<value_type *>(static_cast<void *>(&v));\
stored_allocator_type &a = this->get_stored_allocator();\
get_stored_allocator_noconst_return_t a = this->get_stored_allocator();\
stored_allocator_traits::construct(a, &val BOOST_MOVE_I##N BOOST_MOVE_FWD##N);\
value_destructor<stored_allocator_type> d(a, val);\
value_destructor<stored_allocator_type, value_type> d(a, val);\
return this->insert_equal(hint, ::boost::move(val));\
}\
template <class KeyType BOOST_MOVE_I##N BOOST_MOVE_CLASS##N>\
@@ -790,16 +968,32 @@ class flat_tree
{ 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_seq.nth(n); }
{
const bool value = boost::container::container_detail::
has_member_function_callable_with_nth<container_type, size_type>::value;
return flat_tree_nth<iterator>(this->m_data.m_seq, n, container_detail::bool_<value>());
}
BOOST_CONTAINER_FORCEINLINE const_iterator nth(size_type n) const BOOST_NOEXCEPT_OR_NOTHROW
{ return this->m_data.m_seq.nth(n); }
{
const bool value = boost::container::container_detail::
has_member_function_callable_with_nth<container_type, size_type>::value;
return flat_tree_nth<const_iterator>(this->m_data.m_seq, n, container_detail::bool_<value>());
}
BOOST_CONTAINER_FORCEINLINE size_type index_of(iterator p) BOOST_NOEXCEPT_OR_NOTHROW
{ return this->m_data.m_seq.index_of(p); }
{
const bool value = boost::container::container_detail::
has_member_function_callable_with_index_of<container_type, iterator>::value;
return flat_tree_index_of(this->m_data.m_seq, p, container_detail::bool_<value>());
}
BOOST_CONTAINER_FORCEINLINE size_type index_of(const_iterator p) const BOOST_NOEXCEPT_OR_NOTHROW
{ return this->m_data.m_seq.index_of(p); }
{
const bool value = boost::container::container_detail::
has_member_function_callable_with_index_of<container_type, const_iterator>::value;
return flat_tree_index_of(this->m_data.m_seq, p, container_detail::bool_<value>());
}
// set operations:
iterator find(const key_type& k)
@@ -832,33 +1026,41 @@ class flat_tree
}
template<class C2>
void merge_unique(flat_tree<Value, KeyOfValue, C2, Allocator>& source)
BOOST_CONTAINER_FORCEINLINE void merge_unique(flat_tree<Value, KeyOfValue, C2, AllocatorOrContainer>& source)
{
this->insert( boost::make_move_iterator(source.begin())
, boost::make_move_iterator(source.end()));
}
template<class C2>
void merge_equal(flat_tree<Value, KeyOfValue, C2, Allocator>& source)
BOOST_CONTAINER_FORCEINLINE void merge_equal(flat_tree<Value, KeyOfValue, C2, AllocatorOrContainer>& source)
{
this->insert( boost::make_move_iterator(source.begin())
, boost::make_move_iterator(source.end()));
}
void merge_unique(flat_tree& source)
BOOST_CONTAINER_FORCEINLINE void merge_unique(flat_tree& source)
{
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));
const bool value = boost::container::container_detail::
has_member_function_callable_with_merge_unique<container_type, iterator, iterator, value_compare>::value;
(flat_tree_merge_unique)
( this->m_data.m_seq
, boost::make_move_iterator(source.m_data.m_seq.begin())
, boost::make_move_iterator(source.m_data.m_seq.end())
, this->priv_value_comp()
, container_detail::bool_<value>());
}
void merge_equal(flat_tree& source)
BOOST_CONTAINER_FORCEINLINE void merge_equal(flat_tree& source)
{
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));
const bool value = boost::container::container_detail::
has_member_function_callable_with_merge<container_type, iterator, iterator, value_compare>::value;
(flat_tree_merge_equal)
( this->m_data.m_seq
, boost::make_move_iterator(source.m_data.m_seq.begin())
, boost::make_move_iterator(source.m_data.m_seq.end())
, this->priv_value_comp()
, container_detail::bool_<value>());
}
BOOST_CONTAINER_FORCEINLINE iterator lower_bound(const key_type& k)
@@ -891,54 +1093,66 @@ class flat_tree
BOOST_CONTAINER_FORCEINLINE void reserve(size_type cnt)
{ this->m_data.m_seq.reserve(cnt); }
BOOST_CONTAINER_FORCEINLINE sequence_type extract_sequence()
BOOST_CONTAINER_FORCEINLINE container_type extract_sequence()
{
return boost::move(m_data.m_seq);
}
BOOST_CONTAINER_FORCEINLINE sequence_type &get_sequence_ref()
BOOST_CONTAINER_FORCEINLINE container_type &get_sequence_ref()
{
return m_data.m_seq;
}
void adopt_sequence_equal(BOOST_RV_REF(sequence_type) seq)
void adopt_sequence_equal(BOOST_RV_REF(container_type) seq)
{
sequence_type &tseq = m_data.m_seq;
boost::movelib::adaptive_sort
( boost::movelib::iterator_to_raw_pointer(seq.begin())
, boost::movelib::iterator_to_raw_pointer(seq.end())
, this->priv_value_comp()
, boost::movelib::iterator_to_raw_pointer(tseq.begin() + tseq.size())
, tseq.capacity() - tseq.size());
container_type &tseq = m_data.m_seq;
if (is_contiguous_container<container_type>::value){
boost::movelib::adaptive_sort
( boost::movelib::iterator_to_raw_pointer(seq.begin())
, boost::movelib::iterator_to_raw_pointer(seq.end())
, this->priv_value_comp()
, boost::movelib::iterator_to_raw_pointer(tseq.begin() + tseq.size())
, tseq.capacity() - tseq.size());
}
else{
boost::movelib::adaptive_sort
(seq.begin(), seq.end(), this->priv_value_comp());
}
tseq = boost::move(seq);
}
void adopt_sequence_equal(ordered_range_t, BOOST_RV_REF(sequence_type) seq)
void adopt_sequence_unique(BOOST_RV_REF(container_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
( boost::movelib::iterator_to_raw_pointer(seq.begin())
, boost::movelib::iterator_to_raw_pointer(seq.end())
, this->priv_value_comp()
, boost::movelib::iterator_to_raw_pointer(tseq.begin() + tseq.size())
, tseq.capacity() - tseq.size());
container_type &tseq = m_data.m_seq;
if (is_contiguous_container<container_type>::value){
boost::movelib::adaptive_sort
( boost::movelib::iterator_to_raw_pointer(seq.begin())
, boost::movelib::iterator_to_raw_pointer(seq.end())
, this->priv_value_comp()
, boost::movelib::iterator_to_raw_pointer(tseq.begin() + tseq.size())
, tseq.capacity() - tseq.size());
}
else{
boost::movelib::adaptive_sort
( seq.begin(), seq.end(), this->priv_value_comp());
}
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)
void adopt_sequence_equal(ordered_range_t, BOOST_RV_REF(container_type) seq)
{
BOOST_ASSERT((is_sorted)(seq.cbegin(), seq.cend(), this->priv_value_comp()));
container_type &tseq = m_data.m_seq;
tseq = boost::move(seq);
}
void adopt_sequence_unique(ordered_unique_range_t, BOOST_RV_REF(container_type) seq)
{
BOOST_ASSERT((is_sorted_and_unique)(seq.cbegin(), seq.cend(), this->priv_value_comp()));
sequence_type &tseq = m_data.m_seq;
container_type &tseq = m_data.m_seq;
tseq = boost::move(seq);
}
@@ -993,11 +1207,6 @@ class flat_tree
return (this->begin() <= pos) && (pos <= this->end());
}
struct insert_commit_data
{
const_iterator position;
};
// insert/erase
void priv_insert_equal_prepare
(const_iterator pos, const value_type& val, insert_commit_data &data)
@@ -1216,11 +1425,13 @@ class flat_tree
//!has_trivial_destructor_after_move<> == true_type
//!specialization for optimizations
template <class T, class KeyOfValue,
class Compare, class Allocator>
struct has_trivial_destructor_after_move<boost::container::container_detail::flat_tree<T, KeyOfValue, Compare, Allocator> >
class Compare, class AllocatorOrContainer>
struct has_trivial_destructor_after_move<boost::container::container_detail::flat_tree<T, KeyOfValue, Compare, AllocatorOrContainer> >
{
typedef typename ::boost::container::allocator_traits<Allocator>::pointer pointer;
static const bool value = ::boost::has_trivial_destructor_after_move<Allocator>::value &&
typedef typename boost::container::container_detail::select_container_type<T, AllocatorOrContainer>::type container_type;
typedef typename container_type::allocator_type allocator_t;
typedef typename ::boost::container::allocator_traits<allocator_t>::pointer pointer;
static const bool value = ::boost::has_trivial_destructor_after_move<allocator_t>::value &&
::boost::has_trivial_destructor_after_move<pointer>::value;
};

View File

@@ -0,0 +1,55 @@
//////////////////////////////////////////////////////////////////////////////
//
// (C) Copyright Ion Gaztanaga 2017-2017. Distributed under the Boost
// Software License, Version 1.0. (See accompanying file
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
// See http://www.boost.org/libs/container for documentation.
//
//////////////////////////////////////////////////////////////////////////////
#ifndef BOOST_CONTAINER_DETAIL_IS_CONTAINER_HPP
#define BOOST_CONTAINER_DETAIL_IS_CONTAINER_HPP
#ifndef BOOST_CONFIG_HPP
# include <boost/config.hpp>
#endif
#if defined(BOOST_HAS_PRAGMA_ONCE)
# pragma once
#endif
//empty
#define BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_FUNCNAME empty
#define BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_NS_BEG namespace boost { namespace container { namespace is_container_detail {
#define BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_NS_END }}}
#define BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_MIN 0
#define BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_MAX 0
#include <boost/intrusive/detail/has_member_function_callable_with.hpp>
//size
#define BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_FUNCNAME size
#define BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_NS_BEG namespace boost { namespace container { namespace is_container_detail {
#define BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_NS_END }}}
#define BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_MIN 0
#define BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_MAX 0
#include <boost/intrusive/detail/has_member_function_callable_with.hpp>
namespace boost {
namespace container {
namespace container_detail {
template <class Container>
struct is_container
{
static const bool value =
boost::container::is_container_detail::
has_member_function_callable_with_size <const Container>::value &&
boost::container::is_container_detail::
has_member_function_callable_with_empty<const Container>::value;
};
} //namespace container_detail {
} //namespace container {
} //namespace boost {
#endif //#ifndef BOOST_CONTAINER_DETAIL_IS_CONTAINER_HPP

View File

@@ -0,0 +1,47 @@
//////////////////////////////////////////////////////////////////////////////
//
// (C) Copyright Ion Gaztanaga 2017-2017. Distributed under the Boost
// Software License, Version 1.0. (See accompanying file
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
// See http://www.boost.org/libs/container for documentation.
//
//////////////////////////////////////////////////////////////////////////////
#ifndef BOOST_CONTAINER_DETAIL_IS_CONTIGUOUS_CONTAINER_HPP
#define BOOST_CONTAINER_DETAIL_IS_CONTIGUOUS_CONTAINER_HPP
#ifndef BOOST_CONFIG_HPP
# include <boost/config.hpp>
#endif
#if defined(BOOST_HAS_PRAGMA_ONCE)
# pragma once
#endif
//data
#define BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_FUNCNAME data
#define BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_NS_BEG namespace boost { namespace container { namespace is_contiguous_container_detail {
#define BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_NS_END }}}
#define BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_MIN 0
#define BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_MAX 0
#include <boost/intrusive/detail/has_member_function_callable_with.hpp>
namespace boost {
namespace container {
namespace container_detail {
template <class Container>
struct is_contiguous_container
{
static const bool value =
boost::container::is_contiguous_container_detail::
has_member_function_callable_with_data<Container>::value &&
boost::container::is_contiguous_container_detail::
has_member_function_callable_with_data<const Container>::value;
};
} //namespace container_detail {
} //namespace container {
} //namespace boost {
#endif //#ifndef BOOST_CONTAINER_DETAIL_IS_CONTIGUOUS_CONTAINER_HPP

View File

@@ -53,7 +53,7 @@ namespace container {
#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
template <class Key, class T, class Compare, class Allocator>
template <class Key, class T, class Compare, class AllocatorOrContainer>
class flat_multimap;
namespace container_detail{
@@ -76,37 +76,37 @@ BOOST_CONTAINER_FORCEINLINE static D force_copy(const S &s)
//! A flat_map is a kind of associative container that supports unique keys (contains at
//! most one of each key value) and provides for fast retrieval of values of another
//! type T based on the keys. The flat_map class supports random-access iterators.
//! type T based on the keys.
//!
//! A flat_map satisfies all of the requirements of a container and of a reversible
//! container and of an associative container. A flat_map also provides
//! A flat_map satisfies all of the requirements of a container, a reversible
//! container and an associative container. A flat_map also provides
//! most operations described for unique keys. For a
//! flat_map<Key,T> the key_type is Key and the value_type is std::pair<Key,T>
//! (unlike std::map<Key, T> which value_type is std::pair<<b>const</b> Key, T>).
//!
//! Compare is the ordering function for Keys (e.g. <i>std::less<Key></i>).
//! flat_map is similar to std::map but it's implemented by as an ordered sequence container.
//! The underlying sequence container is by default <i>vector</i> but it can also work
//! user-provided vector-like SequenceContainers (like <i>static_vector</i> or <i>small_vector</i>).
//!
//! Allocator is the allocator to allocate the value_types
//! (e.g. <i>allocator< std::pair<Key, T> ></i>).
//!
//! flat_map is similar to std::map but it's implemented like an ordered vector.
//! This means that inserting a new element into a flat_map invalidates
//! previous iterators and references
//!
//! Erasing an element invalidates iterators and references
//! pointing to elements that come after (their keys are bigger) the erased element.
//! Using vector-like sequence containers means that inserting a new element into a flat_map might invalidate
//! previous iterators and references (unless that sequence container is <i>stable_vector</i> or a similar
//! container that offers stable pointers and references). Similarly, erasing an element might invalidate
//! iterators and references pointing to elements that come after (their keys are bigger) the erased element.
//!
//! This container provides random-access iterators.
//!
//! \tparam Key is the key_type of the map
//! \tparam Value is the <code>mapped_type</code>
//! \tparam Compare is the ordering function for Keys (e.g. <i>std::less<Key></i>).
//! \tparam Allocator is the allocator to allocate the <code>value_type</code>s
//! (e.g. <i>allocator< std::pair<Key, T> > </i>).
//! \tparam AllocatorOrContainer is either:
//! - The allocator to allocate <code>value_type</code>s (e.g. <i>allocator< std::pair<Key, T> > </i>).
//! (in this case <i>sequence_type</i> will be vector<value_type, AllocatorOrContainer>)
//! - The SequenceContainer to be used as the underlying <i>sequence_type</i>. It must be a vector-like
//! sequence container with random-access iterators..
#ifdef BOOST_CONTAINER_DOXYGEN_INVOKED
template <class Key, class T, class Compare = std::less<Key>, class Allocator = new_allocator< std::pair< Key, T> > >
template <class Key, class T, class Compare = std::less<Key>, class AllocatorOrContainer = new_allocator< std::pair< Key, T> > >
#else
template <class Key, class T, class Compare, class Allocator>
template <class Key, class T, class Compare, class AllocatorOrContainer>
#endif
class flat_map
{
@@ -118,14 +118,14 @@ class flat_map
std::pair<Key, T>,
container_detail::select1st<Key>,
Compare,
Allocator> tree_t;
AllocatorOrContainer> tree_t;
//This is the real tree stored here. It's based on a movable pair
typedef container_detail::flat_tree<
container_detail::pair<Key, T>,
container_detail::select1st<Key>,
Compare,
typename allocator_traits<Allocator>::template portable_rebind_alloc
typename allocator_traits<AllocatorOrContainer>::template portable_rebind_alloc
<container_detail::pair<Key, T> >::type> impl_tree_t;
impl_tree_t m_flat_tree; // flat tree representing flat_map
@@ -133,18 +133,18 @@ class flat_map
typedef typename impl_tree_t::const_iterator impl_const_iterator;
typedef typename impl_tree_t::iterator impl_iterator;
typedef typename impl_tree_t::allocator_type impl_allocator_type;
#if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
typedef std::initializer_list<impl_value_type> impl_initializer_list;
#endif
typedef container_detail::flat_tree_value_compare
< Compare
, container_detail::select1st<Key>
, std::pair<Key, T> > value_compare_impl;
typedef typename container_detail::get_flat_tree_iterators
<typename allocator_traits<Allocator>::pointer>::iterator iterator_impl;
typedef typename container_detail::get_flat_tree_iterators
<typename allocator_traits<Allocator>::pointer>::const_iterator const_iterator_impl;
typedef typename container_detail::get_flat_tree_iterators
<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;
, std::pair<Key, T> > value_compare_t;
typedef typename tree_t::iterator iterator_t;
typedef typename tree_t::const_iterator const_iterator_t;
typedef typename tree_t::reverse_iterator reverse_iterator_t;
typedef typename tree_t::const_reverse_iterator const_reverse_iterator_t;
public:
typedef typename impl_tree_t::stored_allocator_type impl_stored_allocator_type;
@@ -168,27 +168,28 @@ class flat_map
//////////////////////////////////////////////
typedef Key key_type;
typedef T mapped_type;
typedef std::pair<Key, T> value_type;
typedef ::boost::container::allocator_traits<Allocator> allocator_traits_type;
typedef typename boost::container::allocator_traits<Allocator>::pointer pointer;
typedef typename boost::container::allocator_traits<Allocator>::const_pointer const_pointer;
typedef typename boost::container::allocator_traits<Allocator>::reference reference;
typedef typename boost::container::allocator_traits<Allocator>::const_reference const_reference;
typedef typename boost::container::allocator_traits<Allocator>::size_type size_type;
typedef typename boost::container::allocator_traits<Allocator>::difference_type difference_type;
typedef Allocator allocator_type;
typedef BOOST_CONTAINER_IMPDEF(Allocator) stored_allocator_type;
typedef BOOST_CONTAINER_IMPDEF(value_compare_impl) value_compare;
typedef Compare key_compare;
typedef BOOST_CONTAINER_IMPDEF(iterator_impl) iterator;
typedef BOOST_CONTAINER_IMPDEF(const_iterator_impl) const_iterator;
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 std::pair<Key, T> value_type;
typedef typename BOOST_CONTAINER_IMPDEF(tree_t::sequence_type) sequence_type;
typedef typename sequence_type::allocator_type allocator_type;
typedef ::boost::container::allocator_traits<allocator_type> allocator_traits_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 sequence_type::size_type size_type;
typedef typename sequence_type::difference_type difference_type;
typedef typename BOOST_CONTAINER_IMPDEF(tree_t::stored_allocator_type) stored_allocator_type;
typedef typename BOOST_CONTAINER_IMPDEF(tree_t::value_compare) value_compare;
//Allocator::value_type must be std::pair<Key, T>
BOOST_STATIC_ASSERT((container_detail::is_same<std::pair<Key, T>, typename Allocator::value_type>::value));
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;
typedef BOOST_CONTAINER_IMPDEF(impl_value_type) movable_value_type;
//AllocatorOrContainer::value_type must be std::pair<Key, T>
BOOST_STATIC_ASSERT((container_detail::is_same<std::pair<Key, T>, typename allocator_type::value_type>::value));
//////////////////////////////////////////////
//
@@ -199,7 +200,7 @@ class flat_map
//! <b>Effects</b>: Default constructs an empty flat_map.
//!
//! <b>Complexity</b>: Constant.
BOOST_CONTAINER_FORCEINLINE flat_map() BOOST_NOEXCEPT_IF(container_detail::is_nothrow_default_constructible<Allocator>::value &&
BOOST_CONTAINER_FORCEINLINE flat_map() BOOST_NOEXCEPT_IF(container_detail::is_nothrow_default_constructible<AllocatorOrContainer>::value &&
container_detail::is_nothrow_default_constructible<Compare>::value)
: m_flat_tree()
{}
@@ -309,7 +310,7 @@ class flat_map
template <class InputIterator>
BOOST_CONTAINER_FORCEINLINE
flat_map(ordered_unique_range_t, InputIterator first, InputIterator last, const Compare& comp, const allocator_type& a)
: m_flat_tree(ordered_range, first, last, comp, a)
: m_flat_tree(ordered_range, first, last, comp, container_detail::force<const impl_allocator_type>(a))
{}
#if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
@@ -319,7 +320,9 @@ class flat_map
//! <b>Complexity</b>: Linear in N if the range [il.begin(), il.end()) is already sorted using
//! the predicate and otherwise N logN, where N is last - first.
BOOST_CONTAINER_FORCEINLINE flat_map(std::initializer_list<value_type> il)
: m_flat_tree(true, il.begin(), il.end())
: m_flat_tree( true
, container_detail::force<impl_initializer_list>(il).begin()
, container_detail::force<impl_initializer_list>(il).end())
{}
//! <b>Effects</b>: Constructs an empty flat_map using the specified
@@ -328,7 +331,10 @@ class flat_map
//! <b>Complexity</b>: Linear in N if the range [il.begin(), il.end()) is already sorted using
//! the predicate and otherwise N logN, where N is last - first.
BOOST_CONTAINER_FORCEINLINE flat_map(std::initializer_list<value_type> il, const allocator_type& a)
: m_flat_tree(true, il.begin(), il.end(), container_detail::force<const impl_allocator_type>(a))
: m_flat_tree( true
, container_detail::force<impl_initializer_list>(il).begin()
, container_detail::force<impl_initializer_list>(il).end()
, container_detail::force<const impl_allocator_type>(a))
{}
//! <b>Effects</b>: Constructs an empty flat_map using the specified comparison object and
@@ -337,7 +343,10 @@ class flat_map
//! <b>Complexity</b>: Linear in N if the range [il.begin(), il.end()) is already sorted using
//! the predicate and otherwise N logN, where N is last - first.
BOOST_CONTAINER_FORCEINLINE flat_map(std::initializer_list<value_type> il, const Compare& comp)
: m_flat_tree(true, il.begin(), il.end(), comp)
: m_flat_tree(true
, container_detail::force<impl_initializer_list>(il).begin()
, container_detail::force<impl_initializer_list>(il).end()
, comp)
{}
//! <b>Effects</b>: Constructs an empty flat_map using the specified comparison object and
@@ -346,7 +355,11 @@ class flat_map
//! <b>Complexity</b>: Linear in N if the range [il.begin(), il.end()) is already sorted using
//! the predicate and otherwise N logN, where N is last - first.
BOOST_CONTAINER_FORCEINLINE flat_map(std::initializer_list<value_type> il, const Compare& comp, const allocator_type& a)
: m_flat_tree(true, il.begin(), il.end(), comp, container_detail::force<const impl_allocator_type>(a))
: m_flat_tree(true
, container_detail::force<impl_initializer_list>(il).begin()
, container_detail::force<impl_initializer_list>(il).end()
, comp
, container_detail::force<const impl_allocator_type>(a))
{}
//! <b>Effects</b>: Constructs an empty flat_map using and
@@ -360,7 +373,9 @@ class flat_map
//!
//! <b>Note</b>: Non-standard extension.
BOOST_CONTAINER_FORCEINLINE flat_map(ordered_unique_range_t, std::initializer_list<value_type> il)
: m_flat_tree(ordered_unique_range, il.begin(), il.end())
: m_flat_tree(ordered_unique_range
, container_detail::force<impl_initializer_list>(il).begin()
, container_detail::force<impl_initializer_list>(il).end())
{}
//! <b>Effects</b>: Constructs an empty flat_map using the specified comparison object and
@@ -374,7 +389,10 @@ class flat_map
//!
//! <b>Note</b>: Non-standard extension.
BOOST_CONTAINER_FORCEINLINE flat_map(ordered_unique_range_t, std::initializer_list<value_type> il, const Compare& comp)
: m_flat_tree(ordered_unique_range, il.begin(), il.end(), comp)
: m_flat_tree(ordered_unique_range
, container_detail::force<impl_initializer_list>(il).begin()
, container_detail::force<impl_initializer_list>(il).end()
, comp)
{}
//! <b>Effects</b>: Constructs an empty flat_map using the specified comparison object and
@@ -388,7 +406,11 @@ class flat_map
//!
//! <b>Note</b>: Non-standard extension.
BOOST_CONTAINER_FORCEINLINE flat_map(ordered_unique_range_t, std::initializer_list<value_type> il, const Compare& comp, const allocator_type& a)
: m_flat_tree(ordered_unique_range, il.begin(), il.end(), comp, a)
: m_flat_tree( ordered_unique_range
, container_detail::force<impl_initializer_list>(il).begin()
, container_detail::force<impl_initializer_list>(il).end()
, comp
, container_detail::force<const impl_allocator_type>(a))
{}
#endif
@@ -414,7 +436,7 @@ class flat_map
//!
//! <b>Complexity</b>: Linear in x.size().
BOOST_CONTAINER_FORCEINLINE flat_map(const flat_map& x, const allocator_type &a)
: m_flat_tree(x.m_flat_tree, a)
: m_flat_tree(x.m_flat_tree, container_detail::force<const impl_allocator_type>(a))
{}
//! <b>Effects</b>: Move constructs a flat_map using the specified allocator.
@@ -422,7 +444,7 @@ class flat_map
//!
//! <b>Complexity</b>: Constant if x.get_allocator() == a, linear otherwise.
BOOST_CONTAINER_FORCEINLINE flat_map(BOOST_RV_REF(flat_map) x, const allocator_type &a)
: m_flat_tree(boost::move(x.m_flat_tree), a)
: m_flat_tree(boost::move(x.m_flat_tree), container_detail::force<const impl_allocator_type>(a))
{}
//! <b>Effects</b>: Makes *this a copy of x.
@@ -1114,7 +1136,10 @@ class flat_map
//!
//! <b>Note</b>: If an element is inserted it might invalidate elements.
BOOST_CONTAINER_FORCEINLINE void insert(std::initializer_list<value_type> il)
{ m_flat_tree.insert_unique(il.begin(), il.end()); }
{
m_flat_tree.insert_unique( container_detail::force<impl_initializer_list>(il).begin()
, container_detail::force<impl_initializer_list>(il).end());
}
//! <b>Requires</b>: [il.begin(), il.end()) must be ordered according to the predicate and must be
//! unique values.
@@ -1130,7 +1155,11 @@ class flat_map
//!
//! <b>Note</b>: Non-standard extension.
BOOST_CONTAINER_FORCEINLINE void insert(ordered_unique_range_t, std::initializer_list<value_type> il)
{ m_flat_tree.insert_unique(ordered_unique_range, il.begin(), il.end()); }
{
m_flat_tree.insert_unique(ordered_unique_range
, container_detail::force<impl_initializer_list>(il).begin()
, container_detail::force<impl_initializer_list>(il).end());
}
#endif
//! <b>Requires</b>: this->get_allocator() == source.get_allocator().
@@ -1148,23 +1177,23 @@ class flat_map
//!
//! <b>Complexity</b>: N log(a.size() + N) (N has the value source.size())
template<class C2>
BOOST_CONTAINER_FORCEINLINE void merge(flat_map<Key, T, C2, Allocator>& source)
BOOST_CONTAINER_FORCEINLINE void merge(flat_map<Key, T, C2, AllocatorOrContainer>& source)
{ m_flat_tree.merge_unique(source.tree()); }
//! @copydoc ::boost::container::flat_map::merge(flat_map<Key, T, C2, Allocator>&)
//! @copydoc ::boost::container::flat_map::merge(flat_map<Key, T, C2, AllocatorOrContainer>&)
template<class C2>
BOOST_CONTAINER_FORCEINLINE void merge(BOOST_RV_REF_BEG flat_map<Key, T, C2, Allocator> BOOST_RV_REF_END source)
{ return this->merge(static_cast<flat_map<Key, T, C2, Allocator>&>(source)); }
BOOST_CONTAINER_FORCEINLINE void merge(BOOST_RV_REF_BEG flat_map<Key, T, C2, AllocatorOrContainer> BOOST_RV_REF_END source)
{ return this->merge(static_cast<flat_map<Key, T, C2, AllocatorOrContainer>&>(source)); }
//! @copydoc ::boost::container::flat_map::merge(flat_map<Key, T, C2, Allocator>&)
//! @copydoc ::boost::container::flat_map::merge(flat_map<Key, T, C2, AllocatorOrContainer>&)
template<class C2>
BOOST_CONTAINER_FORCEINLINE void merge(flat_multimap<Key, T, C2, Allocator>& source)
BOOST_CONTAINER_FORCEINLINE void merge(flat_multimap<Key, T, C2, AllocatorOrContainer>& source)
{ m_flat_tree.merge_unique(source.tree()); }
//! @copydoc ::boost::container::flat_map::merge(flat_map<Key, T, C2, Allocator>&)
//! @copydoc ::boost::container::flat_map::merge(flat_map<Key, T, C2, AllocatorOrContainer>&)
template<class C2>
BOOST_CONTAINER_FORCEINLINE void merge(BOOST_RV_REF_BEG flat_multimap<Key, T, C2, Allocator> BOOST_RV_REF_END source)
{ return this->merge(static_cast<flat_multimap<Key, T, C2, Allocator>&>(source)); }
BOOST_CONTAINER_FORCEINLINE void merge(BOOST_RV_REF_BEG flat_multimap<Key, T, C2, AllocatorOrContainer> BOOST_RV_REF_END source)
{ return this->merge(static_cast<flat_multimap<Key, T, C2, AllocatorOrContainer>&>(source)); }
//! <b>Effects</b>: Erases the element pointed to by p.
//!
@@ -1417,11 +1446,11 @@ class flat_map
//!has_trivial_destructor_after_move<> == true_type
//!specialization for optimizations
template <class Key, class T, class Compare, class Allocator>
struct has_trivial_destructor_after_move<boost::container::flat_map<Key, T, Compare, Allocator> >
template <class Key, class T, class Compare, class AllocatorOrContainer>
struct has_trivial_destructor_after_move<boost::container::flat_map<Key, T, Compare, AllocatorOrContainer> >
{
typedef typename ::boost::container::allocator_traits<Allocator>::pointer pointer;
static const bool value = ::boost::has_trivial_destructor_after_move<Allocator>::value &&
typedef typename ::boost::container::allocator_traits<AllocatorOrContainer>::pointer pointer;
static const bool value = ::boost::has_trivial_destructor_after_move<AllocatorOrContainer>::value &&
::boost::has_trivial_destructor_after_move<pointer>::value &&
::boost::has_trivial_destructor_after_move<Compare>::value;
};
@@ -1432,37 +1461,36 @@ namespace container {
//! A flat_multimap is a kind of associative container that supports equivalent keys
//! (possibly containing multiple copies of the same key value) and provides for
//! fast retrieval of values of another type T based on the keys. The flat_multimap
//! class supports random-access iterators.
//! fast retrieval of values of another type T based on the keys.
//!
//! A flat_multimap satisfies all of the requirements of a container and of a reversible
//! container and of an associative container. For a
//! flat_multimap<Key,T> the key_type is Key and the value_type is std::pair<Key,T>
//! (unlike std::multimap<Key, T> which value_type is std::pair<<b>const</b> Key, T>).
//!
//! Compare is the ordering function for Keys (e.g. <i>std::less<Key></i>).
//! flat_multimap is similar to std::multimap but it's implemented by as an ordered sequence container.
//! The underlying sequence container is by default <i>vector</i> but it can also work
//! user-provided vector-like SequenceContainers (like <i>static_vector</i> or <i>small_vector</i>).
//!
//! Allocator is the allocator to allocate the value_types
//! (e.g. <i>allocator< std::pair<Key, T> ></i>).
//!
//! flat_multimap is similar to std::multimap but it's implemented like an ordered vector.
//! This means that inserting a new element into a flat_map invalidates
//! previous iterators and references
//!
//! Erasing an element invalidates iterators and references
//! pointing to elements that come after (their keys are bigger) the erased element.
//! Using vector-like sequence containers means that inserting a new element into a flat_multimap might invalidate
//! previous iterators and references (unless that sequence container is <i>stable_vector</i> or a similar
//! container that offers stable pointers and references). Similarly, erasing an element might invalidate
//! iterators and references pointing to elements that come after (their keys are bigger) the erased element.
//!
//! This container provides random-access iterators.
//!
//! \tparam Key is the key_type of the map
//! \tparam Value is the <code>mapped_type</code>
//! \tparam Compare is the ordering function for Keys (e.g. <i>std::less<Key></i>).
//! \tparam Allocator is the allocator to allocate the <code>value_type</code>s
//! (e.g. <i>allocator< std::pair<Key, T> > </i>).
//! \tparam AllocatorOrContainer is either:
//! - The allocator to allocate <code>value_type</code>s (e.g. <i>allocator< std::pair<Key, T> > </i>).
//! (in this case <i>sequence_type</i> will be vector<value_type, AllocatorOrContainer>)
//! - The SequenceContainer to be used as the underlying <i>sequence_type</i>. It must be a vector-like
//! sequence container with random-access iterators.
#ifdef BOOST_CONTAINER_DOXYGEN_INVOKED
template <class Key, class T, class Compare = std::less<Key>, class Allocator = new_allocator< std::pair< Key, T> > >
template <class Key, class T, class Compare = std::less<Key>, class AllocatorOrContainer = new_allocator< std::pair< Key, T> > >
#else
template <class Key, class T, class Compare, class Allocator>
template <class Key, class T, class Compare, class AllocatorOrContainer>
#endif
class flat_multimap
{
@@ -1473,13 +1501,13 @@ class flat_multimap
std::pair<Key, T>,
container_detail::select1st<Key>,
Compare,
Allocator> tree_t;
AllocatorOrContainer> tree_t;
//This is the real tree stored here. It's based on a movable pair
typedef container_detail::flat_tree<
container_detail::pair<Key, T>,
container_detail::select1st<Key>,
Compare,
typename allocator_traits<Allocator>::template portable_rebind_alloc
typename allocator_traits<AllocatorOrContainer>::template portable_rebind_alloc
<container_detail::pair<Key, T> >::type> impl_tree_t;
impl_tree_t m_flat_tree; // flat tree representing flat_map
@@ -1487,21 +1515,22 @@ class flat_multimap
typedef typename impl_tree_t::const_iterator impl_const_iterator;
typedef typename impl_tree_t::iterator impl_iterator;
typedef typename impl_tree_t::allocator_type impl_allocator_type;
#if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
typedef std::initializer_list<impl_value_type> impl_initializer_list;
#endif
typedef container_detail::flat_tree_value_compare
< Compare
, container_detail::select1st<Key>
, std::pair<Key, T> > value_compare_impl;
typedef typename container_detail::get_flat_tree_iterators
<typename allocator_traits<Allocator>::pointer>::iterator iterator_impl;
typedef typename container_detail::get_flat_tree_iterators
<typename allocator_traits<Allocator>::pointer>::const_iterator const_iterator_impl;
typedef typename container_detail::get_flat_tree_iterators
<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;
, std::pair<Key, T> > value_compare_t;
typedef typename tree_t::iterator iterator_t;
typedef typename tree_t::const_iterator const_iterator_t;
typedef typename tree_t::reverse_iterator reverse_iterator_t;
typedef typename tree_t::const_reverse_iterator const_reverse_iterator_t;
public:
typedef typename impl_tree_t::stored_allocator_type impl_stored_allocator_type;
typedef typename impl_tree_t::sequence_type impl_sequence_type;
typedef typename impl_tree_t::stored_allocator_type impl_stored_allocator_type;
typedef typename impl_tree_t::sequence_type impl_sequence_type;
BOOST_CONTAINER_FORCEINLINE impl_tree_t &tree()
{ return m_flat_tree; }
@@ -1521,27 +1550,28 @@ class flat_multimap
//////////////////////////////////////////////
typedef Key key_type;
typedef T mapped_type;
typedef std::pair<Key, T> value_type;
typedef ::boost::container::allocator_traits<Allocator> allocator_traits_type;
typedef typename boost::container::allocator_traits<Allocator>::pointer pointer;
typedef typename boost::container::allocator_traits<Allocator>::const_pointer const_pointer;
typedef typename boost::container::allocator_traits<Allocator>::reference reference;
typedef typename boost::container::allocator_traits<Allocator>::const_reference const_reference;
typedef typename boost::container::allocator_traits<Allocator>::size_type size_type;
typedef typename boost::container::allocator_traits<Allocator>::difference_type difference_type;
typedef Allocator allocator_type;
typedef BOOST_CONTAINER_IMPDEF(Allocator) stored_allocator_type;
typedef BOOST_CONTAINER_IMPDEF(value_compare_impl) value_compare;
typedef Compare key_compare;
typedef BOOST_CONTAINER_IMPDEF(iterator_impl) iterator;
typedef BOOST_CONTAINER_IMPDEF(const_iterator_impl) const_iterator;
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 std::pair<Key, T> value_type;
typedef typename BOOST_CONTAINER_IMPDEF(tree_t::sequence_type) sequence_type;
typedef typename sequence_type::allocator_type allocator_type;
typedef ::boost::container::allocator_traits<allocator_type> allocator_traits_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 sequence_type::size_type size_type;
typedef typename sequence_type::difference_type difference_type;
typedef typename BOOST_CONTAINER_IMPDEF(tree_t::stored_allocator_type) stored_allocator_type;
typedef typename BOOST_CONTAINER_IMPDEF(tree_t::value_compare) value_compare;
//Allocator::value_type must be std::pair<Key, T>
BOOST_STATIC_ASSERT((container_detail::is_same<std::pair<Key, T>, typename Allocator::value_type>::value));
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;
typedef BOOST_CONTAINER_IMPDEF(impl_value_type) movable_value_type;
//AllocatorOrContainer::value_type must be std::pair<Key, T>
BOOST_STATIC_ASSERT((container_detail::is_same<std::pair<Key, T>, typename AllocatorOrContainer::value_type>::value));
//////////////////////////////////////////////
//
@@ -1553,7 +1583,7 @@ class flat_multimap
//!
//! <b>Complexity</b>: Constant.
BOOST_CONTAINER_FORCEINLINE flat_multimap()
BOOST_NOEXCEPT_IF(container_detail::is_nothrow_default_constructible<Allocator>::value &&
BOOST_NOEXCEPT_IF(container_detail::is_nothrow_default_constructible<AllocatorOrContainer>::value &&
container_detail::is_nothrow_default_constructible<Compare>::value)
: m_flat_tree()
{}
@@ -1679,7 +1709,9 @@ class flat_multimap
//! the predicate and otherwise N logN, where N is last - first.
BOOST_CONTAINER_FORCEINLINE
flat_multimap(std::initializer_list<value_type> il)
: m_flat_tree(false, il.begin(), il.end())
: m_flat_tree( false
, container_detail::force<impl_initializer_list>(il).begin()
, container_detail::force<impl_initializer_list>(il).end())
{}
//! <b>Effects</b>: Constructs an empty flat_map using the specified
@@ -1689,7 +1721,10 @@ class flat_multimap
//! the predicate and otherwise N logN, where N is last - first.
BOOST_CONTAINER_FORCEINLINE
flat_multimap(std::initializer_list<value_type> il, const allocator_type& a)
: m_flat_tree(false, il.begin(), il.end(), container_detail::force<const impl_allocator_type>(a))
: m_flat_tree(false
, container_detail::force<impl_initializer_list>(il).begin()
, container_detail::force<impl_initializer_list>(il).end()
, container_detail::force<const impl_allocator_type>(a))
{}
//! <b>Effects</b>: Constructs an empty flat_map using the specified comparison object and
@@ -1699,7 +1734,9 @@ class flat_multimap
//! the predicate and otherwise N logN, where N is last - first.
BOOST_CONTAINER_FORCEINLINE
flat_multimap(std::initializer_list<value_type> il, const Compare& comp)
: m_flat_tree(false, il.begin(), il.end(), comp)
: m_flat_tree(false
, container_detail::force<impl_initializer_list>(il).begin()
, container_detail::force<impl_initializer_list>(il).end(), comp)
{}
//! <b>Effects</b>: Constructs an empty flat_map using the specified comparison object and
@@ -1709,7 +1746,10 @@ class flat_multimap
//! the predicate and otherwise N logN, where N is last - first.
BOOST_CONTAINER_FORCEINLINE
flat_multimap(std::initializer_list<value_type> il, const Compare& comp, const allocator_type& a)
: m_flat_tree(false, il.begin(), il.end(), comp, container_detail::force<const impl_allocator_type>(a))
: m_flat_tree( false
, container_detail::force<impl_initializer_list>(il).begin()
, container_detail::force<impl_initializer_list>(il).end()
, comp, container_detail::force<const impl_allocator_type>(a))
{}
//! <b>Effects</b>: Constructs an empty flat_multimap and
@@ -1723,7 +1763,9 @@ class flat_multimap
//! <b>Note</b>: Non-standard extension.
BOOST_CONTAINER_FORCEINLINE
flat_multimap(ordered_range_t, std::initializer_list<value_type> il)
: m_flat_tree(ordered_range, il.begin(), il.end())
: m_flat_tree( ordered_range
, container_detail::force<impl_initializer_list>(il).begin()
, container_detail::force<impl_initializer_list>(il).end())
{}
//! <b>Effects</b>: Constructs an empty flat_multimap using the specified comparison object and
@@ -1737,7 +1779,9 @@ class flat_multimap
//! <b>Note</b>: Non-standard extension.
BOOST_CONTAINER_FORCEINLINE
flat_multimap(ordered_range_t, std::initializer_list<value_type> il, const Compare& comp)
: m_flat_tree(ordered_range, il.begin(), il.end(), comp)
: m_flat_tree( ordered_range
, container_detail::force<impl_initializer_list>(il).begin()
, container_detail::force<impl_initializer_list>(il).end(), comp)
{}
//! <b>Effects</b>: Constructs an empty flat_multimap using the specified comparison object and
@@ -1751,7 +1795,10 @@ class flat_multimap
//! <b>Note</b>: Non-standard extension.
BOOST_CONTAINER_FORCEINLINE
flat_multimap(ordered_range_t, std::initializer_list<value_type> il, const Compare& comp, const allocator_type& a)
: m_flat_tree(ordered_range, il.begin(), il.end(), comp, a)
: m_flat_tree( ordered_range
, container_detail::force<impl_initializer_list>(il).begin()
, container_detail::force<impl_initializer_list>(il).end()
, comp, a)
{}
#endif
@@ -2235,7 +2282,10 @@ class flat_multimap
//!
//! <b>Note</b>: If an element is inserted it might invalidate elements.
BOOST_CONTAINER_FORCEINLINE void insert(std::initializer_list<value_type> il)
{ m_flat_tree.insert_equal(il.begin(), il.end()); }
{
m_flat_tree.insert_equal( container_detail::force<impl_initializer_list>(il).begin()
, container_detail::force<impl_initializer_list>(il).end());
}
//! <b>Requires</b>: [il.begin(), il.end()) must be ordered according to the predicate.
//!
@@ -2250,7 +2300,11 @@ class flat_multimap
//!
//! <b>Note</b>: Non-standard extension.
BOOST_CONTAINER_FORCEINLINE void insert(ordered_range_t, std::initializer_list<value_type> il)
{ m_flat_tree.insert_equal(ordered_range, il.begin(), il.end()); }
{
m_flat_tree.insert_equal( ordered_range
, container_detail::force<impl_initializer_list>(il).begin()
, container_detail::force<impl_initializer_list>(il).end());
}
#endif
//! <b>Requires</b>: this->get_allocator() == source.get_allocator().
@@ -2267,23 +2321,23 @@ class flat_multimap
//!
//! <b>Complexity</b>: N log(a.size() + N) (N has the value source.size())
template<class C2>
BOOST_CONTAINER_FORCEINLINE void merge(flat_multimap<Key, T, C2, Allocator>& source)
BOOST_CONTAINER_FORCEINLINE void merge(flat_multimap<Key, T, C2, AllocatorOrContainer>& source)
{ m_flat_tree.merge_equal(source.tree()); }
//! @copydoc ::boost::container::flat_multimap::merge(flat_multimap<Key, T, C2, Allocator>&)
//! @copydoc ::boost::container::flat_multimap::merge(flat_multimap<Key, T, C2, AllocatorOrContainer>&)
template<class C2>
BOOST_CONTAINER_FORCEINLINE void merge(BOOST_RV_REF_BEG flat_multimap<Key, T, C2, Allocator> BOOST_RV_REF_END source)
{ return this->merge(static_cast<flat_multimap<Key, T, C2, Allocator>&>(source)); }
BOOST_CONTAINER_FORCEINLINE void merge(BOOST_RV_REF_BEG flat_multimap<Key, T, C2, AllocatorOrContainer> BOOST_RV_REF_END source)
{ return this->merge(static_cast<flat_multimap<Key, T, C2, AllocatorOrContainer>&>(source)); }
//! @copydoc ::boost::container::flat_multimap::merge(flat_multimap<Key, T, C2, Allocator>&)
//! @copydoc ::boost::container::flat_multimap::merge(flat_multimap<Key, T, C2, AllocatorOrContainer>&)
template<class C2>
BOOST_CONTAINER_FORCEINLINE void merge(flat_map<Key, T, C2, Allocator>& source)
BOOST_CONTAINER_FORCEINLINE void merge(flat_map<Key, T, C2, AllocatorOrContainer>& source)
{ m_flat_tree.merge_equal(source.tree()); }
//! @copydoc ::boost::container::flat_multimap::merge(flat_map<Key, T, C2, Allocator>&)
//! @copydoc ::boost::container::flat_multimap::merge(flat_map<Key, T, C2, AllocatorOrContainer>&)
template<class C2>
BOOST_CONTAINER_FORCEINLINE void merge(BOOST_RV_REF_BEG flat_map<Key, T, C2, Allocator> BOOST_RV_REF_END source)
{ return this->merge(static_cast<flat_map<Key, T, C2, Allocator>&>(source)); }
BOOST_CONTAINER_FORCEINLINE void merge(BOOST_RV_REF_BEG flat_map<Key, T, C2, AllocatorOrContainer> BOOST_RV_REF_END source)
{ return this->merge(static_cast<flat_map<Key, T, C2, AllocatorOrContainer>&>(source)); }
//! <b>Effects</b>: Erases the element pointed to by p.
//!
@@ -2512,11 +2566,11 @@ namespace boost {
//!has_trivial_destructor_after_move<> == true_type
//!specialization for optimizations
template <class Key, class T, class Compare, class Allocator>
struct has_trivial_destructor_after_move< boost::container::flat_multimap<Key, T, Compare, Allocator> >
template <class Key, class T, class Compare, class AllocatorOrContainer>
struct has_trivial_destructor_after_move< boost::container::flat_multimap<Key, T, Compare, AllocatorOrContainer> >
{
typedef typename ::boost::container::allocator_traits<Allocator>::pointer pointer;
static const bool value = ::boost::has_trivial_destructor_after_move<Allocator>::value &&
typedef typename ::boost::container::allocator_traits<AllocatorOrContainer>::pointer pointer;
static const bool value = ::boost::has_trivial_destructor_after_move<AllocatorOrContainer>::value &&
::boost::has_trivial_destructor_after_move<pointer>::value &&
::boost::has_trivial_destructor_after_move<Compare>::value;
};

View File

@@ -48,45 +48,51 @@ namespace boost {
namespace container {
#if !defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
template <class Key, class T, class Compare, class Allocator>
class flat_multimap;
template <class Key, class Compare, class AllocatorOrContainer>
class flat_multiset;
#endif
//! flat_set is a Sorted Associative Container that stores objects of type Key.
//! It is also a Unique Associative Container, meaning that no two elements are the same.
//!
//! flat_set is similar to std::set but it's implemented like an ordered vector.
//! This means that inserting a new element into a flat_set invalidates
//! previous iterators and references
//! flat_set is similar to std::set but it's implemented by as an ordered sequence container.
//! The underlying sequence container is by default <i>vector</i> but it can also work
//! user-provided vector-like SequenceContainers (like <i>static_vector</i> or <i>small_vector</i>).
//!
//! Erasing an element of a flat_set invalidates iterators and references
//! pointing to elements that come after (their keys are bigger) the erased element.
//! Using vector-like sequence containers means that inserting a new element into a flat_set might invalidate
//! previous iterators and references (unless that sequence container is <i>stable_vector</i> or a similar
//! container that offers stable pointers and references). Similarly, erasing an element might invalidate
//! iterators and references pointing to elements that come after (their keys are bigger) the erased element.
//!
//! This container provides random-access iterators.
//!
//! \tparam Key is the type to be inserted in the set, which is also the key_type
//! \tparam Compare is the comparison functor used to order keys
//! \tparam Allocator is the allocator to be used to allocate memory for this container
//! \tparam AllocatorOrContainer is either:
//! - The allocator to allocate <code>value_type</code>s (e.g. <i>allocator< std::pair<Key, T> > </i>).
//! (in this case <i>sequence_type</i> will be vector<value_type, AllocatorOrContainer>)
//! - The SequenceContainer to be used as the underlying <i>sequence_type</i>. It must be a vector-like
//! sequence container with random-access iterators.
#ifdef BOOST_CONTAINER_DOXYGEN_INVOKED
template <class Key, class Compare = std::less<Key>, class Allocator = new_allocator<Key> >
template <class Key, class Compare = std::less<Key>, class AllocatorOrContainer = new_allocator<Key> >
#else
template <class Key, class Compare, class Allocator>
template <class Key, class Compare, class AllocatorOrContainer>
#endif
class flat_set
///@cond
: public container_detail::flat_tree<Key, container_detail::identity<Key>, Compare, Allocator>
: public container_detail::flat_tree<Key, container_detail::identity<Key>, Compare, AllocatorOrContainer>
///@endcond
{
#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
private:
BOOST_COPYABLE_AND_MOVABLE(flat_set)
typedef container_detail::flat_tree<Key, container_detail::identity<Key>, Compare, Allocator> base_t;
typedef container_detail::flat_tree<Key, container_detail::identity<Key>, Compare, AllocatorOrContainer> tree_t;
public:
base_t &tree()
tree_t &tree()
{ return *this; }
const base_t &tree() const
const tree_t &tree() const
{ return *this; }
#endif //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
@@ -97,24 +103,25 @@ class flat_set
// types
//
//////////////////////////////////////////////
typedef Key key_type;
typedef Key value_type;
typedef Compare key_compare;
typedef Compare value_compare;
typedef ::boost::container::allocator_traits<Allocator> allocator_traits_type;
typedef typename ::boost::container::allocator_traits<Allocator>::pointer pointer;
typedef typename ::boost::container::allocator_traits<Allocator>::const_pointer const_pointer;
typedef typename ::boost::container::allocator_traits<Allocator>::reference reference;
typedef typename ::boost::container::allocator_traits<Allocator>::const_reference const_reference;
typedef typename ::boost::container::allocator_traits<Allocator>::size_type size_type;
typedef typename ::boost::container::allocator_traits<Allocator>::difference_type difference_type;
typedef Allocator allocator_type;
typedef typename BOOST_CONTAINER_IMPDEF(base_t::stored_allocator_type) stored_allocator_type;
typedef typename BOOST_CONTAINER_IMPDEF(base_t::iterator) iterator;
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;
typedef Key key_type;
typedef Compare key_compare;
typedef Key value_type;
typedef typename BOOST_CONTAINER_IMPDEF(tree_t::sequence_type) sequence_type;
typedef typename sequence_type::allocator_type allocator_type;
typedef ::boost::container::allocator_traits<allocator_type> allocator_traits_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 sequence_type::size_type size_type;
typedef typename sequence_type::difference_type difference_type;
typedef typename BOOST_CONTAINER_IMPDEF(tree_t::stored_allocator_type) stored_allocator_type;
typedef typename BOOST_CONTAINER_IMPDEF(tree_t::value_compare) value_compare;
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;
public:
//////////////////////////////////////////////
@@ -127,9 +134,9 @@ class flat_set
//!
//! <b>Complexity</b>: Constant.
BOOST_CONTAINER_FORCEINLINE
flat_set() BOOST_NOEXCEPT_IF(container_detail::is_nothrow_default_constructible<Allocator>::value &&
flat_set() BOOST_NOEXCEPT_IF(container_detail::is_nothrow_default_constructible<AllocatorOrContainer>::value &&
container_detail::is_nothrow_default_constructible<Compare>::value)
: base_t()
: tree_t()
{}
//! <b>Effects</b>: Constructs an empty container using the specified
@@ -138,7 +145,7 @@ class flat_set
//! <b>Complexity</b>: Constant.
BOOST_CONTAINER_FORCEINLINE
explicit flat_set(const Compare& comp)
: base_t(comp)
: tree_t(comp)
{}
//! <b>Effects</b>: Constructs an empty container using the specified allocator.
@@ -146,7 +153,7 @@ class flat_set
//! <b>Complexity</b>: Constant.
BOOST_CONTAINER_FORCEINLINE
explicit flat_set(const allocator_type& a)
: base_t(a)
: tree_t(a)
{}
//! <b>Effects</b>: Constructs an empty container using the specified
@@ -155,7 +162,7 @@ class flat_set
//! <b>Complexity</b>: Constant.
BOOST_CONTAINER_FORCEINLINE
flat_set(const Compare& comp, const allocator_type& a)
: base_t(comp, a)
: tree_t(comp, a)
{}
//! <b>Effects</b>: Constructs an empty container and
@@ -166,7 +173,7 @@ class flat_set
template <class InputIterator>
BOOST_CONTAINER_FORCEINLINE
flat_set(InputIterator first, InputIterator last)
: base_t(true, first, last)
: tree_t(true, first, last)
{}
//! <b>Effects</b>: Constructs an empty container using the specified
@@ -177,7 +184,7 @@ class flat_set
template <class InputIterator>
BOOST_CONTAINER_FORCEINLINE
flat_set(InputIterator first, InputIterator last, const allocator_type& a)
: base_t(true, first, last, a)
: tree_t(true, first, last, a)
{}
//! <b>Effects</b>: Constructs an empty container using the specified comparison object and
@@ -188,7 +195,7 @@ class flat_set
template <class InputIterator>
BOOST_CONTAINER_FORCEINLINE
flat_set(InputIterator first, InputIterator last, const Compare& comp)
: base_t(true, first, last, comp)
: tree_t(true, first, last, comp)
{}
//! <b>Effects</b>: Constructs an empty container using the specified comparison object and
@@ -199,7 +206,7 @@ class flat_set
template <class InputIterator>
BOOST_CONTAINER_FORCEINLINE
flat_set(InputIterator first, InputIterator last, const Compare& comp, const allocator_type& a)
: base_t(true, first, last, comp, a)
: tree_t(true, first, last, comp, a)
{}
//! <b>Effects</b>: Constructs an empty container and
@@ -215,7 +222,7 @@ class flat_set
template <class InputIterator>
BOOST_CONTAINER_FORCEINLINE
flat_set(ordered_unique_range_t, InputIterator first, InputIterator last)
: base_t(ordered_unique_range, first, last)
: tree_t(ordered_unique_range, first, last)
{}
//! <b>Effects</b>: Constructs an empty container using the specified comparison object and
@@ -231,7 +238,7 @@ class flat_set
template <class InputIterator>
BOOST_CONTAINER_FORCEINLINE
flat_set(ordered_unique_range_t, InputIterator first, InputIterator last, const Compare& comp)
: base_t(ordered_unique_range, first, last, comp)
: tree_t(ordered_unique_range, first, last, comp)
{}
//! <b>Effects</b>: Constructs an empty container using the specified comparison object and
@@ -247,7 +254,7 @@ class flat_set
template <class InputIterator>
BOOST_CONTAINER_FORCEINLINE
flat_set(ordered_unique_range_t, InputIterator first, InputIterator last, const Compare& comp, const allocator_type& a)
: base_t(ordered_unique_range, first, last, comp, a)
: tree_t(ordered_unique_range, first, last, comp, a)
{}
#if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
@@ -257,7 +264,7 @@ class flat_set
//! <b>Complexity</b>: Linear in N if the range [il.begin(), il.end()) is already sorted using
//! comp and otherwise N logN, where N is il.begin() - il.end().
BOOST_CONTAINER_FORCEINLINE flat_set(std::initializer_list<value_type> il)
: base_t(true, il.begin(), il.end())
: tree_t(true, il.begin(), il.end())
{}
//! <b>Effects</b>: Constructs an empty container using the specified
@@ -266,7 +273,7 @@ class flat_set
//! <b>Complexity</b>: Linear in N if the range [il.begin(), il.end()) is already sorted using
//! comp and otherwise N logN, where N is il.begin() - il.end().
BOOST_CONTAINER_FORCEINLINE flat_set(std::initializer_list<value_type> il, const allocator_type& a)
: base_t(true, il.begin(), il.end(), a)
: tree_t(true, il.begin(), il.end(), a)
{}
//! <b>Effects</b>: Constructs an empty container using the specified comparison object and
@@ -275,7 +282,7 @@ class flat_set
//! <b>Complexity</b>: Linear in N if the range [il.begin(), il.end()) is already sorted using
//! comp and otherwise N logN, where N is il.begin() - il.end().
BOOST_CONTAINER_FORCEINLINE flat_set(std::initializer_list<value_type> il, const Compare& comp)
: base_t(true, il.begin(), il.end(), comp)
: tree_t(true, il.begin(), il.end(), comp)
{}
//! <b>Effects</b>: Constructs an empty container using the specified comparison object and
@@ -284,7 +291,7 @@ class flat_set
//! <b>Complexity</b>: Linear in N if the range [il.begin(), il.end()) is already sorted using
//! comp and otherwise N logN, where N is il.begin() - il.end().
BOOST_CONTAINER_FORCEINLINE flat_set(std::initializer_list<value_type> il, const Compare& comp, const allocator_type& a)
: base_t(true, il.begin(), il.end(), comp, a)
: tree_t(true, il.begin(), il.end(), comp, a)
{}
//! <b>Effects</b>: Constructs an empty container using the specified comparison object and
@@ -298,7 +305,7 @@ class flat_set
//!
//! <b>Note</b>: Non-standard extension.
BOOST_CONTAINER_FORCEINLINE flat_set(ordered_unique_range_t, std::initializer_list<value_type> il)
: base_t(ordered_unique_range, il.begin(), il.end())
: tree_t(ordered_unique_range, il.begin(), il.end())
{}
//! <b>Effects</b>: Constructs an empty container using the specified comparison object and
@@ -312,7 +319,7 @@ class flat_set
//!
//! <b>Note</b>: Non-standard extension.
BOOST_CONTAINER_FORCEINLINE flat_set(ordered_unique_range_t, std::initializer_list<value_type> il, const Compare& comp)
: base_t(ordered_unique_range, il.begin(), il.end(), comp)
: tree_t(ordered_unique_range, il.begin(), il.end(), comp)
{}
//! <b>Effects</b>: Constructs an empty container using the specified comparison object and
@@ -326,7 +333,7 @@ class flat_set
//!
//! <b>Note</b>: Non-standard extension.
BOOST_CONTAINER_FORCEINLINE flat_set(ordered_unique_range_t, std::initializer_list<value_type> il, const Compare& comp, const allocator_type& a)
: base_t(ordered_unique_range, il.begin(), il.end(), comp, a)
: tree_t(ordered_unique_range, il.begin(), il.end(), comp, a)
{}
#endif
@@ -334,7 +341,7 @@ class flat_set
//!
//! <b>Complexity</b>: Linear in x.size().
BOOST_CONTAINER_FORCEINLINE flat_set(const flat_set& x)
: base_t(static_cast<const base_t&>(x))
: tree_t(static_cast<const tree_t&>(x))
{}
//! <b>Effects</b>: Move constructs thecontainer. Constructs *this using x's resources.
@@ -344,14 +351,14 @@ class flat_set
//! <b>Postcondition</b>: x is emptied.
BOOST_CONTAINER_FORCEINLINE flat_set(BOOST_RV_REF(flat_set) x)
BOOST_NOEXCEPT_IF(boost::container::container_detail::is_nothrow_move_constructible<Compare>::value)
: base_t(BOOST_MOVE_BASE(base_t, x))
: tree_t(BOOST_MOVE_BASE(tree_t, x))
{}
//! <b>Effects</b>: Copy constructs a container using the specified allocator.
//!
//! <b>Complexity</b>: Linear in x.size().
BOOST_CONTAINER_FORCEINLINE flat_set(const flat_set& x, const allocator_type &a)
: base_t(static_cast<const base_t&>(x), a)
: tree_t(static_cast<const tree_t&>(x), a)
{}
//! <b>Effects</b>: Move constructs a container using the specified allocator.
@@ -359,14 +366,14 @@ class flat_set
//!
//! <b>Complexity</b>: Constant if a == x.get_allocator(), linear otherwise
BOOST_CONTAINER_FORCEINLINE flat_set(BOOST_RV_REF(flat_set) x, const allocator_type &a)
: base_t(BOOST_MOVE_BASE(base_t, x), a)
: tree_t(BOOST_MOVE_BASE(tree_t, x), a)
{}
//! <b>Effects</b>: Makes *this a copy of x.
//!
//! <b>Complexity</b>: Linear in x.size().
BOOST_CONTAINER_FORCEINLINE flat_set& operator=(BOOST_COPY_ASSIGN_REF(flat_set) x)
{ return static_cast<flat_set&>(this->base_t::operator=(static_cast<const base_t&>(x))); }
{ return static_cast<flat_set&>(this->tree_t::operator=(static_cast<const tree_t&>(x))); }
//! <b>Throws</b>: If allocator_traits_type::propagate_on_container_move_assignment
//! is false and (allocation throws or value_type's move constructor throws)
@@ -378,7 +385,7 @@ class flat_set
BOOST_NOEXCEPT_IF( (allocator_traits_type::propagate_on_container_move_assignment::value ||
allocator_traits_type::is_always_equal::value) &&
boost::container::container_detail::is_nothrow_move_assignable<Compare>::value)
{ return static_cast<flat_set&>(this->base_t::operator=(BOOST_MOVE_BASE(base_t, x))); }
{ return static_cast<flat_set&>(this->tree_t::operator=(BOOST_MOVE_BASE(tree_t, x))); }
#if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
//! <b>Effects</b>: Copy all elements from il to *this.
@@ -579,7 +586,7 @@ class flat_set
//! <b>Note</b>: If an element is inserted it might invalidate elements.
template <class... Args>
BOOST_CONTAINER_FORCEINLINE std::pair<iterator,bool> emplace(BOOST_FWD_REF(Args)... args)
{ return this->base_t::emplace_unique(boost::forward<Args>(args)...); }
{ return this->tree_t::emplace_unique(boost::forward<Args>(args)...); }
//! <b>Effects</b>: Inserts an object of type Key constructed with
//! std::forward<Args>(args)... in the container if and only if there is
@@ -595,18 +602,18 @@ class flat_set
//! <b>Note</b>: If an element is inserted it might invalidate elements.
template <class... Args>
BOOST_CONTAINER_FORCEINLINE iterator emplace_hint(const_iterator p, BOOST_FWD_REF(Args)... args)
{ return this->base_t::emplace_hint_unique(p, boost::forward<Args>(args)...); }
{ return this->tree_t::emplace_hint_unique(p, boost::forward<Args>(args)...); }
#else // !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
#define BOOST_CONTAINER_FLAT_SET_EMPLACE_CODE(N) \
BOOST_MOVE_TMPL_LT##N BOOST_MOVE_CLASS##N BOOST_MOVE_GT##N \
BOOST_CONTAINER_FORCEINLINE std::pair<iterator,bool> emplace(BOOST_MOVE_UREF##N)\
{ return this->base_t::emplace_unique(BOOST_MOVE_FWD##N); }\
{ return this->tree_t::emplace_unique(BOOST_MOVE_FWD##N); }\
\
BOOST_MOVE_TMPL_LT##N BOOST_MOVE_CLASS##N BOOST_MOVE_GT##N \
BOOST_CONTAINER_FORCEINLINE iterator emplace_hint(const_iterator hint BOOST_MOVE_I##N BOOST_MOVE_UREF##N)\
{ return this->base_t::emplace_hint_unique(hint BOOST_MOVE_I##N BOOST_MOVE_FWD##N); }\
{ return this->tree_t::emplace_hint_unique(hint BOOST_MOVE_I##N BOOST_MOVE_FWD##N); }\
//
BOOST_MOVE_ITERATE_0TO9(BOOST_CONTAINER_FLAT_SET_EMPLACE_CODE)
#undef BOOST_CONTAINER_FLAT_SET_EMPLACE_CODE
@@ -685,7 +692,7 @@ class flat_set
//! <b>Note</b>: If an element is inserted it might invalidate elements.
template <class InputIterator>
BOOST_CONTAINER_FORCEINLINE void insert(InputIterator first, InputIterator last)
{ this->base_t::insert_unique(first, last); }
{ this->tree_t::insert_unique(first, last); }
//! <b>Requires</b>: first, last are not iterators into *this and
//! must be ordered according to the predicate and must be
@@ -700,7 +707,7 @@ class flat_set
//! <b>Note</b>: Non-standard extension. If an element is inserted it might invalidate elements.
template <class InputIterator>
BOOST_CONTAINER_FORCEINLINE void insert(ordered_unique_range_t, InputIterator first, InputIterator last)
{ this->base_t::insert_unique(ordered_unique_range, first, last); }
{ this->tree_t::insert_unique(ordered_unique_range, first, last); }
#if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
//! <b>Effects</b>: inserts each element from the range [il.begin(), il.end()) if and only
@@ -711,7 +718,7 @@ class flat_set
//!
//! <b>Note</b>: If an element is inserted it might invalidate elements.
BOOST_CONTAINER_FORCEINLINE void insert(std::initializer_list<value_type> il)
{ this->base_t::insert_unique(il.begin(), il.end()); }
{ this->tree_t::insert_unique(il.begin(), il.end()); }
//! <b>Requires</b>: Range [il.begin(), il.end()) must be ordered according to the predicate
//! and must be unique values.
@@ -724,28 +731,28 @@ class flat_set
//!
//! <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)
{ this->base_t::insert_unique(ordered_unique_range, il.begin(), il.end()); }
{ this->tree_t::insert_unique(ordered_unique_range, il.begin(), il.end()); }
#endif
//! @copydoc ::boost::container::flat_map::merge(flat_map<Key, T, C2, Allocator>&)
//! @copydoc ::boost::container::flat_map::merge(flat_map<Key, T, C2, AllocatorOrContainer>&)
template<class C2>
BOOST_CONTAINER_FORCEINLINE void merge(flat_set<Key, C2, Allocator>& source)
{ this->base_t::merge_unique(source.tree()); }
BOOST_CONTAINER_FORCEINLINE void merge(flat_set<Key, C2, AllocatorOrContainer>& source)
{ this->tree_t::merge_unique(source.tree()); }
//! @copydoc ::boost::container::flat_set::merge(flat_set<Key, C2, Allocator>&)
//! @copydoc ::boost::container::flat_set::merge(flat_set<Key, C2, AllocatorOrContainer>&)
template<class C2>
BOOST_CONTAINER_FORCEINLINE void merge(BOOST_RV_REF_BEG flat_set<Key, C2, Allocator> BOOST_RV_REF_END source)
{ return this->merge(static_cast<flat_set<Key, C2, Allocator>&>(source)); }
BOOST_CONTAINER_FORCEINLINE void merge(BOOST_RV_REF_BEG flat_set<Key, C2, AllocatorOrContainer> BOOST_RV_REF_END source)
{ return this->merge(static_cast<flat_set<Key, C2, AllocatorOrContainer>&>(source)); }
//! @copydoc ::boost::container::flat_map::merge(flat_multimap<Key, T, C2, Allocator>&)
//! @copydoc ::boost::container::flat_map::merge(flat_multimap<Key, T, C2, AllocatorOrContainer>&)
template<class C2>
BOOST_CONTAINER_FORCEINLINE void merge(flat_multiset<Key, C2, Allocator>& source)
{ this->base_t::merge_unique(source.tree()); }
BOOST_CONTAINER_FORCEINLINE void merge(flat_multiset<Key, C2, AllocatorOrContainer>& source)
{ this->tree_t::merge_unique(source.tree()); }
//! @copydoc ::boost::container::flat_set::merge(flat_multiset<Key, C2, Allocator>&)
//! @copydoc ::boost::container::flat_set::merge(flat_multiset<Key, C2, AllocatorOrContainer>&)
template<class C2>
BOOST_CONTAINER_FORCEINLINE void merge(BOOST_RV_REF_BEG flat_multiset<Key, C2, Allocator> BOOST_RV_REF_END source)
{ return this->merge(static_cast<flat_multiset<Key, C2, Allocator>&>(source)); }
BOOST_CONTAINER_FORCEINLINE void merge(BOOST_RV_REF_BEG flat_multiset<Key, C2, AllocatorOrContainer> BOOST_RV_REF_END source)
{ return this->merge(static_cast<flat_multiset<Key, C2, AllocatorOrContainer>&>(source)); }
#if defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
@@ -875,7 +882,7 @@ class flat_set
//!
//! <b>Complexity</b>: log(size())+count(k)
BOOST_CONTAINER_FORCEINLINE size_type count(const key_type& x) const
{ return static_cast<size_type>(this->base_t::find(x) != this->base_t::cend()); }
{ return static_cast<size_type>(this->tree_t::find(x) != this->tree_t::cend()); }
#if defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
//! <b>Returns</b>: An iterator pointing to the first element with key not less
@@ -908,13 +915,13 @@ class flat_set
//!
//! <b>Complexity</b>: Logarithmic
BOOST_CONTAINER_FORCEINLINE std::pair<const_iterator, const_iterator> equal_range(const key_type& x) const
{ return this->base_t::lower_bound_range(x); }
{ return this->tree_t::lower_bound_range(x); }
//! <b>Effects</b>: Equivalent to std::make_pair(this->lower_bound(k), this->upper_bound(k)).
//!
//! <b>Complexity</b>: Logarithmic
BOOST_CONTAINER_FORCEINLINE std::pair<iterator,iterator> equal_range(const key_type& x)
{ return this->base_t::lower_bound_range(x); }
{ return this->tree_t::lower_bound_range(x); }
#if defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
@@ -971,7 +978,7 @@ class flat_set
//!
//! <b>Throws</b>: If the comparison or the move constructor throws
BOOST_CONTAINER_FORCEINLINE void adopt_sequence(BOOST_RV_REF(sequence_type) seq)
{ this->base_t::adopt_sequence_unique(boost::move(seq)); }
{ this->tree_t::adopt_sequence_unique(boost::move(seq)); }
//! <b>Requires</b>: seq shall be ordered according to this->compare()
//! and shall contain unique elements.
@@ -983,17 +990,17 @@ class flat_set
//!
//! <b>Throws</b>: If the move assignment throws
BOOST_CONTAINER_FORCEINLINE 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)); }
{ this->tree_t::adopt_sequence_unique(ordered_unique_range_t(), boost::move(seq)); }
#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
private:
template<class KeyType>
BOOST_CONTAINER_FORCEINLINE std::pair<iterator, bool> priv_insert(BOOST_FWD_REF(KeyType) x)
{ return this->base_t::insert_unique(::boost::forward<KeyType>(x)); }
{ return this->tree_t::insert_unique(::boost::forward<KeyType>(x)); }
template<class KeyType>
BOOST_CONTAINER_FORCEINLINE iterator priv_insert(const_iterator p, BOOST_FWD_REF(KeyType) x)
{ return this->base_t::insert_unique(p, ::boost::forward<KeyType>(x)); }
{ return this->tree_t::insert_unique(p, ::boost::forward<KeyType>(x)); }
#endif //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
};
@@ -1003,11 +1010,11 @@ class flat_set
//!has_trivial_destructor_after_move<> == true_type
//!specialization for optimizations
template <class Key, class Compare, class Allocator>
struct has_trivial_destructor_after_move<boost::container::flat_set<Key, Compare, Allocator> >
template <class Key, class Compare, class AllocatorOrContainer>
struct has_trivial_destructor_after_move<boost::container::flat_set<Key, Compare, AllocatorOrContainer> >
{
typedef typename ::boost::container::allocator_traits<Allocator>::pointer pointer;
static const bool value = ::boost::has_trivial_destructor_after_move<Allocator>::value &&
typedef typename ::boost::container::allocator_traits<AllocatorOrContainer>::pointer pointer;
static const bool value = ::boost::has_trivial_destructor_after_move<AllocatorOrContainer>::value &&
::boost::has_trivial_destructor_after_move<pointer>::value &&
::boost::has_trivial_destructor_after_move<Compare>::value;
};
@@ -1016,42 +1023,47 @@ namespace container {
#endif //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
//! flat_multiset is a Sorted Associative Container that stores objects of type Key.
//! flat_multiset is a Sorted Associative Container that stores objects of type Key and
//! can store multiple copies of the same key value.
//!
//! flat_multiset can store multiple copies of the same key value.
//! flat_multiset is similar to std::multiset but it's implemented by as an ordered sequence container.
//! The underlying sequence container is by default <i>vector</i> but it can also work
//! user-provided vector-like SequenceContainers (like <i>static_vector</i> or <i>small_vector</i>).
//!
//! flat_multiset is similar to std::multiset but it's implemented like an ordered vector.
//! This means that inserting a new element into a flat_multiset invalidates
//! previous iterators and references
//!
//! Erasing an element invalidates iterators and references
//! pointing to elements that come after (their keys are bigger) the erased element.
//! Using vector-like sequence containers means that inserting a new element into a flat_multiset might invalidate
//! previous iterators and references (unless that sequence container is <i>stable_vector</i> or a similar
//! container that offers stable pointers and references). Similarly, erasing an element might invalidate
//! iterators and references pointing to elements that come after (their keys are bigger) the erased element.
//!
//! This container provides random-access iterators.
//!
//! \tparam Key is the type to be inserted in the multiset, which is also the key_type
//! \tparam Compare is the comparison functor used to order keys
//! \tparam Allocator is the allocator to be used to allocate memory for this container
//! \tparam AllocatorOrContainer is either:
//! - The allocator to allocate <code>value_type</code>s (e.g. <i>allocator< std::pair<Key, T> > </i>).
//! (in this case <i>sequence_type</i> will be vector<value_type, AllocatorOrContainer>)
//! - The SequenceContainer to be used as the underlying <i>sequence_type</i>. It must be a vector-like
//! sequence container with random-access iterators.
#ifdef BOOST_CONTAINER_DOXYGEN_INVOKED
template <class Key, class Compare = std::less<Key>, class Allocator = new_allocator<Key> >
template <class Key, class Compare = std::less<Key>, class AllocatorOrContainer = new_allocator<Key> >
#else
template <class Key, class Compare, class Allocator>
template <class Key, class Compare, class AllocatorOrContainer>
#endif
class flat_multiset
///@cond
: public container_detail::flat_tree<Key, container_detail::identity<Key>, Compare, Allocator>
: public container_detail::flat_tree<Key, container_detail::identity<Key>, Compare, AllocatorOrContainer>
///@endcond
{
#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
private:
BOOST_COPYABLE_AND_MOVABLE(flat_multiset)
typedef container_detail::flat_tree<Key, container_detail::identity<Key>, Compare, Allocator> base_t;
typedef container_detail::flat_tree<Key, container_detail::identity<Key>, Compare, AllocatorOrContainer> tree_t;
public:
base_t &tree()
tree_t &tree()
{ return *this; }
const base_t &tree() const
const tree_t &tree() const
{ return *this; }
#endif //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
@@ -1061,68 +1073,69 @@ class flat_multiset
// types
//
//////////////////////////////////////////////
typedef Key key_type;
typedef Key value_type;
typedef Compare key_compare;
typedef Compare value_compare;
typedef ::boost::container::allocator_traits<Allocator> allocator_traits_type;
typedef typename ::boost::container::allocator_traits<Allocator>::pointer pointer;
typedef typename ::boost::container::allocator_traits<Allocator>::const_pointer const_pointer;
typedef typename ::boost::container::allocator_traits<Allocator>::reference reference;
typedef typename ::boost::container::allocator_traits<Allocator>::const_reference const_reference;
typedef typename ::boost::container::allocator_traits<Allocator>::size_type size_type;
typedef typename ::boost::container::allocator_traits<Allocator>::difference_type difference_type;
typedef Allocator allocator_type;
typedef typename BOOST_CONTAINER_IMPDEF(base_t::stored_allocator_type) stored_allocator_type;
typedef typename BOOST_CONTAINER_IMPDEF(base_t::iterator) iterator;
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;
typedef Key key_type;
typedef Compare key_compare;
typedef Key value_type;
typedef typename BOOST_CONTAINER_IMPDEF(tree_t::sequence_type) sequence_type;
typedef typename sequence_type::allocator_type allocator_type;
typedef ::boost::container::allocator_traits<allocator_type> allocator_traits_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 sequence_type::size_type size_type;
typedef typename sequence_type::difference_type difference_type;
typedef typename BOOST_CONTAINER_IMPDEF(tree_t::stored_allocator_type) stored_allocator_type;
typedef typename BOOST_CONTAINER_IMPDEF(tree_t::value_compare) value_compare;
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;
//! @copydoc ::boost::container::flat_set::flat_set()
BOOST_CONTAINER_FORCEINLINE flat_multiset() BOOST_NOEXCEPT_IF(container_detail::is_nothrow_default_constructible<Allocator>::value &&
BOOST_CONTAINER_FORCEINLINE flat_multiset() BOOST_NOEXCEPT_IF(container_detail::is_nothrow_default_constructible<AllocatorOrContainer>::value &&
container_detail::is_nothrow_default_constructible<Compare>::value)
: base_t()
: tree_t()
{}
//! @copydoc ::boost::container::flat_set::flat_set(const Compare&)
BOOST_CONTAINER_FORCEINLINE explicit flat_multiset(const Compare& comp)
: base_t(comp)
: tree_t(comp)
{}
//! @copydoc ::boost::container::flat_set::flat_set(const allocator_type&)
BOOST_CONTAINER_FORCEINLINE explicit flat_multiset(const allocator_type& a)
: base_t(a)
: tree_t(a)
{}
//! @copydoc ::boost::container::flat_set::flat_set(const Compare&, const allocator_type&)
BOOST_CONTAINER_FORCEINLINE flat_multiset(const Compare& comp, const allocator_type& a)
: base_t(comp, a)
: tree_t(comp, a)
{}
//! @copydoc ::boost::container::flat_set::flat_set(InputIterator, InputIterator)
template <class InputIterator>
BOOST_CONTAINER_FORCEINLINE flat_multiset(InputIterator first, InputIterator last)
: base_t(false, first, last)
: tree_t(false, first, last)
{}
//! @copydoc ::boost::container::flat_set::flat_set(InputIterator, InputIterator, const allocator_type&)
template <class InputIterator>
BOOST_CONTAINER_FORCEINLINE flat_multiset(InputIterator first, InputIterator last, const allocator_type& a)
: base_t(false, first, last, a)
: tree_t(false, first, last, a)
{}
//! @copydoc ::boost::container::flat_set::flat_set(InputIterator, InputIterator, const Compare& comp)
template <class InputIterator>
BOOST_CONTAINER_FORCEINLINE flat_multiset(InputIterator first, InputIterator last, const Compare& comp)
: base_t(false, first, last, comp)
: tree_t(false, first, last, comp)
{}
//! @copydoc ::boost::container::flat_set::flat_set(InputIterator, InputIterator, const Compare& comp, const allocator_type&)
template <class InputIterator>
BOOST_CONTAINER_FORCEINLINE flat_multiset(InputIterator first, InputIterator last, const Compare& comp, const allocator_type& a)
: base_t(false, first, last, comp, a)
: tree_t(false, first, last, comp, a)
{}
//! <b>Effects</b>: Constructs an empty flat_multiset and
@@ -1136,7 +1149,7 @@ class flat_multiset
//! <b>Note</b>: Non-standard extension.
template <class InputIterator>
BOOST_CONTAINER_FORCEINLINE flat_multiset(ordered_range_t, InputIterator first, InputIterator last)
: base_t(ordered_range, first, last)
: tree_t(ordered_range, first, last)
{}
//! <b>Effects</b>: Constructs an empty flat_multiset using the specified comparison object and
@@ -1150,7 +1163,7 @@ class flat_multiset
//! <b>Note</b>: Non-standard extension.
template <class InputIterator>
BOOST_CONTAINER_FORCEINLINE flat_multiset(ordered_range_t, InputIterator first, InputIterator last, const Compare& comp)
: base_t(ordered_range, first, last, comp)
: tree_t(ordered_range, first, last, comp)
{}
//! <b>Effects</b>: Constructs an empty flat_multiset using the specified comparison object and
@@ -1164,28 +1177,28 @@ class flat_multiset
//! <b>Note</b>: Non-standard extension.
template <class InputIterator>
BOOST_CONTAINER_FORCEINLINE flat_multiset(ordered_range_t, InputIterator first, InputIterator last, const Compare& comp, const allocator_type& a)
: base_t(ordered_range, first, last, comp, a)
: tree_t(ordered_range, first, last, comp, a)
{}
#if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
//! @copydoc ::boost::container::flat_set::flat_set(std::initializer_list<value_type)
BOOST_CONTAINER_FORCEINLINE flat_multiset(std::initializer_list<value_type> il)
: base_t(false, il.begin(), il.end())
: tree_t(false, il.begin(), il.end())
{}
//! @copydoc ::boost::container::flat_set::flat_set(std::initializer_list<value_type>, const allocator_type&)
BOOST_CONTAINER_FORCEINLINE flat_multiset(std::initializer_list<value_type> il, const allocator_type& a)
: base_t(false, il.begin(), il.end(), a)
: tree_t(false, il.begin(), il.end(), a)
{}
//! @copydoc ::boost::container::flat_set::flat_set(std::initializer_list<value_type>, const Compare& comp)
BOOST_CONTAINER_FORCEINLINE flat_multiset(std::initializer_list<value_type> il, const Compare& comp)
: base_t(false, il.begin(), il.end(), comp)
: tree_t(false, il.begin(), il.end(), comp)
{}
//! @copydoc ::boost::container::flat_set::flat_set(std::initializer_list<value_type>, const Compare& comp, const allocator_type&)
BOOST_CONTAINER_FORCEINLINE flat_multiset(std::initializer_list<value_type> il, const Compare& comp, const allocator_type& a)
: base_t(false, il.begin(), il.end(), comp, a)
: tree_t(false, il.begin(), il.end(), comp, a)
{}
//! <b>Effects</b>: Constructs an empty containerand
@@ -1198,7 +1211,7 @@ class flat_multiset
//!
//! <b>Note</b>: Non-standard extension.
BOOST_CONTAINER_FORCEINLINE flat_multiset(ordered_range_t, std::initializer_list<value_type> il)
: base_t(ordered_range, il.begin(), il.end())
: tree_t(ordered_range, il.begin(), il.end())
{}
//! <b>Effects</b>: Constructs an empty container using the specified comparison object and
@@ -1211,7 +1224,7 @@ class flat_multiset
//!
//! <b>Note</b>: Non-standard extension.
BOOST_CONTAINER_FORCEINLINE flat_multiset(ordered_range_t, std::initializer_list<value_type> il, const Compare& comp)
: base_t(ordered_range, il.begin(), il.end(), comp)
: tree_t(ordered_range, il.begin(), il.end(), comp)
{}
//! <b>Effects</b>: Constructs an empty container using the specified comparison object and
@@ -1224,41 +1237,41 @@ class flat_multiset
//!
//! <b>Note</b>: Non-standard extension.
BOOST_CONTAINER_FORCEINLINE flat_multiset(ordered_range_t, std::initializer_list<value_type> il, const Compare& comp, const allocator_type& a)
: base_t(ordered_range, il.begin(), il.end(), comp, a)
: tree_t(ordered_range, il.begin(), il.end(), comp, a)
{}
#endif
//! @copydoc ::boost::container::flat_set::flat_set(const flat_set &)
BOOST_CONTAINER_FORCEINLINE flat_multiset(const flat_multiset& x)
: base_t(static_cast<const base_t&>(x))
: tree_t(static_cast<const tree_t&>(x))
{}
//! @copydoc ::boost::container::flat_set::flat_set(flat_set &&)
BOOST_CONTAINER_FORCEINLINE flat_multiset(BOOST_RV_REF(flat_multiset) x)
BOOST_NOEXCEPT_IF(boost::container::container_detail::is_nothrow_move_constructible<Compare>::value)
: base_t(boost::move(static_cast<base_t&>(x)))
: tree_t(boost::move(static_cast<tree_t&>(x)))
{}
//! @copydoc ::boost::container::flat_set::flat_set(const flat_set &, const allocator_type &)
BOOST_CONTAINER_FORCEINLINE flat_multiset(const flat_multiset& x, const allocator_type &a)
: base_t(static_cast<const base_t&>(x), a)
: tree_t(static_cast<const tree_t&>(x), a)
{}
//! @copydoc ::boost::container::flat_set::flat_set(flat_set &&, const allocator_type &)
BOOST_CONTAINER_FORCEINLINE flat_multiset(BOOST_RV_REF(flat_multiset) x, const allocator_type &a)
: base_t(BOOST_MOVE_BASE(base_t, x), a)
: tree_t(BOOST_MOVE_BASE(tree_t, x), a)
{}
//! @copydoc ::boost::container::flat_set::operator=(const flat_set &)
BOOST_CONTAINER_FORCEINLINE flat_multiset& operator=(BOOST_COPY_ASSIGN_REF(flat_multiset) x)
{ return static_cast<flat_multiset&>(this->base_t::operator=(static_cast<const base_t&>(x))); }
{ return static_cast<flat_multiset&>(this->tree_t::operator=(static_cast<const tree_t&>(x))); }
//! @copydoc ::boost::container::flat_set::operator=(flat_set &&)
BOOST_CONTAINER_FORCEINLINE flat_multiset& operator=(BOOST_RV_REF(flat_multiset) x)
BOOST_NOEXCEPT_IF( (allocator_traits_type::propagate_on_container_move_assignment::value ||
allocator_traits_type::is_always_equal::value) &&
boost::container::container_detail::is_nothrow_move_assignable<Compare>::value)
{ return static_cast<flat_multiset&>(this->base_t::operator=(BOOST_MOVE_BASE(base_t, x))); }
{ return static_cast<flat_multiset&>(this->tree_t::operator=(BOOST_MOVE_BASE(tree_t, x))); }
#if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
//! @copydoc ::boost::container::flat_set::operator=(std::initializer_list<value_type>)
@@ -1355,7 +1368,7 @@ class flat_multiset
//! <b>Note</b>: If an element is inserted it might invalidate elements.
template <class... Args>
BOOST_CONTAINER_FORCEINLINE iterator emplace(BOOST_FWD_REF(Args)... args)
{ return this->base_t::emplace_equal(boost::forward<Args>(args)...); }
{ return this->tree_t::emplace_equal(boost::forward<Args>(args)...); }
//! <b>Effects</b>: Inserts an object of type Key constructed with
//! std::forward<Args>(args)... in the container.
@@ -1370,18 +1383,18 @@ class flat_multiset
//! <b>Note</b>: If an element is inserted it might invalidate elements.
template <class... Args>
BOOST_CONTAINER_FORCEINLINE iterator emplace_hint(const_iterator p, BOOST_FWD_REF(Args)... args)
{ return this->base_t::emplace_hint_equal(p, boost::forward<Args>(args)...); }
{ return this->tree_t::emplace_hint_equal(p, boost::forward<Args>(args)...); }
#else // !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
#define BOOST_CONTAINER_FLAT_MULTISET_EMPLACE_CODE(N) \
BOOST_MOVE_TMPL_LT##N BOOST_MOVE_CLASS##N BOOST_MOVE_GT##N \
BOOST_CONTAINER_FORCEINLINE iterator emplace(BOOST_MOVE_UREF##N)\
{ return this->base_t::emplace_equal(BOOST_MOVE_FWD##N); }\
{ return this->tree_t::emplace_equal(BOOST_MOVE_FWD##N); }\
\
BOOST_MOVE_TMPL_LT##N BOOST_MOVE_CLASS##N BOOST_MOVE_GT##N \
BOOST_CONTAINER_FORCEINLINE iterator emplace_hint(const_iterator hint BOOST_MOVE_I##N BOOST_MOVE_UREF##N)\
{ return this->base_t::emplace_hint_equal(hint BOOST_MOVE_I##N BOOST_MOVE_FWD##N); }\
{ return this->tree_t::emplace_hint_equal(hint BOOST_MOVE_I##N BOOST_MOVE_FWD##N); }\
//
BOOST_MOVE_ITERATE_0TO9(BOOST_CONTAINER_FLAT_MULTISET_EMPLACE_CODE)
#undef BOOST_CONTAINER_FLAT_MULTISET_EMPLACE_CODE
@@ -1448,7 +1461,7 @@ class flat_multiset
//! <b>Note</b>: If an element is inserted it might invalidate elements.
template <class InputIterator>
BOOST_CONTAINER_FORCEINLINE void insert(InputIterator first, InputIterator last)
{ this->base_t::insert_equal(first, last); }
{ this->tree_t::insert_equal(first, last); }
//! <b>Requires</b>: first, last are not iterators into *this and
//! must be ordered according to the predicate.
@@ -1462,7 +1475,7 @@ class flat_multiset
//! <b>Note</b>: Non-standard extension. If an element is inserted it might invalidate elements.
template <class InputIterator>
BOOST_CONTAINER_FORCEINLINE void insert(ordered_range_t, InputIterator first, InputIterator last)
{ this->base_t::insert_equal(ordered_range, first, last); }
{ this->tree_t::insert_equal(ordered_range, first, last); }
#if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
//! <b>Effects</b>: inserts each element from the range [il.begin(), il.end()).
@@ -1472,7 +1485,7 @@ class flat_multiset
//!
//! <b>Note</b>: If an element is inserted it might invalidate elements.
BOOST_CONTAINER_FORCEINLINE void insert(std::initializer_list<value_type> il)
{ this->base_t::insert_equal(il.begin(), il.end()); }
{ this->tree_t::insert_equal(il.begin(), il.end()); }
//! <b>Requires</b>: Range [il.begin(), il.end()) must be ordered according to the predicate.
//!
@@ -1484,28 +1497,28 @@ class flat_multiset
//!
//! <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)
{ this->base_t::insert_equal(ordered_range, il.begin(), il.end()); }
{ this->tree_t::insert_equal(ordered_range, il.begin(), il.end()); }
#endif
//! @copydoc ::boost::container::flat_multimap::merge(flat_multimap<Key, T, C2, Allocator>&)
//! @copydoc ::boost::container::flat_multimap::merge(flat_multimap<Key, T, C2, AllocatorOrContainer>&)
template<class C2>
BOOST_CONTAINER_FORCEINLINE void merge(flat_multiset<Key, C2, Allocator>& source)
{ this->base_t::merge_equal(source.tree()); }
BOOST_CONTAINER_FORCEINLINE void merge(flat_multiset<Key, C2, AllocatorOrContainer>& source)
{ this->tree_t::merge_equal(source.tree()); }
//! @copydoc ::boost::container::flat_multiset::merge(flat_multiset<Key, C2, Allocator>&)
//! @copydoc ::boost::container::flat_multiset::merge(flat_multiset<Key, C2, AllocatorOrContainer>&)
template<class C2>
BOOST_CONTAINER_FORCEINLINE void merge(BOOST_RV_REF_BEG flat_multiset<Key, C2, Allocator> BOOST_RV_REF_END source)
{ return this->merge(static_cast<flat_multiset<Key, C2, Allocator>&>(source)); }
BOOST_CONTAINER_FORCEINLINE void merge(BOOST_RV_REF_BEG flat_multiset<Key, C2, AllocatorOrContainer> BOOST_RV_REF_END source)
{ return this->merge(static_cast<flat_multiset<Key, C2, AllocatorOrContainer>&>(source)); }
//! @copydoc ::boost::container::flat_multimap::merge(flat_map<Key, T, C2, Allocator>&)
//! @copydoc ::boost::container::flat_multimap::merge(flat_map<Key, T, C2, AllocatorOrContainer>&)
template<class C2>
BOOST_CONTAINER_FORCEINLINE void merge(flat_set<Key, C2, Allocator>& source)
{ this->base_t::merge_equal(source.tree()); }
BOOST_CONTAINER_FORCEINLINE void merge(flat_set<Key, C2, AllocatorOrContainer>& source)
{ this->tree_t::merge_equal(source.tree()); }
//! @copydoc ::boost::container::flat_multiset::merge(flat_set<Key, C2, Allocator>&)
//! @copydoc ::boost::container::flat_multiset::merge(flat_set<Key, C2, AllocatorOrContainer>&)
template<class C2>
BOOST_CONTAINER_FORCEINLINE void merge(BOOST_RV_REF_BEG flat_set<Key, C2, Allocator> BOOST_RV_REF_END source)
{ return this->merge(static_cast<flat_set<Key, C2, Allocator>&>(source)); }
BOOST_CONTAINER_FORCEINLINE void merge(BOOST_RV_REF_BEG flat_set<Key, C2, AllocatorOrContainer> BOOST_RV_REF_END source)
{ return this->merge(static_cast<flat_set<Key, C2, AllocatorOrContainer>&>(source)); }
#if defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
@@ -1624,7 +1637,7 @@ class flat_multiset
//!
//! <b>Throws</b>: If the comparison or the move constructor throws
BOOST_CONTAINER_FORCEINLINE void adopt_sequence(BOOST_RV_REF(sequence_type) seq)
{ this->base_t::adopt_sequence_equal(boost::move(seq)); }
{ this->tree_t::adopt_sequence_equal(boost::move(seq)); }
//! <b>Requires</b>: seq shall be ordered according to this->compare()
//!
@@ -1635,17 +1648,17 @@ class flat_multiset
//!
//! <b>Throws</b>: If the move assignment throws
BOOST_CONTAINER_FORCEINLINE void adopt_sequence(ordered_range_t, BOOST_RV_REF(sequence_type) seq)
{ this->base_t::adopt_sequence_equal(ordered_range_t(), boost::move(seq)); }
{ this->tree_t::adopt_sequence_equal(ordered_range_t(), boost::move(seq)); }
#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
private:
template <class KeyType>
BOOST_CONTAINER_FORCEINLINE iterator priv_insert(BOOST_FWD_REF(KeyType) x)
{ return this->base_t::insert_equal(::boost::forward<KeyType>(x)); }
{ return this->tree_t::insert_equal(::boost::forward<KeyType>(x)); }
template <class KeyType>
BOOST_CONTAINER_FORCEINLINE iterator priv_insert(const_iterator p, BOOST_FWD_REF(KeyType) x)
{ return this->base_t::insert_equal(p, ::boost::forward<KeyType>(x)); }
{ return this->tree_t::insert_equal(p, ::boost::forward<KeyType>(x)); }
#endif //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
};
@@ -1655,11 +1668,11 @@ class flat_multiset
//!has_trivial_destructor_after_move<> == true_type
//!specialization for optimizations
template <class Key, class Compare, class Allocator>
struct has_trivial_destructor_after_move<boost::container::flat_multiset<Key, Compare, Allocator> >
template <class Key, class Compare, class AllocatorOrContainer>
struct has_trivial_destructor_after_move<boost::container::flat_multiset<Key, Compare, AllocatorOrContainer> >
{
typedef typename ::boost::container::allocator_traits<Allocator>::pointer pointer;
static const bool value = ::boost::has_trivial_destructor_after_move<Allocator>::value &&
typedef typename ::boost::container::allocator_traits<AllocatorOrContainer>::pointer pointer;
static const bool value = ::boost::has_trivial_destructor_after_move<AllocatorOrContainer>::value &&
::boost::has_trivial_destructor_after_move<pointer>::value &&
::boost::has_trivial_destructor_after_move<Compare>::value;
};

View File

@@ -113,6 +113,8 @@ class static_vector
template<class U, std::size_t OtherCapacity>
friend class static_vector;
public:
typedef container_detail::static_storage_allocator<Value, Capacity> allocator_type;
#endif //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
public:
@@ -252,6 +254,19 @@ public:
: base_t(other)
{}
BOOST_CONTAINER_FORCEINLINE static_vector(static_vector const& other, const allocator_type &)
: base_t(other)
{}
BOOST_CONTAINER_FORCEINLINE static_vector(BOOST_RV_REF(static_vector) other, const allocator_type &)
BOOST_NOEXCEPT_IF(boost::container::container_detail::is_nothrow_move_constructible<value_type>::value)
: base_t(BOOST_MOVE_BASE(base_t, other))
{}
BOOST_CONTAINER_FORCEINLINE explicit static_vector(const allocator_type &)
: base_t()
{}
//! @pre <tt>other.size() <= capacity()</tt>.
//!
//! @brief Constructs a copy of other static_vector.

View File

@@ -315,6 +315,10 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "tree_test", "tree_test.vcpr
ProjectSection(ProjectDependencies) = postProject
EndProjectSection
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "flat_tree_test", "flat_tree_test.vcproj", "{DE1834C3-2609-FE38-4FA5-0BA0D3CD0796}"
ProjectSection(ProjectDependencies) = postProject
EndProjectSection
EndProject
Global
GlobalSection(SolutionConfiguration) = preSolution
Debug = Debug
@@ -637,6 +641,10 @@ Global
{5CE185C3-2609-4FA5-FE38-792BA0D3A606}.Debug.Build.0 = Debug|Win32
{5CE185C3-2609-4FA5-FE38-792BA0D3A606}.Release.ActiveCfg = Release|Win32
{5CE185C3-2609-4FA5-FE38-792BA0D3A606}.Release.Build.0 = Release|Win32
{DE1834C3-2609-FE38-4FA5-0BA0D3CD0796}.Debug.ActiveCfg = Debug|Win32
{DE1834C3-2609-FE38-4FA5-0BA0D3CD0796}.Debug.Build.0 = Debug|Win32
{DE1834C3-2609-FE38-4FA5-0BA0D3CD0796}.Release.ActiveCfg = Release|Win32
{DE1834C3-2609-FE38-4FA5-0BA0D3CD0796}.Release.Build.0 = Release|Win32
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
EndGlobalSection

View File

@@ -245,6 +245,12 @@
<File
RelativePath="..\..\..\..\boost\container\detail\function_detector.hpp">
</File>
<File
RelativePath="..\..\..\..\boost\container\detail\is_container.hpp">
</File>
<File
RelativePath="..\..\..\..\boost\container\detail\is_contiguous_container.hpp">
</File>
<File
RelativePath="..\..\..\..\boost\container\detail\is_sorted.hpp">
</File>

View File

@@ -12,6 +12,7 @@
#include <boost/container/flat_map.hpp>
#include <boost/container/allocator.hpp>
#include <boost/container/detail/flat_tree.hpp>
#include <boost/container/stable_vector.hpp>
#include "print_container.hpp"
#include "dummy_test_allocator.hpp"
@@ -336,9 +337,25 @@ bool flat_tree_extract_adopt_test()
}}}
template<class VoidAllocatorOrContainer, class ValueType, bool = boost::container::container_detail::is_container<VoidAllocatorOrContainer>::value>
struct RebindAllocatorOrContainer
{
typedef typename allocator_traits<VoidAllocatorOrContainer>
::template portable_rebind_alloc< std::pair<ValueType, ValueType> >::type type;
};
template<class VoidAllocator>
struct GetAllocatorMap
template<class SomeType, class ValueType, template <class> class Allocator>
struct RebindAllocatorOrContainer< boost::container::stable_vector<SomeType, Allocator<SomeType> >, ValueType, true>
{
typedef std::pair<ValueType, ValueType> type_t;
typedef typename allocator_traits< Allocator<SomeType> >
::template portable_rebind_alloc< type_t >::type allocator_t;
typedef typename boost::container::stable_vector<type_t, allocator_t> type;
};
template<class VoidAllocatorOrContainer>
struct GetMapContainer
{
template<class ValueType>
struct apply
@@ -346,15 +363,13 @@ struct GetAllocatorMap
typedef flat_map< ValueType
, ValueType
, std::less<ValueType>
, typename allocator_traits<VoidAllocator>
::template portable_rebind_alloc< std::pair<ValueType, ValueType> >::type
, typename RebindAllocatorOrContainer<VoidAllocatorOrContainer, ValueType>::type
> map_type;
typedef flat_multimap< ValueType
, ValueType
, std::less<ValueType>
, typename allocator_traits<VoidAllocator>
::template portable_rebind_alloc< std::pair<ValueType, ValueType> >::type
, typename RebindAllocatorOrContainer<VoidAllocatorOrContainer, ValueType>::type
> multimap_type;
};
};
@@ -402,18 +417,18 @@ struct get_real_stored_allocator<flat_multimap<Key, T, Compare, Allocator> >
}}} //namespace boost::container::test
template<class VoidAllocator>
template<class VoidAllocatorOrContainer>
int test_map_variants()
{
typedef typename GetAllocatorMap<VoidAllocator>::template apply<int>::map_type MyMap;
typedef typename GetAllocatorMap<VoidAllocator>::template apply<test::movable_int>::map_type MyMoveMap;
typedef typename GetAllocatorMap<VoidAllocator>::template apply<test::movable_and_copyable_int>::map_type MyCopyMoveMap;
typedef typename GetAllocatorMap<VoidAllocator>::template apply<test::copyable_int>::map_type MyCopyMap;
typedef typename GetMapContainer<VoidAllocatorOrContainer>::template apply<int>::map_type MyMap;
typedef typename GetMapContainer<VoidAllocatorOrContainer>::template apply<test::movable_int>::map_type MyMoveMap;
typedef typename GetMapContainer<VoidAllocatorOrContainer>::template apply<test::movable_and_copyable_int>::map_type MyCopyMoveMap;
typedef typename GetMapContainer<VoidAllocatorOrContainer>::template apply<test::copyable_int>::map_type MyCopyMap;
typedef typename GetAllocatorMap<VoidAllocator>::template apply<int>::multimap_type MyMultiMap;
typedef typename GetAllocatorMap<VoidAllocator>::template apply<test::movable_int>::multimap_type MyMoveMultiMap;
typedef typename GetAllocatorMap<VoidAllocator>::template apply<test::movable_and_copyable_int>::multimap_type MyCopyMoveMultiMap;
typedef typename GetAllocatorMap<VoidAllocator>::template apply<test::copyable_int>::multimap_type MyCopyMultiMap;
typedef typename GetMapContainer<VoidAllocatorOrContainer>::template apply<int>::multimap_type MyMultiMap;
typedef typename GetMapContainer<VoidAllocatorOrContainer>::template apply<test::movable_int>::multimap_type MyMoveMultiMap;
typedef typename GetMapContainer<VoidAllocatorOrContainer>::template apply<test::movable_and_copyable_int>::multimap_type MyCopyMoveMultiMap;
typedef typename GetMapContainer<VoidAllocatorOrContainer>::template apply<test::copyable_int>::multimap_type MyCopyMultiMap;
typedef std::map<int, int> MyStdMap;
typedef std::multimap<int, int> MyStdMultiMap;

View File

@@ -57,25 +57,6 @@ template class flat_multiset
, allocator<test::movable_and_copyable_int>
>;
namespace container_detail {
//Instantiate base class as previous instantiations don't instantiate inherited members
template class flat_tree
< test::movable_and_copyable_int
, identity<test::movable_and_copyable_int>
, std::less<test::movable_and_copyable_int>
, test::simple_allocator<test::movable_and_copyable_int>
>;
template class flat_tree
< test::movable_and_copyable_int
, identity<test::movable_and_copyable_int>
, std::less<test::movable_and_copyable_int>
, allocator<test::movable_and_copyable_int>
>;
} //container_detail {
//As flat container iterators are typedefs for vector::[const_]iterator,
//no need to explicit instantiate them

124
test/flat_tree_test.cpp Normal file
View File

@@ -0,0 +1,124 @@
//////////////////////////////////////////////////////////////////////////////
//
// (C) Copyright Ion Gaztanaga 2004-2013. Distributed under the Boost
// Software License, Version 1.0. (See accompanying file
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
// See http://www.boost.org/libs/container for documentation.
//
//////////////////////////////////////////////////////////////////////////////
#include <boost/container/detail/flat_tree.hpp>
#include <boost/container/small_vector.hpp>
#include <boost/container/stable_vector.hpp>
#include <boost/container/static_vector.hpp>
#include "movable_int.hpp"
#include "dummy_test_allocator.hpp"
using namespace boost::container;
typedef boost::container::container_detail::pair<test::movable_and_copyable_int, test::movable_and_copyable_int> pair_t;
namespace boost {
namespace container {
//Explicit instantiation to detect compilation errors
namespace container_detail {
template class flat_tree
< pair_t
, select1st<test::movable_and_copyable_int>
, std::less<test::movable_and_copyable_int>
, test::simple_allocator<pair_t>
>;
template class flat_tree
< pair_t
, select1st<test::movable_and_copyable_int>
, std::less<test::movable_and_copyable_int>
, std::allocator<pair_t>
>;
template class flat_tree
< pair_t
, select1st<test::movable_and_copyable_int>
, std::less<test::movable_and_copyable_int>
, small_vector<pair_t, 10>
>;
template class flat_tree
< pair_t
, select1st<test::movable_and_copyable_int>
, std::less<test::movable_and_copyable_int>
, stable_vector<pair_t>
>;
template class flat_tree
< test::movable_and_copyable_int
, identity<test::movable_and_copyable_int>
, std::less<test::movable_and_copyable_int>
, test::simple_allocator<test::movable_and_copyable_int>
>;
template class flat_tree
< test::movable_and_copyable_int
, identity<test::movable_and_copyable_int>
, std::less<test::movable_and_copyable_int>
, std::allocator<test::movable_and_copyable_int>
>;
template class flat_tree
< test::movable_and_copyable_int
, identity<test::movable_and_copyable_int>
, std::less<test::movable_and_copyable_int>
, small_vector<test::movable_and_copyable_int, 10>
>;
template class flat_tree
< test::movable_and_copyable_int
, identity<test::movable_and_copyable_int>
, std::less<test::movable_and_copyable_int>
, stable_vector<test::movable_and_copyable_int>
>;
template class flat_tree
< test::movable_and_copyable_int
, identity<test::movable_and_copyable_int>
, std::less<test::movable_and_copyable_int>
, static_vector<test::movable_and_copyable_int, 10>
>;
} //container_detail {
}} //boost::container
#if (__cplusplus >= 201402L)
#include <vector>
namespace boost{
namespace container{
namespace container_detail{
template class flat_tree
< test::movable_and_copyable_int
, identity<test::movable_and_copyable_int>
, std::less<test::movable_and_copyable_int>
, std::vector<test::movable_and_copyable_int>
>;
template class flat_tree
< pair_t
, select1st<test::movable_and_copyable_int>
, std::less<test::movable_and_copyable_int>
, std::vector<pair_t>
>;
} //container_detail {
}} //boost::container
#endif
int main ()
{
return 0;
}

View File

@@ -886,14 +886,14 @@ int map_test()
for(int i = 0; i < MaxElem; ++i){
stdmultimap.insert(StdPairType(MaxElem/2+i, MaxElem-i));
}
boostmultimap.merge(boost::move(boostmultimap2));
boostmultimap.merge(boostmultimap2);
if(!CheckEqualPairContainers(boostmultimap, stdmultimap)) return 1;
for(int i = 0; i < MaxElem; ++i){
stdmultimap.insert(StdPairType(MaxElem*2/2+i, MaxElem*2+i));
}
boostmultimap.merge(boost::move(boostmap2));
boostmultimap.merge(boostmap2);
if(!CheckEqualPairContainers(boostmultimap, stdmultimap)) return 1;
}

View File

@@ -49,7 +49,6 @@ template class tree
, tree_assoc_defaults
>;
//Instantiate base class as previous instantiations don't instantiate inherited members
template class tree
< test::movable_and_copyable_int
, identity<test::movable_and_copyable_int>