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 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). ]] complexity guarantees of insert and erase (linear as opposed to constant). ]]
[*Boost.Container] `flat_[multi]map/set` containers are ordered-vector based associative containers [*Boost.Container] `flat_[multi]map/set` containers are ordered, vector-like container based, associative
based on Austern's and Alexandrescu's guidelines. These ordered vector containers have also containers following 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 benefited with the addition of `move semantics` to C++11, speeding up insertion and
and erasure times considerably. Flat associative containers have the following erasure times considerably. Flat associative containers have the following attributes:
attributes:
* Faster lookup than standard associative containers * Faster lookup than standard associative containers
* Much faster iteration 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 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] [section:release_notes_boost_1_65_00 Boost 1.65 Release]
* Implemented `extract_sequence`, `adopt_sequence` functions for flat_[multi]map/set associative containers. * 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] [endsect]
https://svn.boost.org/trac/boost/ticket/12577#comment:1
[section:release_notes_boost_1_62_00 Boost 1.62 Release] [section:release_notes_boost_1_62_00 Boost 1.62 Release]
* Fixed bugs: * Fixed bugs:

View File

@@ -163,7 +163,7 @@ struct insert_copy_proxy
void copy_n_and_update(Allocator &, Iterator p, size_type n) const void copy_n_and_update(Allocator &, Iterator p, size_type n) const
{ {
BOOST_ASSERT(n == 1); (void)n; BOOST_ASSERT(n == 1); (void)n;
*p =v_; *p = v_;
} }
const value_type &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 class value_destructor
{ {
typedef boost::container::allocator_traits<Allocator> AllocTraits; typedef boost::container::allocator_traits<Allocator> AllocTraits;
public: public:
typedef typename Allocator::value_type value_type; typedef Value value_type;
value_destructor(Allocator &a, value_type &rv) value_destructor(Allocator &a, value_type &rv)
: rv_(rv), a_(a) : rv_(rv), a_(a)
{} {}

View File

@@ -37,10 +37,10 @@
#include <boost/container/detail/is_sorted.hpp> #include <boost/container/detail/is_sorted.hpp>
#include <boost/container/detail/type_traits.hpp> #include <boost/container/detail/type_traits.hpp>
#include <boost/container/detail/iterators.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/intrusive/detail/minimal_pair_header.hpp> //pair
#include <boost/move/make_unique.hpp> #include <boost/move/make_unique.hpp>
@@ -52,11 +52,152 @@
#include <boost/move/detail/fwd_macros.hpp> #include <boost/move/detail/fwd_macros.hpp>
#endif #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 boost {
namespace container { namespace container {
namespace container_detail { 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> template<class Compare, class Value, class KeyOfValue>
class flat_tree_value_compare class flat_tree_value_compare
: private Compare : private Compare
@@ -85,37 +226,43 @@ class flat_tree_value_compare
Compare &get_comp() Compare &get_comp()
{ return *this; } { return *this; }
}; };
/*
template<class Pointer> template<class Pointer>
struct get_flat_tree_iterators 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:: typedef typename boost::container::container_detail::
vec_iterator<Pointer, false> iterator; vec_iterator<Pointer, false> iterator;
typedef typename boost::container::container_detail:: typedef typename boost::container::container_detail::
vec_iterator<Pointer, true > const_iterator; 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<iterator> reverse_iterator;
typedef boost::container::reverse_iterator<const_iterator> const_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, template <class Value, class KeyOfValue,
class Compare, class Allocator> class Compare, class AllocatorOrContainer>
class flat_tree class flat_tree
{ {
public: 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: private:
typedef Allocator allocator_t; typedef typename container_type::allocator_type allocator_t;
typedef allocator_traits<Allocator> allocator_traits_type; typedef allocator_traits<allocator_t> allocator_traits_type;
public: public:
typedef flat_tree_value_compare<Compare, Value, KeyOfValue> value_compare; 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)) : 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) : 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) : 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); this->m_seq.swap(d.m_seq);
} }
sequence_type m_seq; container_type m_seq;
}; };
Data m_data; Data m_data;
@@ -189,26 +336,36 @@ class flat_tree
public: public:
typedef typename sequence_type::value_type value_type; typedef typename container_type::value_type value_type;
typedef typename sequence_type::pointer pointer; typedef typename container_type::pointer pointer;
typedef typename sequence_type::const_pointer const_pointer; typedef typename container_type::const_pointer const_pointer;
typedef typename sequence_type::reference reference; typedef typename container_type::reference reference;
typedef typename sequence_type::const_reference const_reference; typedef typename container_type::const_reference const_reference;
typedef typename KeyOfValue::type key_type; typedef typename KeyOfValue::type key_type;
typedef Compare key_compare; typedef Compare key_compare;
typedef typename sequence_type::allocator_type allocator_type; typedef typename container_type::allocator_type allocator_type;
typedef typename sequence_type::size_type size_type; typedef typename container_type::size_type size_type;
typedef typename sequence_type::difference_type difference_type; typedef typename container_type::difference_type difference_type;
typedef typename sequence_type::iterator iterator; typedef typename container_type::iterator iterator;
typedef typename sequence_type::const_iterator const_iterator; typedef typename container_type::const_iterator const_iterator;
typedef typename sequence_type::reverse_iterator reverse_iterator; typedef typename container_type::reverse_iterator reverse_iterator;
typedef typename sequence_type::const_reverse_iterator const_reverse_iterator; typedef typename container_type::const_reverse_iterator const_reverse_iterator;
//!Standard extension //!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: private:
typedef allocator_traits<stored_allocator_type> stored_allocator_traits; 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: public:
BOOST_CONTAINER_FORCEINLINE flat_tree() BOOST_CONTAINER_FORCEINLINE flat_tree()
@@ -357,6 +514,11 @@ class flat_tree
BOOST_CONTAINER_FORCEINLINE key_compare &priv_key_comp() BOOST_CONTAINER_FORCEINLINE key_compare &priv_key_comp()
{ return this->priv_value_comp().get_comp(); } { return this->priv_value_comp().get_comp(); }
struct insert_commit_data
{
const_iterator position;
};
public: public:
// accessors: // accessors:
BOOST_CONTAINER_FORCEINLINE Compare key_comp() const BOOST_CONTAINER_FORCEINLINE Compare key_comp() const
@@ -368,11 +530,15 @@ class flat_tree
BOOST_CONTAINER_FORCEINLINE allocator_type get_allocator() const BOOST_CONTAINER_FORCEINLINE allocator_type get_allocator() const
{ return this->m_data.m_seq.get_allocator(); } { return this->m_data.m_seq.get_allocator(); }
BOOST_CONTAINER_FORCEINLINE const stored_allocator_type &get_stored_allocator() const BOOST_CONTAINER_FORCEINLINE get_stored_allocator_const_return_t get_stored_allocator() const
{ return this->m_data.m_seq.get_stored_allocator(); } {
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() BOOST_CONTAINER_FORCEINLINE get_stored_allocator_noconst_return_t get_stored_allocator()
{ return this->m_data.m_seq.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() BOOST_CONTAINER_FORCEINLINE iterator begin()
{ return this->m_data.m_seq.begin(); } { return this->m_data.m_seq.begin(); }
@@ -432,7 +598,8 @@ class flat_tree
insert_commit_data data; insert_commit_data data;
ret.second = this->priv_insert_unique_prepare(KeyOfValue()(val), data); ret.second = this->priv_insert_unique_prepare(KeyOfValue()(val), data);
ret.first = ret.second ? this->priv_insert_commit(data, val) 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; return ret;
} }
@@ -442,7 +609,8 @@ class flat_tree
insert_commit_data data; insert_commit_data data;
ret.second = this->priv_insert_unique_prepare(KeyOfValue()(val), data); ret.second = this->priv_insert_unique_prepare(KeyOfValue()(val), data);
ret.first = ret.second ? this->priv_insert_commit(data, boost::move(val)) 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; return ret;
} }
@@ -466,7 +634,8 @@ class flat_tree
insert_commit_data data; insert_commit_data data;
return this->priv_insert_unique_prepare(hint, KeyOfValue()(val), data) return this->priv_insert_unique_prepare(hint, KeyOfValue()(val), data)
? this->priv_insert_commit(data, val) ? 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) iterator insert_unique(const_iterator hint, BOOST_RV_REF(value_type) val)
@@ -475,7 +644,8 @@ class flat_tree
insert_commit_data data; insert_commit_data data;
return this->priv_insert_unique_prepare(hint, KeyOfValue()(val), data) return this->priv_insert_unique_prepare(hint, KeyOfValue()(val), data)
? this->priv_insert_commit(data, boost::move(val)) ? 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) iterator insert_equal(const_iterator hint, const value_type& val)
@@ -563,7 +733,11 @@ class flat_tree
>::type * = 0 >::type * = 0
#endif #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> template <class InIt>
void insert_unique(ordered_unique_range_t, InIt first, InIt last void insert_unique(ordered_unique_range_t, InIt first, InIt last
@@ -592,7 +766,11 @@ class flat_tree
>::type * = 0 >::type * = 0
#endif #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) #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; typename aligned_storage<sizeof(value_type), alignment_of<value_type>::value>::type v;
value_type &val = *static_cast<value_type *>(static_cast<void *>(&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)... ); 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)); return this->insert_unique(::boost::move(val));
} }
@@ -613,9 +791,9 @@ class flat_tree
//hint checked in insert_unique //hint checked in insert_unique
typename aligned_storage<sizeof(value_type), alignment_of<value_type>::value>::type v; typename aligned_storage<sizeof(value_type), alignment_of<value_type>::value>::type v;
value_type &val = *static_cast<value_type *>(static_cast<void *>(&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)... ); 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)); 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; typename aligned_storage<sizeof(value_type), alignment_of<value_type>::value>::type v;
value_type &val = *static_cast<value_type *>(static_cast<void *>(&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)... ); 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)); return this->insert_equal(::boost::move(val));
} }
@@ -636,9 +814,9 @@ class flat_tree
//hint checked in insert_equal //hint checked in insert_equal
typename aligned_storage<sizeof(value_type), alignment_of<value_type>::value>::type v; typename aligned_storage<sizeof(value_type), alignment_of<value_type>::value>::type v;
value_type &val = *static_cast<value_type *>(static_cast<void *>(&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)... ); 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)); 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;\ typename aligned_storage<sizeof(value_type), alignment_of<value_type>::value>::type v;\
value_type &val = *static_cast<value_type *>(static_cast<void *>(&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);\ 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));\ 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;\ typename aligned_storage<sizeof(value_type), alignment_of<value_type>::value>::type v;\
value_type &val = *static_cast<value_type *>(static_cast<void *>(&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);\ 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));\ 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;\ typename aligned_storage<sizeof(value_type), alignment_of<value_type>::value>::type v;\
value_type &val = *static_cast<value_type *>(static_cast<void *>(&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);\ 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));\ 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;\ typename aligned_storage <sizeof(value_type), alignment_of<value_type>::value>::type v;\
value_type &val = *static_cast<value_type *>(static_cast<void *>(&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);\ 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));\ return this->insert_equal(hint, ::boost::move(val));\
}\ }\
template <class KeyType BOOST_MOVE_I##N BOOST_MOVE_CLASS##N>\ 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(); } { this->m_data.m_seq.shrink_to_fit(); }
BOOST_CONTAINER_FORCEINLINE iterator nth(size_type n) BOOST_NOEXCEPT_OR_NOTHROW 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 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 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 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: // set operations:
iterator find(const key_type& k) iterator find(const key_type& k)
@@ -832,33 +1026,41 @@ class flat_tree
} }
template<class C2> 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()) this->insert( boost::make_move_iterator(source.begin())
, boost::make_move_iterator(source.end())); , boost::make_move_iterator(source.end()));
} }
template<class C2> 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()) this->insert( boost::make_move_iterator(source.begin())
, boost::make_move_iterator(source.end())); , 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 const bool value = boost::container::container_detail::
( boost::make_move_iterator(source.begin()) has_member_function_callable_with_merge_unique<container_type, iterator, iterator, value_compare>::value;
, boost::make_move_iterator(source.end()) (flat_tree_merge_unique)
, static_cast<const value_compare &>(this->m_data)); ( 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 const bool value = boost::container::container_detail::
( boost::make_move_iterator(source.begin()) has_member_function_callable_with_merge<container_type, iterator, iterator, value_compare>::value;
, boost::make_move_iterator(source.end()) (flat_tree_merge_equal)
, static_cast<const value_compare &>(this->m_data)); ( 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) 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) BOOST_CONTAINER_FORCEINLINE void reserve(size_type cnt)
{ this->m_data.m_seq.reserve(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); 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; 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; container_type &tseq = m_data.m_seq;
if (is_contiguous_container<container_type>::value){
boost::movelib::adaptive_sort boost::movelib::adaptive_sort
( boost::movelib::iterator_to_raw_pointer(seq.begin()) ( boost::movelib::iterator_to_raw_pointer(seq.begin())
, boost::movelib::iterator_to_raw_pointer(seq.end()) , boost::movelib::iterator_to_raw_pointer(seq.end())
, this->priv_value_comp() , this->priv_value_comp()
, boost::movelib::iterator_to_raw_pointer(tseq.begin() + tseq.size()) , boost::movelib::iterator_to_raw_pointer(tseq.begin() + tseq.size())
, tseq.capacity() - tseq.size()); , tseq.capacity() - tseq.size());
}
else{
boost::movelib::adaptive_sort
(seq.begin(), seq.end(), this->priv_value_comp());
}
tseq = boost::move(seq); 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())); container_type &tseq = m_data.m_seq;
sequence_type &tseq = m_data.m_seq; if (is_contiguous_container<container_type>::value){
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::adaptive_sort
( boost::movelib::iterator_to_raw_pointer(seq.begin()) ( boost::movelib::iterator_to_raw_pointer(seq.begin())
, boost::movelib::iterator_to_raw_pointer(seq.end()) , boost::movelib::iterator_to_raw_pointer(seq.end())
, this->priv_value_comp() , this->priv_value_comp()
, boost::movelib::iterator_to_raw_pointer(tseq.begin() + tseq.size()) , boost::movelib::iterator_to_raw_pointer(tseq.begin() + tseq.size())
, tseq.capacity() - 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.erase( boost::movelib::unique
(seq.begin(), seq.end(), boost::movelib::negate<value_compare>(this->m_data.get_comp())) (seq.begin(), seq.end(), boost::movelib::negate<value_compare>(this->m_data.get_comp()))
, seq.cend()); , seq.cend());
tseq = boost::move(seq); 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())); 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); tseq = boost::move(seq);
} }
@@ -993,11 +1207,6 @@ class flat_tree
return (this->begin() <= pos) && (pos <= this->end()); return (this->begin() <= pos) && (pos <= this->end());
} }
struct insert_commit_data
{
const_iterator position;
};
// insert/erase // insert/erase
void priv_insert_equal_prepare void priv_insert_equal_prepare
(const_iterator pos, const value_type& val, insert_commit_data &data) (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 //!has_trivial_destructor_after_move<> == true_type
//!specialization for optimizations //!specialization for optimizations
template <class T, class KeyOfValue, template <class T, class KeyOfValue,
class Compare, class Allocator> class Compare, class AllocatorOrContainer>
struct has_trivial_destructor_after_move<boost::container::container_detail::flat_tree<T, KeyOfValue, Compare, Allocator> > 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; typedef typename boost::container::container_detail::select_container_type<T, AllocatorOrContainer>::type container_type;
static const bool value = ::boost::has_trivial_destructor_after_move<Allocator>::value && 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; ::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 #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; class flat_multimap;
namespace container_detail{ 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 //! 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 //! 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 //! A flat_map satisfies all of the requirements of a container, a reversible
//! container and of an associative container. A flat_map also provides //! container and an associative container. A flat_map also provides
//! most operations described for unique keys. For a //! 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> //! 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>). //! (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 //! Using vector-like sequence containers means that inserting a new element into a flat_map might invalidate
//! (e.g. <i>allocator< std::pair<Key, T> ></i>). //! 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
//! flat_map is similar to std::map but it's implemented like an ordered vector. //! iterators and references pointing to elements that come after (their keys are bigger) the erased element.
//! 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.
//! //!
//! This container provides random-access iterators. //! This container provides random-access iterators.
//! //!
//! \tparam Key is the key_type of the map //! \tparam Key is the key_type of the map
//! \tparam Value is the <code>mapped_type</code> //! \tparam Value is the <code>mapped_type</code>
//! \tparam Compare is the ordering function for Keys (e.g. <i>std::less<Key></i>). //! \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 //! \tparam AllocatorOrContainer is either:
//! (e.g. <i>allocator< std::pair<Key, T> > </i>). //! - 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 #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 #else
template <class Key, class T, class Compare, class Allocator> template <class Key, class T, class Compare, class AllocatorOrContainer>
#endif #endif
class flat_map class flat_map
{ {
@@ -118,14 +118,14 @@ class flat_map
std::pair<Key, T>, std::pair<Key, T>,
container_detail::select1st<Key>, container_detail::select1st<Key>,
Compare, Compare,
Allocator> tree_t; AllocatorOrContainer> tree_t;
//This is the real tree stored here. It's based on a movable pair //This is the real tree stored here. It's based on a movable pair
typedef container_detail::flat_tree< typedef container_detail::flat_tree<
container_detail::pair<Key, T>, container_detail::pair<Key, T>,
container_detail::select1st<Key>, container_detail::select1st<Key>,
Compare, 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; <container_detail::pair<Key, T> >::type> impl_tree_t;
impl_tree_t m_flat_tree; // flat tree representing flat_map 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::const_iterator impl_const_iterator;
typedef typename impl_tree_t::iterator impl_iterator; typedef typename impl_tree_t::iterator impl_iterator;
typedef typename impl_tree_t::allocator_type impl_allocator_type; 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 typedef container_detail::flat_tree_value_compare
< Compare < Compare
, container_detail::select1st<Key> , container_detail::select1st<Key>
, std::pair<Key, T> > value_compare_impl; , std::pair<Key, T> > value_compare_t;
typedef typename container_detail::get_flat_tree_iterators typedef typename tree_t::iterator iterator_t;
<typename allocator_traits<Allocator>::pointer>::iterator iterator_impl; typedef typename tree_t::const_iterator const_iterator_t;
typedef typename container_detail::get_flat_tree_iterators typedef typename tree_t::reverse_iterator reverse_iterator_t;
<typename allocator_traits<Allocator>::pointer>::const_iterator const_iterator_impl; typedef typename tree_t::const_reverse_iterator const_reverse_iterator_t;
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;
public: public:
typedef typename impl_tree_t::stored_allocator_type impl_stored_allocator_type; typedef typename impl_tree_t::stored_allocator_type impl_stored_allocator_type;
@@ -168,27 +168,28 @@ class flat_map
////////////////////////////////////////////// //////////////////////////////////////////////
typedef Key key_type; typedef Key key_type;
typedef T mapped_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 Compare key_compare;
typedef BOOST_CONTAINER_IMPDEF(iterator_impl) iterator; typedef std::pair<Key, T> value_type;
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 typename BOOST_CONTAINER_IMPDEF(tree_t::sequence_type) sequence_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> typedef typename sequence_type::iterator iterator;
BOOST_STATIC_ASSERT((container_detail::is_same<std::pair<Key, T>, typename Allocator::value_type>::value)); 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>Effects</b>: Default constructs an empty flat_map.
//! //!
//! <b>Complexity</b>: Constant. //! <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) container_detail::is_nothrow_default_constructible<Compare>::value)
: m_flat_tree() : m_flat_tree()
{} {}
@@ -309,7 +310,7 @@ class flat_map
template <class InputIterator> template <class InputIterator>
BOOST_CONTAINER_FORCEINLINE BOOST_CONTAINER_FORCEINLINE
flat_map(ordered_unique_range_t, InputIterator first, InputIterator last, const Compare& comp, const allocator_type& a) 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) #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 //! <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. //! the predicate and otherwise N logN, where N is last - first.
BOOST_CONTAINER_FORCEINLINE flat_map(std::initializer_list<value_type> il) 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 //! <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 //! <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. //! 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) 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 //! <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 //! <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. //! 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) 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 //! <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 //! <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. //! 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) 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 //! <b>Effects</b>: Constructs an empty flat_map using and
@@ -360,7 +373,9 @@ class flat_map
//! //!
//! <b>Note</b>: Non-standard extension. //! <b>Note</b>: Non-standard extension.
BOOST_CONTAINER_FORCEINLINE flat_map(ordered_unique_range_t, std::initializer_list<value_type> il) 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 //! <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. //! <b>Note</b>: Non-standard extension.
BOOST_CONTAINER_FORCEINLINE flat_map(ordered_unique_range_t, std::initializer_list<value_type> il, const Compare& comp) 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 //! <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. //! <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) 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 #endif
@@ -414,7 +436,7 @@ class flat_map
//! //!
//! <b>Complexity</b>: Linear in x.size(). //! <b>Complexity</b>: Linear in x.size().
BOOST_CONTAINER_FORCEINLINE flat_map(const flat_map& x, const allocator_type &a) 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. //! <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. //! <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) 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. //! <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. //! <b>Note</b>: If an element is inserted it might invalidate elements.
BOOST_CONTAINER_FORCEINLINE void insert(std::initializer_list<value_type> il) BOOST_CONTAINER_FORCEINLINE void insert(std::initializer_list<value_type> il)
{ 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 //! <b>Requires</b>: [il.begin(), il.end()) must be ordered according to the predicate and must be
//! unique values. //! unique values.
@@ -1130,7 +1155,11 @@ class flat_map
//! //!
//! <b>Note</b>: Non-standard extension. //! <b>Note</b>: Non-standard extension.
BOOST_CONTAINER_FORCEINLINE void insert(ordered_unique_range_t, std::initializer_list<value_type> il) BOOST_CONTAINER_FORCEINLINE void insert(ordered_unique_range_t, std::initializer_list<value_type> il)
{ 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 #endif
//! <b>Requires</b>: this->get_allocator() == source.get_allocator(). //! <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()) //! <b>Complexity</b>: N log(a.size() + N) (N has the value source.size())
template<class C2> 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()); } { 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> template<class C2>
BOOST_CONTAINER_FORCEINLINE void merge(BOOST_RV_REF_BEG flat_map<Key, T, C2, Allocator> BOOST_RV_REF_END 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, Allocator>&>(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> 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()); } { 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> template<class C2>
BOOST_CONTAINER_FORCEINLINE void merge(BOOST_RV_REF_BEG flat_multimap<Key, T, C2, Allocator> BOOST_RV_REF_END 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, Allocator>&>(source)); } { return this->merge(static_cast<flat_multimap<Key, T, C2, AllocatorOrContainer>&>(source)); }
//! <b>Effects</b>: Erases the element pointed to by p. //! <b>Effects</b>: Erases the element pointed to by p.
//! //!
@@ -1417,11 +1446,11 @@ class flat_map
//!has_trivial_destructor_after_move<> == true_type //!has_trivial_destructor_after_move<> == true_type
//!specialization for optimizations //!specialization for optimizations
template <class Key, class T, class Compare, class Allocator> template <class Key, class T, class Compare, class AllocatorOrContainer>
struct has_trivial_destructor_after_move<boost::container::flat_map<Key, T, Compare, Allocator> > struct has_trivial_destructor_after_move<boost::container::flat_map<Key, T, Compare, AllocatorOrContainer> >
{ {
typedef typename ::boost::container::allocator_traits<Allocator>::pointer pointer; typedef typename ::boost::container::allocator_traits<AllocatorOrContainer>::pointer pointer;
static const bool value = ::boost::has_trivial_destructor_after_move<Allocator>::value && 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<pointer>::value &&
::boost::has_trivial_destructor_after_move<Compare>::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 //! 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 //! (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 //! fast retrieval of values of another type T based on the keys.
//! class supports random-access iterators.
//! //!
//! A flat_multimap satisfies all of the requirements of a container and of a reversible //! A flat_multimap satisfies all of the requirements of a container and of a reversible
//! container and of an associative container. For a //! 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> //! 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>). //! (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 //! Using vector-like sequence containers means that inserting a new element into a flat_multimap might invalidate
//! (e.g. <i>allocator< std::pair<Key, T> ></i>). //! 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
//! flat_multimap is similar to std::multimap but it's implemented like an ordered vector. //! iterators and references pointing to elements that come after (their keys are bigger) the erased element.
//! 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.
//! //!
//! This container provides random-access iterators. //! This container provides random-access iterators.
//! //!
//! \tparam Key is the key_type of the map //! \tparam Key is the key_type of the map
//! \tparam Value is the <code>mapped_type</code> //! \tparam Value is the <code>mapped_type</code>
//! \tparam Compare is the ordering function for Keys (e.g. <i>std::less<Key></i>). //! \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 //! \tparam AllocatorOrContainer is either:
//! (e.g. <i>allocator< std::pair<Key, T> > </i>). //! - 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 #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 #else
template <class Key, class T, class Compare, class Allocator> template <class Key, class T, class Compare, class AllocatorOrContainer>
#endif #endif
class flat_multimap class flat_multimap
{ {
@@ -1473,13 +1501,13 @@ class flat_multimap
std::pair<Key, T>, std::pair<Key, T>,
container_detail::select1st<Key>, container_detail::select1st<Key>,
Compare, Compare,
Allocator> tree_t; AllocatorOrContainer> tree_t;
//This is the real tree stored here. It's based on a movable pair //This is the real tree stored here. It's based on a movable pair
typedef container_detail::flat_tree< typedef container_detail::flat_tree<
container_detail::pair<Key, T>, container_detail::pair<Key, T>,
container_detail::select1st<Key>, container_detail::select1st<Key>,
Compare, 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; <container_detail::pair<Key, T> >::type> impl_tree_t;
impl_tree_t m_flat_tree; // flat tree representing flat_map impl_tree_t m_flat_tree; // flat tree representing flat_map
@@ -1487,18 +1515,19 @@ class flat_multimap
typedef typename impl_tree_t::const_iterator impl_const_iterator; typedef typename impl_tree_t::const_iterator impl_const_iterator;
typedef typename impl_tree_t::iterator impl_iterator; typedef typename impl_tree_t::iterator impl_iterator;
typedef typename impl_tree_t::allocator_type impl_allocator_type; 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 typedef container_detail::flat_tree_value_compare
< Compare < Compare
, container_detail::select1st<Key> , container_detail::select1st<Key>
, std::pair<Key, T> > value_compare_impl; , std::pair<Key, T> > value_compare_t;
typedef typename container_detail::get_flat_tree_iterators typedef typename tree_t::iterator iterator_t;
<typename allocator_traits<Allocator>::pointer>::iterator iterator_impl; typedef typename tree_t::const_iterator const_iterator_t;
typedef typename container_detail::get_flat_tree_iterators typedef typename tree_t::reverse_iterator reverse_iterator_t;
<typename allocator_traits<Allocator>::pointer>::const_iterator const_iterator_impl; typedef typename tree_t::const_reverse_iterator const_reverse_iterator_t;
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;
public: public:
typedef typename impl_tree_t::stored_allocator_type impl_stored_allocator_type; 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::sequence_type impl_sequence_type;
@@ -1521,27 +1550,28 @@ class flat_multimap
////////////////////////////////////////////// //////////////////////////////////////////////
typedef Key key_type; typedef Key key_type;
typedef T mapped_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 Compare key_compare;
typedef BOOST_CONTAINER_IMPDEF(iterator_impl) iterator; typedef std::pair<Key, T> value_type;
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 typename BOOST_CONTAINER_IMPDEF(tree_t::sequence_type) sequence_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> typedef typename sequence_type::iterator iterator;
BOOST_STATIC_ASSERT((container_detail::is_same<std::pair<Key, T>, typename Allocator::value_type>::value)); 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. //! <b>Complexity</b>: Constant.
BOOST_CONTAINER_FORCEINLINE flat_multimap() 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) container_detail::is_nothrow_default_constructible<Compare>::value)
: m_flat_tree() : m_flat_tree()
{} {}
@@ -1679,7 +1709,9 @@ class flat_multimap
//! the predicate and otherwise N logN, where N is last - first. //! the predicate and otherwise N logN, where N is last - first.
BOOST_CONTAINER_FORCEINLINE BOOST_CONTAINER_FORCEINLINE
flat_multimap(std::initializer_list<value_type> il) 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 //! <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. //! the predicate and otherwise N logN, where N is last - first.
BOOST_CONTAINER_FORCEINLINE BOOST_CONTAINER_FORCEINLINE
flat_multimap(std::initializer_list<value_type> il, const allocator_type& a) 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 //! <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. //! the predicate and otherwise N logN, where N is last - first.
BOOST_CONTAINER_FORCEINLINE BOOST_CONTAINER_FORCEINLINE
flat_multimap(std::initializer_list<value_type> il, const Compare& comp) 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 //! <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. //! the predicate and otherwise N logN, where N is last - first.
BOOST_CONTAINER_FORCEINLINE BOOST_CONTAINER_FORCEINLINE
flat_multimap(std::initializer_list<value_type> il, const Compare& comp, const allocator_type& a) 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 //! <b>Effects</b>: Constructs an empty flat_multimap and
@@ -1723,7 +1763,9 @@ class flat_multimap
//! <b>Note</b>: Non-standard extension. //! <b>Note</b>: Non-standard extension.
BOOST_CONTAINER_FORCEINLINE BOOST_CONTAINER_FORCEINLINE
flat_multimap(ordered_range_t, std::initializer_list<value_type> il) 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 //! <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. //! <b>Note</b>: Non-standard extension.
BOOST_CONTAINER_FORCEINLINE BOOST_CONTAINER_FORCEINLINE
flat_multimap(ordered_range_t, std::initializer_list<value_type> il, const Compare& comp) 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 //! <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. //! <b>Note</b>: Non-standard extension.
BOOST_CONTAINER_FORCEINLINE BOOST_CONTAINER_FORCEINLINE
flat_multimap(ordered_range_t, std::initializer_list<value_type> il, const Compare& comp, const allocator_type& a) 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 #endif
@@ -2235,7 +2282,10 @@ class flat_multimap
//! //!
//! <b>Note</b>: If an element is inserted it might invalidate elements. //! <b>Note</b>: If an element is inserted it might invalidate elements.
BOOST_CONTAINER_FORCEINLINE void insert(std::initializer_list<value_type> il) BOOST_CONTAINER_FORCEINLINE void insert(std::initializer_list<value_type> il)
{ 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. //! <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. //! <b>Note</b>: Non-standard extension.
BOOST_CONTAINER_FORCEINLINE void insert(ordered_range_t, std::initializer_list<value_type> il) BOOST_CONTAINER_FORCEINLINE void insert(ordered_range_t, std::initializer_list<value_type> il)
{ 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 #endif
//! <b>Requires</b>: this->get_allocator() == source.get_allocator(). //! <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()) //! <b>Complexity</b>: N log(a.size() + N) (N has the value source.size())
template<class C2> 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()); } { 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> template<class C2>
BOOST_CONTAINER_FORCEINLINE void merge(BOOST_RV_REF_BEG flat_multimap<Key, T, C2, Allocator> BOOST_RV_REF_END 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, Allocator>&>(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> 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()); } { 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> template<class C2>
BOOST_CONTAINER_FORCEINLINE void merge(BOOST_RV_REF_BEG flat_map<Key, T, C2, Allocator> BOOST_RV_REF_END 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, Allocator>&>(source)); } { return this->merge(static_cast<flat_map<Key, T, C2, AllocatorOrContainer>&>(source)); }
//! <b>Effects</b>: Erases the element pointed to by p. //! <b>Effects</b>: Erases the element pointed to by p.
//! //!
@@ -2512,11 +2566,11 @@ namespace boost {
//!has_trivial_destructor_after_move<> == true_type //!has_trivial_destructor_after_move<> == true_type
//!specialization for optimizations //!specialization for optimizations
template <class Key, class T, class Compare, class Allocator> template <class Key, class T, class Compare, class AllocatorOrContainer>
struct has_trivial_destructor_after_move< boost::container::flat_multimap<Key, T, Compare, Allocator> > struct has_trivial_destructor_after_move< boost::container::flat_multimap<Key, T, Compare, AllocatorOrContainer> >
{ {
typedef typename ::boost::container::allocator_traits<Allocator>::pointer pointer; typedef typename ::boost::container::allocator_traits<AllocatorOrContainer>::pointer pointer;
static const bool value = ::boost::has_trivial_destructor_after_move<Allocator>::value && 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<pointer>::value &&
::boost::has_trivial_destructor_after_move<Compare>::value; ::boost::has_trivial_destructor_after_move<Compare>::value;
}; };

View File

@@ -48,45 +48,51 @@ namespace boost {
namespace container { namespace container {
#if !defined(BOOST_CONTAINER_DOXYGEN_INVOKED) #if !defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
template <class Key, class T, class Compare, class Allocator> template <class Key, class Compare, class AllocatorOrContainer>
class flat_multimap; class flat_multiset;
#endif #endif
//! flat_set is a Sorted Associative Container that stores objects of type Key. //! 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. //! 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. //! flat_set is similar to std::set but it's implemented by as an ordered sequence container.
//! This means that inserting a new element into a flat_set invalidates //! The underlying sequence container is by default <i>vector</i> but it can also work
//! previous iterators and references //! 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 //! Using vector-like sequence containers means that inserting a new element into a flat_set might invalidate
//! pointing to elements that come after (their keys are bigger) the erased element. //! 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. //! This container provides random-access iterators.
//! //!
//! \tparam Key is the type to be inserted in the set, which is also the key_type //! \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 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 #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 #else
template <class Key, class Compare, class Allocator> template <class Key, class Compare, class AllocatorOrContainer>
#endif #endif
class flat_set class flat_set
///@cond ///@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 ///@endcond
{ {
#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED #ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
private: private:
BOOST_COPYABLE_AND_MOVABLE(flat_set) 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: public:
base_t &tree() tree_t &tree()
{ return *this; } { return *this; }
const base_t &tree() const const tree_t &tree() const
{ return *this; } { return *this; }
#endif //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED #endif //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
@@ -98,23 +104,24 @@ class flat_set
// //
////////////////////////////////////////////// //////////////////////////////////////////////
typedef Key key_type; typedef Key key_type;
typedef Key value_type;
typedef Compare key_compare; typedef Compare key_compare;
typedef Compare value_compare; typedef Key value_type;
typedef ::boost::container::allocator_traits<Allocator> allocator_traits_type; typedef typename BOOST_CONTAINER_IMPDEF(tree_t::sequence_type) sequence_type;
typedef typename ::boost::container::allocator_traits<Allocator>::pointer pointer; typedef typename sequence_type::allocator_type allocator_type;
typedef typename ::boost::container::allocator_traits<Allocator>::const_pointer const_pointer; typedef ::boost::container::allocator_traits<allocator_type> allocator_traits_type;
typedef typename ::boost::container::allocator_traits<Allocator>::reference reference; typedef typename sequence_type::pointer pointer;
typedef typename ::boost::container::allocator_traits<Allocator>::const_reference const_reference; typedef typename sequence_type::const_pointer const_pointer;
typedef typename ::boost::container::allocator_traits<Allocator>::size_type size_type; typedef typename sequence_type::reference reference;
typedef typename ::boost::container::allocator_traits<Allocator>::difference_type difference_type; typedef typename sequence_type::const_reference const_reference;
typedef Allocator allocator_type; typedef typename sequence_type::size_type size_type;
typedef typename BOOST_CONTAINER_IMPDEF(base_t::stored_allocator_type) stored_allocator_type; typedef typename sequence_type::difference_type difference_type;
typedef typename BOOST_CONTAINER_IMPDEF(base_t::iterator) iterator; typedef typename BOOST_CONTAINER_IMPDEF(tree_t::stored_allocator_type) stored_allocator_type;
typedef typename BOOST_CONTAINER_IMPDEF(base_t::const_iterator) const_iterator; typedef typename BOOST_CONTAINER_IMPDEF(tree_t::value_compare) value_compare;
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 sequence_type::iterator iterator;
typedef typename BOOST_CONTAINER_IMPDEF(base_t::sequence_type) sequence_type; 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: public:
////////////////////////////////////////////// //////////////////////////////////////////////
@@ -127,9 +134,9 @@ class flat_set
//! //!
//! <b>Complexity</b>: Constant. //! <b>Complexity</b>: Constant.
BOOST_CONTAINER_FORCEINLINE 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) container_detail::is_nothrow_default_constructible<Compare>::value)
: base_t() : tree_t()
{} {}
//! <b>Effects</b>: Constructs an empty container using the specified //! <b>Effects</b>: Constructs an empty container using the specified
@@ -138,7 +145,7 @@ class flat_set
//! <b>Complexity</b>: Constant. //! <b>Complexity</b>: Constant.
BOOST_CONTAINER_FORCEINLINE BOOST_CONTAINER_FORCEINLINE
explicit flat_set(const Compare& comp) explicit flat_set(const Compare& comp)
: base_t(comp) : tree_t(comp)
{} {}
//! <b>Effects</b>: Constructs an empty container using the specified allocator. //! <b>Effects</b>: Constructs an empty container using the specified allocator.
@@ -146,7 +153,7 @@ class flat_set
//! <b>Complexity</b>: Constant. //! <b>Complexity</b>: Constant.
BOOST_CONTAINER_FORCEINLINE BOOST_CONTAINER_FORCEINLINE
explicit flat_set(const allocator_type& a) explicit flat_set(const allocator_type& a)
: base_t(a) : tree_t(a)
{} {}
//! <b>Effects</b>: Constructs an empty container using the specified //! <b>Effects</b>: Constructs an empty container using the specified
@@ -155,7 +162,7 @@ class flat_set
//! <b>Complexity</b>: Constant. //! <b>Complexity</b>: Constant.
BOOST_CONTAINER_FORCEINLINE BOOST_CONTAINER_FORCEINLINE
flat_set(const Compare& comp, const allocator_type& a) 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 //! <b>Effects</b>: Constructs an empty container and
@@ -166,7 +173,7 @@ class flat_set
template <class InputIterator> template <class InputIterator>
BOOST_CONTAINER_FORCEINLINE BOOST_CONTAINER_FORCEINLINE
flat_set(InputIterator first, InputIterator last) 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 //! <b>Effects</b>: Constructs an empty container using the specified
@@ -177,7 +184,7 @@ class flat_set
template <class InputIterator> template <class InputIterator>
BOOST_CONTAINER_FORCEINLINE BOOST_CONTAINER_FORCEINLINE
flat_set(InputIterator first, InputIterator last, const allocator_type& a) 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 //! <b>Effects</b>: Constructs an empty container using the specified comparison object and
@@ -188,7 +195,7 @@ class flat_set
template <class InputIterator> template <class InputIterator>
BOOST_CONTAINER_FORCEINLINE BOOST_CONTAINER_FORCEINLINE
flat_set(InputIterator first, InputIterator last, const Compare& comp) 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 //! <b>Effects</b>: Constructs an empty container using the specified comparison object and
@@ -199,7 +206,7 @@ class flat_set
template <class InputIterator> template <class InputIterator>
BOOST_CONTAINER_FORCEINLINE BOOST_CONTAINER_FORCEINLINE
flat_set(InputIterator first, InputIterator last, const Compare& comp, const allocator_type& a) 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 //! <b>Effects</b>: Constructs an empty container and
@@ -215,7 +222,7 @@ class flat_set
template <class InputIterator> template <class InputIterator>
BOOST_CONTAINER_FORCEINLINE BOOST_CONTAINER_FORCEINLINE
flat_set(ordered_unique_range_t, InputIterator first, InputIterator last) 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 //! <b>Effects</b>: Constructs an empty container using the specified comparison object and
@@ -231,7 +238,7 @@ class flat_set
template <class InputIterator> template <class InputIterator>
BOOST_CONTAINER_FORCEINLINE BOOST_CONTAINER_FORCEINLINE
flat_set(ordered_unique_range_t, InputIterator first, InputIterator last, const Compare& comp) 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 //! <b>Effects</b>: Constructs an empty container using the specified comparison object and
@@ -247,7 +254,7 @@ class flat_set
template <class InputIterator> template <class InputIterator>
BOOST_CONTAINER_FORCEINLINE BOOST_CONTAINER_FORCEINLINE
flat_set(ordered_unique_range_t, InputIterator first, InputIterator last, const Compare& comp, const allocator_type& a) 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) #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 //! <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(). //! comp and otherwise N logN, where N is il.begin() - il.end().
BOOST_CONTAINER_FORCEINLINE flat_set(std::initializer_list<value_type> il) 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 //! <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 //! <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(). //! 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) 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 //! <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 //! <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(). //! 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) 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 //! <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 //! <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(). //! 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) 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 //! <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. //! <b>Note</b>: Non-standard extension.
BOOST_CONTAINER_FORCEINLINE flat_set(ordered_unique_range_t, std::initializer_list<value_type> il) 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 //! <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. //! <b>Note</b>: Non-standard extension.
BOOST_CONTAINER_FORCEINLINE flat_set(ordered_unique_range_t, std::initializer_list<value_type> il, const Compare& comp) 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 //! <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. //! <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) 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 #endif
@@ -334,7 +341,7 @@ class flat_set
//! //!
//! <b>Complexity</b>: Linear in x.size(). //! <b>Complexity</b>: Linear in x.size().
BOOST_CONTAINER_FORCEINLINE flat_set(const flat_set& x) 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. //! <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. //! <b>Postcondition</b>: x is emptied.
BOOST_CONTAINER_FORCEINLINE flat_set(BOOST_RV_REF(flat_set) x) BOOST_CONTAINER_FORCEINLINE flat_set(BOOST_RV_REF(flat_set) x)
BOOST_NOEXCEPT_IF(boost::container::container_detail::is_nothrow_move_constructible<Compare>::value) 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>Effects</b>: Copy constructs a container using the specified allocator.
//! //!
//! <b>Complexity</b>: Linear in x.size(). //! <b>Complexity</b>: Linear in x.size().
BOOST_CONTAINER_FORCEINLINE flat_set(const flat_set& x, const allocator_type &a) 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. //! <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 //! <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) 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>Effects</b>: Makes *this a copy of x.
//! //!
//! <b>Complexity</b>: Linear in x.size(). //! <b>Complexity</b>: Linear in x.size().
BOOST_CONTAINER_FORCEINLINE flat_set& operator=(BOOST_COPY_ASSIGN_REF(flat_set) x) 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 //! <b>Throws</b>: If allocator_traits_type::propagate_on_container_move_assignment
//! is false and (allocation throws or value_type's move constructor throws) //! 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 || BOOST_NOEXCEPT_IF( (allocator_traits_type::propagate_on_container_move_assignment::value ||
allocator_traits_type::is_always_equal::value) && allocator_traits_type::is_always_equal::value) &&
boost::container::container_detail::is_nothrow_move_assignable<Compare>::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) #if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
//! <b>Effects</b>: Copy all elements from il to *this. //! <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. //! <b>Note</b>: If an element is inserted it might invalidate elements.
template <class... Args> template <class... Args>
BOOST_CONTAINER_FORCEINLINE std::pair<iterator,bool> emplace(BOOST_FWD_REF(Args)... 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 //! <b>Effects</b>: Inserts an object of type Key constructed with
//! std::forward<Args>(args)... in the container if and only if there is //! 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. //! <b>Note</b>: If an element is inserted it might invalidate elements.
template <class... Args> template <class... Args>
BOOST_CONTAINER_FORCEINLINE iterator emplace_hint(const_iterator p, BOOST_FWD_REF(Args)... 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) #else // !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
#define BOOST_CONTAINER_FLAT_SET_EMPLACE_CODE(N) \ #define BOOST_CONTAINER_FLAT_SET_EMPLACE_CODE(N) \
BOOST_MOVE_TMPL_LT##N BOOST_MOVE_CLASS##N BOOST_MOVE_GT##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)\ 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_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)\ 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) BOOST_MOVE_ITERATE_0TO9(BOOST_CONTAINER_FLAT_SET_EMPLACE_CODE)
#undef 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. //! <b>Note</b>: If an element is inserted it might invalidate elements.
template <class InputIterator> template <class InputIterator>
BOOST_CONTAINER_FORCEINLINE void insert(InputIterator first, InputIterator last) 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 //! <b>Requires</b>: first, last are not iterators into *this and
//! must be ordered according to the predicate and must be //! 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. //! <b>Note</b>: Non-standard extension. If an element is inserted it might invalidate elements.
template <class InputIterator> template <class InputIterator>
BOOST_CONTAINER_FORCEINLINE void insert(ordered_unique_range_t, InputIterator first, InputIterator last) 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) #if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
//! <b>Effects</b>: inserts each element from the range [il.begin(), il.end()) if and only //! <b>Effects</b>: inserts each element from the range [il.begin(), il.end()) if and only
@@ -711,7 +718,7 @@ class flat_set
//! //!
//! <b>Note</b>: If an element is inserted it might invalidate elements. //! <b>Note</b>: If an element is inserted it might invalidate elements.
BOOST_CONTAINER_FORCEINLINE void insert(std::initializer_list<value_type> il) BOOST_CONTAINER_FORCEINLINE void insert(std::initializer_list<value_type> il)
{ 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 //! <b>Requires</b>: Range [il.begin(), il.end()) must be ordered according to the predicate
//! and must be unique values. //! 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. //! <b>Note</b>: Non-standard extension. If an element is inserted it might invalidate elements.
BOOST_CONTAINER_FORCEINLINE void insert(ordered_unique_range_t, std::initializer_list<value_type> il) BOOST_CONTAINER_FORCEINLINE void insert(ordered_unique_range_t, std::initializer_list<value_type> il)
{ 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 #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> template<class C2>
BOOST_CONTAINER_FORCEINLINE void merge(flat_set<Key, C2, Allocator>& source) BOOST_CONTAINER_FORCEINLINE void merge(flat_set<Key, C2, AllocatorOrContainer>& source)
{ this->base_t::merge_unique(source.tree()); } { 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> template<class C2>
BOOST_CONTAINER_FORCEINLINE void merge(BOOST_RV_REF_BEG flat_set<Key, C2, Allocator> BOOST_RV_REF_END 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, Allocator>&>(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> template<class C2>
BOOST_CONTAINER_FORCEINLINE void merge(flat_multiset<Key, C2, Allocator>& source) BOOST_CONTAINER_FORCEINLINE void merge(flat_multiset<Key, C2, AllocatorOrContainer>& source)
{ this->base_t::merge_unique(source.tree()); } { 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> template<class C2>
BOOST_CONTAINER_FORCEINLINE void merge(BOOST_RV_REF_BEG flat_multiset<Key, C2, Allocator> BOOST_RV_REF_END 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, Allocator>&>(source)); } { return this->merge(static_cast<flat_multiset<Key, C2, AllocatorOrContainer>&>(source)); }
#if defined(BOOST_CONTAINER_DOXYGEN_INVOKED) #if defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
@@ -875,7 +882,7 @@ class flat_set
//! //!
//! <b>Complexity</b>: log(size())+count(k) //! <b>Complexity</b>: log(size())+count(k)
BOOST_CONTAINER_FORCEINLINE size_type count(const key_type& x) const 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) #if defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
//! <b>Returns</b>: An iterator pointing to the first element with key not less //! <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 //! <b>Complexity</b>: Logarithmic
BOOST_CONTAINER_FORCEINLINE std::pair<const_iterator, const_iterator> equal_range(const key_type& x) const 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>Effects</b>: Equivalent to std::make_pair(this->lower_bound(k), this->upper_bound(k)).
//! //!
//! <b>Complexity</b>: Logarithmic //! <b>Complexity</b>: Logarithmic
BOOST_CONTAINER_FORCEINLINE std::pair<iterator,iterator> equal_range(const key_type& x) 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) #if defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
@@ -971,7 +978,7 @@ class flat_set
//! //!
//! <b>Throws</b>: If the comparison or the move constructor throws //! <b>Throws</b>: If the comparison or the move constructor throws
BOOST_CONTAINER_FORCEINLINE void adopt_sequence(BOOST_RV_REF(sequence_type) seq) 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() //! <b>Requires</b>: seq shall be ordered according to this->compare()
//! and shall contain unique elements. //! and shall contain unique elements.
@@ -983,17 +990,17 @@ class flat_set
//! //!
//! <b>Throws</b>: If the move assignment throws //! <b>Throws</b>: If the move assignment throws
BOOST_CONTAINER_FORCEINLINE void adopt_sequence(ordered_unique_range_t, BOOST_RV_REF(sequence_type) seq) 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 #ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
private: private:
template<class KeyType> template<class KeyType>
BOOST_CONTAINER_FORCEINLINE std::pair<iterator, bool> priv_insert(BOOST_FWD_REF(KeyType) x) 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> template<class KeyType>
BOOST_CONTAINER_FORCEINLINE iterator priv_insert(const_iterator p, BOOST_FWD_REF(KeyType) x) 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 #endif //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
}; };
@@ -1003,11 +1010,11 @@ class flat_set
//!has_trivial_destructor_after_move<> == true_type //!has_trivial_destructor_after_move<> == true_type
//!specialization for optimizations //!specialization for optimizations
template <class Key, class Compare, class Allocator> template <class Key, class Compare, class AllocatorOrContainer>
struct has_trivial_destructor_after_move<boost::container::flat_set<Key, Compare, Allocator> > struct has_trivial_destructor_after_move<boost::container::flat_set<Key, Compare, AllocatorOrContainer> >
{ {
typedef typename ::boost::container::allocator_traits<Allocator>::pointer pointer; typedef typename ::boost::container::allocator_traits<AllocatorOrContainer>::pointer pointer;
static const bool value = ::boost::has_trivial_destructor_after_move<Allocator>::value && 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<pointer>::value &&
::boost::has_trivial_destructor_after_move<Compare>::value; ::boost::has_trivial_destructor_after_move<Compare>::value;
}; };
@@ -1016,42 +1023,47 @@ namespace container {
#endif //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED #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. //! Using vector-like sequence containers means that inserting a new element into a flat_multiset might invalidate
//! This means that inserting a new element into a flat_multiset invalidates //! previous iterators and references (unless that sequence container is <i>stable_vector</i> or a similar
//! previous iterators and references //! 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.
//! Erasing an element invalidates iterators and references
//! pointing to elements that come after (their keys are bigger) the erased element.
//! //!
//! This container provides random-access iterators. //! This container provides random-access iterators.
//! //!
//! \tparam Key is the type to be inserted in the multiset, which is also the key_type //! \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 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 #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 #else
template <class Key, class Compare, class Allocator> template <class Key, class Compare, class AllocatorOrContainer>
#endif #endif
class flat_multiset class flat_multiset
///@cond ///@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 ///@endcond
{ {
#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED #ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
private: private:
BOOST_COPYABLE_AND_MOVABLE(flat_multiset) 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: public:
base_t &tree() tree_t &tree()
{ return *this; } { return *this; }
const base_t &tree() const const tree_t &tree() const
{ return *this; } { return *this; }
#endif //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED #endif //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
@@ -1062,67 +1074,68 @@ class flat_multiset
// //
////////////////////////////////////////////// //////////////////////////////////////////////
typedef Key key_type; typedef Key key_type;
typedef Key value_type;
typedef Compare key_compare; typedef Compare key_compare;
typedef Compare value_compare; typedef Key value_type;
typedef ::boost::container::allocator_traits<Allocator> allocator_traits_type; typedef typename BOOST_CONTAINER_IMPDEF(tree_t::sequence_type) sequence_type;
typedef typename ::boost::container::allocator_traits<Allocator>::pointer pointer; typedef typename sequence_type::allocator_type allocator_type;
typedef typename ::boost::container::allocator_traits<Allocator>::const_pointer const_pointer; typedef ::boost::container::allocator_traits<allocator_type> allocator_traits_type;
typedef typename ::boost::container::allocator_traits<Allocator>::reference reference; typedef typename sequence_type::pointer pointer;
typedef typename ::boost::container::allocator_traits<Allocator>::const_reference const_reference; typedef typename sequence_type::const_pointer const_pointer;
typedef typename ::boost::container::allocator_traits<Allocator>::size_type size_type; typedef typename sequence_type::reference reference;
typedef typename ::boost::container::allocator_traits<Allocator>::difference_type difference_type; typedef typename sequence_type::const_reference const_reference;
typedef Allocator allocator_type; typedef typename sequence_type::size_type size_type;
typedef typename BOOST_CONTAINER_IMPDEF(base_t::stored_allocator_type) stored_allocator_type; typedef typename sequence_type::difference_type difference_type;
typedef typename BOOST_CONTAINER_IMPDEF(base_t::iterator) iterator; typedef typename BOOST_CONTAINER_IMPDEF(tree_t::stored_allocator_type) stored_allocator_type;
typedef typename BOOST_CONTAINER_IMPDEF(base_t::const_iterator) const_iterator; typedef typename BOOST_CONTAINER_IMPDEF(tree_t::value_compare) value_compare;
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 sequence_type::iterator iterator;
typedef typename BOOST_CONTAINER_IMPDEF(base_t::sequence_type) sequence_type; 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() //! @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) container_detail::is_nothrow_default_constructible<Compare>::value)
: base_t() : tree_t()
{} {}
//! @copydoc ::boost::container::flat_set::flat_set(const Compare&) //! @copydoc ::boost::container::flat_set::flat_set(const Compare&)
BOOST_CONTAINER_FORCEINLINE explicit flat_multiset(const Compare& comp) 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&) //! @copydoc ::boost::container::flat_set::flat_set(const allocator_type&)
BOOST_CONTAINER_FORCEINLINE explicit flat_multiset(const allocator_type& a) 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&) //! @copydoc ::boost::container::flat_set::flat_set(const Compare&, const allocator_type&)
BOOST_CONTAINER_FORCEINLINE flat_multiset(const Compare& comp, const allocator_type& a) 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) //! @copydoc ::boost::container::flat_set::flat_set(InputIterator, InputIterator)
template <class InputIterator> template <class InputIterator>
BOOST_CONTAINER_FORCEINLINE flat_multiset(InputIterator first, InputIterator last) 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&) //! @copydoc ::boost::container::flat_set::flat_set(InputIterator, InputIterator, const allocator_type&)
template <class InputIterator> template <class InputIterator>
BOOST_CONTAINER_FORCEINLINE flat_multiset(InputIterator first, InputIterator last, const allocator_type& a) 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) //! @copydoc ::boost::container::flat_set::flat_set(InputIterator, InputIterator, const Compare& comp)
template <class InputIterator> template <class InputIterator>
BOOST_CONTAINER_FORCEINLINE flat_multiset(InputIterator first, InputIterator last, const Compare& comp) 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&) //! @copydoc ::boost::container::flat_set::flat_set(InputIterator, InputIterator, const Compare& comp, const allocator_type&)
template <class InputIterator> template <class InputIterator>
BOOST_CONTAINER_FORCEINLINE flat_multiset(InputIterator first, InputIterator last, const Compare& comp, const allocator_type& a) 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 //! <b>Effects</b>: Constructs an empty flat_multiset and
@@ -1136,7 +1149,7 @@ class flat_multiset
//! <b>Note</b>: Non-standard extension. //! <b>Note</b>: Non-standard extension.
template <class InputIterator> template <class InputIterator>
BOOST_CONTAINER_FORCEINLINE flat_multiset(ordered_range_t, InputIterator first, InputIterator last) 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 //! <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. //! <b>Note</b>: Non-standard extension.
template <class InputIterator> template <class InputIterator>
BOOST_CONTAINER_FORCEINLINE flat_multiset(ordered_range_t, InputIterator first, InputIterator last, const Compare& comp) 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 //! <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. //! <b>Note</b>: Non-standard extension.
template <class InputIterator> template <class InputIterator>
BOOST_CONTAINER_FORCEINLINE flat_multiset(ordered_range_t, InputIterator first, InputIterator last, const Compare& comp, const allocator_type& a) 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) #if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
//! @copydoc ::boost::container::flat_set::flat_set(std::initializer_list<value_type) //! @copydoc ::boost::container::flat_set::flat_set(std::initializer_list<value_type)
BOOST_CONTAINER_FORCEINLINE flat_multiset(std::initializer_list<value_type> il) 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&) //! @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) 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) //! @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) 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&) //! @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) 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 //! <b>Effects</b>: Constructs an empty containerand
@@ -1198,7 +1211,7 @@ class flat_multiset
//! //!
//! <b>Note</b>: Non-standard extension. //! <b>Note</b>: Non-standard extension.
BOOST_CONTAINER_FORCEINLINE flat_multiset(ordered_range_t, std::initializer_list<value_type> il) 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 //! <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. //! <b>Note</b>: Non-standard extension.
BOOST_CONTAINER_FORCEINLINE flat_multiset(ordered_range_t, std::initializer_list<value_type> il, const Compare& comp) 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 //! <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. //! <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) 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 #endif
//! @copydoc ::boost::container::flat_set::flat_set(const flat_set &) //! @copydoc ::boost::container::flat_set::flat_set(const flat_set &)
BOOST_CONTAINER_FORCEINLINE flat_multiset(const flat_multiset& x) 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 &&) //! @copydoc ::boost::container::flat_set::flat_set(flat_set &&)
BOOST_CONTAINER_FORCEINLINE flat_multiset(BOOST_RV_REF(flat_multiset) x) BOOST_CONTAINER_FORCEINLINE flat_multiset(BOOST_RV_REF(flat_multiset) x)
BOOST_NOEXCEPT_IF(boost::container::container_detail::is_nothrow_move_constructible<Compare>::value) 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 &) //! @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) 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 &) //! @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) 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 &) //! @copydoc ::boost::container::flat_set::operator=(const flat_set &)
BOOST_CONTAINER_FORCEINLINE flat_multiset& operator=(BOOST_COPY_ASSIGN_REF(flat_multiset) x) 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 &&) //! @copydoc ::boost::container::flat_set::operator=(flat_set &&)
BOOST_CONTAINER_FORCEINLINE flat_multiset& operator=(BOOST_RV_REF(flat_multiset) x) BOOST_CONTAINER_FORCEINLINE flat_multiset& operator=(BOOST_RV_REF(flat_multiset) x)
BOOST_NOEXCEPT_IF( (allocator_traits_type::propagate_on_container_move_assignment::value || BOOST_NOEXCEPT_IF( (allocator_traits_type::propagate_on_container_move_assignment::value ||
allocator_traits_type::is_always_equal::value) && allocator_traits_type::is_always_equal::value) &&
boost::container::container_detail::is_nothrow_move_assignable<Compare>::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) #if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
//! @copydoc ::boost::container::flat_set::operator=(std::initializer_list<value_type>) //! @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. //! <b>Note</b>: If an element is inserted it might invalidate elements.
template <class... Args> template <class... Args>
BOOST_CONTAINER_FORCEINLINE iterator emplace(BOOST_FWD_REF(Args)... 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 //! <b>Effects</b>: Inserts an object of type Key constructed with
//! std::forward<Args>(args)... in the container. //! 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. //! <b>Note</b>: If an element is inserted it might invalidate elements.
template <class... Args> template <class... Args>
BOOST_CONTAINER_FORCEINLINE iterator emplace_hint(const_iterator p, BOOST_FWD_REF(Args)... 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) #else // !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
#define BOOST_CONTAINER_FLAT_MULTISET_EMPLACE_CODE(N) \ #define BOOST_CONTAINER_FLAT_MULTISET_EMPLACE_CODE(N) \
BOOST_MOVE_TMPL_LT##N BOOST_MOVE_CLASS##N BOOST_MOVE_GT##N \ BOOST_MOVE_TMPL_LT##N BOOST_MOVE_CLASS##N BOOST_MOVE_GT##N \
BOOST_CONTAINER_FORCEINLINE iterator emplace(BOOST_MOVE_UREF##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_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)\ 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) BOOST_MOVE_ITERATE_0TO9(BOOST_CONTAINER_FLAT_MULTISET_EMPLACE_CODE)
#undef 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. //! <b>Note</b>: If an element is inserted it might invalidate elements.
template <class InputIterator> template <class InputIterator>
BOOST_CONTAINER_FORCEINLINE void insert(InputIterator first, InputIterator last) 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 //! <b>Requires</b>: first, last are not iterators into *this and
//! must be ordered according to the predicate. //! 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. //! <b>Note</b>: Non-standard extension. If an element is inserted it might invalidate elements.
template <class InputIterator> template <class InputIterator>
BOOST_CONTAINER_FORCEINLINE void insert(ordered_range_t, InputIterator first, InputIterator last) 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) #if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
//! <b>Effects</b>: inserts each element from the range [il.begin(), il.end()). //! <b>Effects</b>: inserts each element from the range [il.begin(), il.end()).
@@ -1472,7 +1485,7 @@ class flat_multiset
//! //!
//! <b>Note</b>: If an element is inserted it might invalidate elements. //! <b>Note</b>: If an element is inserted it might invalidate elements.
BOOST_CONTAINER_FORCEINLINE void insert(std::initializer_list<value_type> il) BOOST_CONTAINER_FORCEINLINE void insert(std::initializer_list<value_type> il)
{ 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. //! <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. //! <b>Note</b>: Non-standard extension. If an element is inserted it might invalidate elements.
BOOST_CONTAINER_FORCEINLINE void insert(ordered_range_t, std::initializer_list<value_type> il) BOOST_CONTAINER_FORCEINLINE void insert(ordered_range_t, std::initializer_list<value_type> il)
{ this->base_t::insert_equal(ordered_range, il.begin(), il.end()); } { this->tree_t::insert_equal(ordered_range, il.begin(), il.end()); }
#endif #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> template<class C2>
BOOST_CONTAINER_FORCEINLINE void merge(flat_multiset<Key, C2, Allocator>& source) BOOST_CONTAINER_FORCEINLINE void merge(flat_multiset<Key, C2, AllocatorOrContainer>& source)
{ this->base_t::merge_equal(source.tree()); } { 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> template<class C2>
BOOST_CONTAINER_FORCEINLINE void merge(BOOST_RV_REF_BEG flat_multiset<Key, C2, Allocator> BOOST_RV_REF_END 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, Allocator>&>(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> template<class C2>
BOOST_CONTAINER_FORCEINLINE void merge(flat_set<Key, C2, Allocator>& source) BOOST_CONTAINER_FORCEINLINE void merge(flat_set<Key, C2, AllocatorOrContainer>& source)
{ this->base_t::merge_equal(source.tree()); } { 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> template<class C2>
BOOST_CONTAINER_FORCEINLINE void merge(BOOST_RV_REF_BEG flat_set<Key, C2, Allocator> BOOST_RV_REF_END 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, Allocator>&>(source)); } { return this->merge(static_cast<flat_set<Key, C2, AllocatorOrContainer>&>(source)); }
#if defined(BOOST_CONTAINER_DOXYGEN_INVOKED) #if defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
@@ -1624,7 +1637,7 @@ class flat_multiset
//! //!
//! <b>Throws</b>: If the comparison or the move constructor throws //! <b>Throws</b>: If the comparison or the move constructor throws
BOOST_CONTAINER_FORCEINLINE void adopt_sequence(BOOST_RV_REF(sequence_type) seq) 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() //! <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 //! <b>Throws</b>: If the move assignment throws
BOOST_CONTAINER_FORCEINLINE void adopt_sequence(ordered_range_t, BOOST_RV_REF(sequence_type) seq) 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 #ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
private: private:
template <class KeyType> template <class KeyType>
BOOST_CONTAINER_FORCEINLINE iterator priv_insert(BOOST_FWD_REF(KeyType) x) 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> template <class KeyType>
BOOST_CONTAINER_FORCEINLINE iterator priv_insert(const_iterator p, BOOST_FWD_REF(KeyType) x) 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 #endif //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
}; };
@@ -1655,11 +1668,11 @@ class flat_multiset
//!has_trivial_destructor_after_move<> == true_type //!has_trivial_destructor_after_move<> == true_type
//!specialization for optimizations //!specialization for optimizations
template <class Key, class Compare, class Allocator> template <class Key, class Compare, class AllocatorOrContainer>
struct has_trivial_destructor_after_move<boost::container::flat_multiset<Key, Compare, Allocator> > struct has_trivial_destructor_after_move<boost::container::flat_multiset<Key, Compare, AllocatorOrContainer> >
{ {
typedef typename ::boost::container::allocator_traits<Allocator>::pointer pointer; typedef typename ::boost::container::allocator_traits<AllocatorOrContainer>::pointer pointer;
static const bool value = ::boost::has_trivial_destructor_after_move<Allocator>::value && 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<pointer>::value &&
::boost::has_trivial_destructor_after_move<Compare>::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> template<class U, std::size_t OtherCapacity>
friend class static_vector; friend class static_vector;
public:
typedef container_detail::static_storage_allocator<Value, Capacity> allocator_type;
#endif //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED #endif //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
public: public:
@@ -252,6 +254,19 @@ public:
: base_t(other) : 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>. //! @pre <tt>other.size() <= capacity()</tt>.
//! //!
//! @brief Constructs a copy of other static_vector. //! @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 ProjectSection(ProjectDependencies) = postProject
EndProjectSection EndProjectSection
EndProject 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 Global
GlobalSection(SolutionConfiguration) = preSolution GlobalSection(SolutionConfiguration) = preSolution
Debug = Debug Debug = Debug
@@ -637,6 +641,10 @@ Global
{5CE185C3-2609-4FA5-FE38-792BA0D3A606}.Debug.Build.0 = Debug|Win32 {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.ActiveCfg = Release|Win32
{5CE185C3-2609-4FA5-FE38-792BA0D3A606}.Release.Build.0 = 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 EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution GlobalSection(ExtensibilityGlobals) = postSolution
EndGlobalSection EndGlobalSection

View File

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

View File

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

View File

@@ -57,25 +57,6 @@ template class flat_multiset
, allocator<test::movable_and_copyable_int> , 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, //As flat container iterators are typedefs for vector::[const_]iterator,
//no need to explicit instantiate them //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){ for(int i = 0; i < MaxElem; ++i){
stdmultimap.insert(StdPairType(MaxElem/2+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; if(!CheckEqualPairContainers(boostmultimap, stdmultimap)) return 1;
for(int i = 0; i < MaxElem; ++i){ for(int i = 0; i < MaxElem; ++i){
stdmultimap.insert(StdPairType(MaxElem*2/2+i, MaxElem*2+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; if(!CheckEqualPairContainers(boostmultimap, stdmultimap)) return 1;
} }

View File

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