Introducing allocator_traits and pointer_traits changes into several libraries.

[SVN r76106]
This commit is contained in:
Ion Gaztañaga
2011-12-22 20:08:24 +00:00
parent 5247083184
commit 935a534713
41 changed files with 4304 additions and 2448 deletions
+241 -229
View File
@@ -8,8 +8,8 @@
//
//////////////////////////////////////////////////////////////////////////////
#ifndef BOOST_CONTAINERS_FLAT_MAP_HPP
#define BOOST_CONTAINERS_FLAT_MAP_HPP
#ifndef BOOST_CONTAINER_FLAT_MAP_HPP
#define BOOST_CONTAINER_FLAT_MAP_HPP
#if (defined _MSC_VER) && (_MSC_VER >= 1200)
# pragma once
@@ -26,6 +26,7 @@
#include <boost/container/detail/flat_tree.hpp>
#include <boost/type_traits/has_trivial_destructor.hpp>
#include <boost/container/detail/mpl.hpp>
#include <boost/container/allocator/allocator_traits.hpp>
#include <boost/move/move.hpp>
#ifdef BOOST_CONTAINER_DOXYGEN_INVOKED
@@ -52,6 +53,23 @@ inline bool operator==(const flat_map<Key,T,Pred,A>& x,
template <class Key, class T, class Pred, class A>
inline bool operator<(const flat_map<Key,T,Pred,A>& x,
const flat_map<Key,T,Pred,A>& y);
namespace container_detail{
template<class D, class S>
static D &force(const S &s)
{ return *const_cast<D*>((reinterpret_cast<const D*>(&s))); }
template<class D, class S>
static D force_copy(S s)
{
D *vp = reinterpret_cast<D *>(&s);
return D(*vp);
}
} //namespace container_detail{
/// @endcond
//! A flat_map is a kind of associative container that supports unique keys (contains at
@@ -86,19 +104,19 @@ class flat_map
private:
BOOST_COPYABLE_AND_MOVABLE(flat_map)
//This is the tree that we should store if pair was movable
typedef containers_detail::flat_tree<Key,
typedef container_detail::flat_tree<Key,
std::pair<Key, T>,
containers_detail::select1st< std::pair<Key, T> >,
container_detail::select1st< std::pair<Key, T> >,
Pred,
A> tree_t;
//This is the real tree stored here. It's based on a movable pair
typedef containers_detail::flat_tree<Key,
containers_detail::pair<Key, T>,
containers_detail::select1st<containers_detail::pair<Key, T> >,
typedef container_detail::flat_tree<Key,
container_detail::pair<Key, T>,
container_detail::select1st<container_detail::pair<Key, T> >,
Pred,
typename A::template
rebind<containers_detail::pair<Key, T> >::other> impl_tree_t;
typename allocator_traits<A>::template portable_rebind_alloc
<container_detail::pair<Key, T> >::type> impl_tree_t;
impl_tree_t m_flat_tree; // flat tree representing flat_map
typedef typename impl_tree_t::value_type impl_value_type;
@@ -112,56 +130,56 @@ class flat_map
typedef typename impl_tree_t::reverse_iterator impl_reverse_iterator;
typedef typename impl_tree_t::const_reverse_iterator impl_const_reverse_iterator;
typedef typename impl_tree_t::allocator_type impl_allocator_type;
typedef allocator_traits<A> allocator_traits_type;
template<class D, class S>
static D &force(const S &s)
{ return *const_cast<D*>(reinterpret_cast<const D*>(&s)); }
template<class D, class S>
static D force_copy(S s)
{
value_type *vp = reinterpret_cast<value_type *>(&*s);
return D(vp);
}
/// @endcond
public:
// typedefs:
typedef typename impl_tree_t::key_type key_type;
typedef T mapped_type;
typedef typename std::pair<key_type, mapped_type> value_type;
typedef typename A::pointer pointer;
typedef typename A::const_pointer const_pointer;
typedef typename A::reference reference;
typedef typename A::const_reference const_reference;
typedef containers_detail::flat_tree_value_compare
typedef Key key_type;
typedef T mapped_type;
typedef typename std::pair<key_type, mapped_type> value_type;
typedef typename allocator_traits_type::pointer pointer;
typedef typename allocator_traits_type::const_pointer const_pointer;
typedef typename allocator_traits_type::reference reference;
typedef typename allocator_traits_type::const_reference const_reference;
typedef typename impl_tree_t::size_type size_type;
typedef typename impl_tree_t::difference_type difference_type;
typedef container_detail::flat_tree_value_compare
< Pred
, containers_detail::select1st< std::pair<Key, T> >
, std::pair<Key, T> > value_compare;
typedef Pred key_compare;
typedef typename containers_detail::
get_flat_tree_iterators<pointer>::iterator iterator;
typedef typename containers_detail::
get_flat_tree_iterators<pointer>::const_iterator const_iterator;
typedef typename containers_detail::
, container_detail::select1st< std::pair<Key, T> >
, std::pair<Key, T> > value_compare;
typedef Pred key_compare;
typedef typename container_detail::
get_flat_tree_iterators<pointer>::iterator iterator;
typedef typename container_detail::
get_flat_tree_iterators<pointer>::const_iterator const_iterator;
typedef typename container_detail::
get_flat_tree_iterators
<pointer>::reverse_iterator reverse_iterator;
typedef typename containers_detail::
<pointer>::reverse_iterator reverse_iterator;
typedef typename container_detail::
get_flat_tree_iterators
<pointer>::const_reverse_iterator const_reverse_iterator;
typedef typename impl_tree_t::size_type size_type;
typedef typename impl_tree_t::difference_type difference_type;
typedef A allocator_type;
typedef A stored_allocator_type;
<pointer>::const_reverse_iterator const_reverse_iterator;
typedef A allocator_type;
typedef A stored_allocator_type;
public:
//! <b>Effects</b>: Default constructs an empty flat_map.
//!
//! <b>Complexity</b>: Constant.
flat_map()
: m_flat_tree() {}
//! <b>Effects</b>: Constructs an empty flat_map using the specified
//! comparison object and allocator.
//!
//! <b>Complexity</b>: Constant.
explicit flat_map(const Pred& comp = Pred(), const allocator_type& a = allocator_type())
: m_flat_tree(comp, force<impl_allocator_type>(a)) {}
explicit flat_map(const Pred& comp, const allocator_type& a = allocator_type())
: m_flat_tree(comp, container_detail::force<impl_allocator_type>(a)) {}
//! <b>Effects</b>: Constructs an empty flat_map using the specified comparison object and
//! allocator, and inserts elements from the range [first ,last ).
@@ -171,7 +189,7 @@ class flat_map
template <class InputIterator>
flat_map(InputIterator first, InputIterator last, const Pred& comp = Pred(),
const allocator_type& a = allocator_type())
: m_flat_tree(comp, force<impl_allocator_type>(a))
: m_flat_tree(comp, container_detail::force<impl_allocator_type>(a))
{ m_flat_tree.insert_unique(first, last); }
//! <b>Effects</b>: Constructs an empty flat_map using the specified comparison object and
@@ -224,27 +242,27 @@ class flat_map
//!
//! <b>Complexity</b>: Constant.
key_compare key_comp() const
{ return force<key_compare>(m_flat_tree.key_comp()); }
{ return container_detail::force<key_compare>(m_flat_tree.key_comp()); }
//! <b>Effects</b>: Returns an object of value_compare constructed out
//! of the comparison object.
//!
//! <b>Complexity</b>: Constant.
value_compare value_comp() const
{ return value_compare(force<key_compare>(m_flat_tree.key_comp())); }
{ return value_compare(container_detail::force<key_compare>(m_flat_tree.key_comp())); }
//! <b>Effects</b>: Returns a copy of the Allocator that
//! was passed to the object's constructor.
//!
//! <b>Complexity</b>: Constant.
allocator_type get_allocator() const
{ return force<allocator_type>(m_flat_tree.get_allocator()); }
{ return container_detail::force<allocator_type>(m_flat_tree.get_allocator()); }
const stored_allocator_type &get_stored_allocator() const
{ return force<stored_allocator_type>(m_flat_tree.get_stored_allocator()); }
{ return container_detail::force<stored_allocator_type>(m_flat_tree.get_stored_allocator()); }
stored_allocator_type &get_stored_allocator()
{ return force<stored_allocator_type>(m_flat_tree.get_stored_allocator()); }
{ return container_detail::force<stored_allocator_type>(m_flat_tree.get_stored_allocator()); }
//! <b>Effects</b>: Returns an iterator to the first element contained in the container.
//!
@@ -252,7 +270,7 @@ class flat_map
//!
//! <b>Complexity</b>: Constant.
iterator begin()
{ return force_copy<iterator>(m_flat_tree.begin()); }
{ return container_detail::force_copy<iterator>(m_flat_tree.begin()); }
//! <b>Effects</b>: Returns a const_iterator to the first element contained in the container.
//!
@@ -260,7 +278,7 @@ class flat_map
//!
//! <b>Complexity</b>: Constant.
const_iterator begin() const
{ return force<const_iterator>(m_flat_tree.begin()); }
{ return container_detail::force<const_iterator>(m_flat_tree.begin()); }
//! <b>Effects</b>: Returns a const_iterator to the first element contained in the container.
//!
@@ -268,7 +286,7 @@ class flat_map
//!
//! <b>Complexity</b>: Constant.
const_iterator cbegin() const
{ return force<const_iterator>(m_flat_tree.cbegin()); }
{ return container_detail::force<const_iterator>(m_flat_tree.cbegin()); }
//! <b>Effects</b>: Returns an iterator to the end of the container.
//!
@@ -276,7 +294,7 @@ class flat_map
//!
//! <b>Complexity</b>: Constant.
iterator end()
{ return force_copy<iterator>(m_flat_tree.end()); }
{ return container_detail::force_copy<iterator>(m_flat_tree.end()); }
//! <b>Effects</b>: Returns a const_iterator to the end of the container.
//!
@@ -284,7 +302,7 @@ class flat_map
//!
//! <b>Complexity</b>: Constant.
const_iterator end() const
{ return force<const_iterator>(m_flat_tree.end()); }
{ return container_detail::force<const_iterator>(m_flat_tree.end()); }
//! <b>Effects</b>: Returns a const_iterator to the end of the container.
//!
@@ -292,7 +310,7 @@ class flat_map
//!
//! <b>Complexity</b>: Constant.
const_iterator cend() const
{ return force<const_iterator>(m_flat_tree.cend()); }
{ return container_detail::force<const_iterator>(m_flat_tree.cend()); }
//! <b>Effects</b>: Returns a reverse_iterator pointing to the beginning
//! of the reversed container.
@@ -301,7 +319,7 @@ class flat_map
//!
//! <b>Complexity</b>: Constant.
reverse_iterator rbegin()
{ return force<reverse_iterator>(m_flat_tree.rbegin()); }
{ return container_detail::force<reverse_iterator>(m_flat_tree.rbegin()); }
//! <b>Effects</b>: Returns a const_reverse_iterator pointing to the beginning
//! of the reversed container.
@@ -310,7 +328,7 @@ class flat_map
//!
//! <b>Complexity</b>: Constant.
const_reverse_iterator rbegin() const
{ return force<const_reverse_iterator>(m_flat_tree.rbegin()); }
{ return container_detail::force<const_reverse_iterator>(m_flat_tree.rbegin()); }
//! <b>Effects</b>: Returns a const_reverse_iterator pointing to the beginning
//! of the reversed container.
@@ -319,7 +337,7 @@ class flat_map
//!
//! <b>Complexity</b>: Constant.
const_reverse_iterator crbegin() const
{ return force<const_reverse_iterator>(m_flat_tree.crbegin()); }
{ return container_detail::force<const_reverse_iterator>(m_flat_tree.crbegin()); }
//! <b>Effects</b>: Returns a reverse_iterator pointing to the end
//! of the reversed container.
@@ -328,7 +346,7 @@ class flat_map
//!
//! <b>Complexity</b>: Constant.
reverse_iterator rend()
{ return force<reverse_iterator>(m_flat_tree.rend()); }
{ return container_detail::force<reverse_iterator>(m_flat_tree.rend()); }
//! <b>Effects</b>: Returns a const_reverse_iterator pointing to the end
//! of the reversed container.
@@ -337,7 +355,7 @@ class flat_map
//!
//! <b>Complexity</b>: Constant.
const_reverse_iterator rend() const
{ return force<const_reverse_iterator>(m_flat_tree.rend()); }
{ return container_detail::force<const_reverse_iterator>(m_flat_tree.rend()); }
//! <b>Effects</b>: Returns a const_reverse_iterator pointing to the end
//! of the reversed container.
@@ -346,7 +364,7 @@ class flat_map
//!
//! <b>Complexity</b>: Constant.
const_reverse_iterator crend() const
{ return force<const_reverse_iterator>(m_flat_tree.crend()); }
{ return container_detail::force<const_reverse_iterator>(m_flat_tree.crend()); }
//! <b>Effects</b>: Returns true if the container contains no elements.
//!
@@ -372,20 +390,14 @@ class flat_map
size_type max_size() const
{ return m_flat_tree.max_size(); }
#if defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
//! Effects: If there is no key equivalent to x in the flat_map, inserts
//! value_type(x, T()) into the flat_map.
//!
//! Returns: A reference to the mapped_type corresponding to x in *this.
//!
//! Complexity: Logarithmic.
T &operator[](const key_type& k)
{
iterator i = lower_bound(k);
// i->first is greater than or equivalent to k.
if (i == end() || key_comp()(k, (*i).first))
i = insert(i, value_type(k, T()));
return (*i).second;
}
mapped_type &operator[](const key_type& k);
//! Effects: If there is no key equivalent to x in the flat_map, inserts
//! value_type(move(x), T()) into the flat_map (the key is move-constructed)
@@ -393,15 +405,11 @@ class flat_map
//! Returns: A reference to the mapped_type corresponding to x in *this.
//!
//! Complexity: Logarithmic.
T &operator[](BOOST_RV_REF(key_type) mk)
{
key_type &k = mk;
iterator i = lower_bound(k);
// i->first is greater than or equivalent to k.
if (i == end() || key_comp()(k, (*i).first))
i = insert(i, value_type(boost::move(k), boost::move(T())));
return (*i).second;
}
mapped_type &operator[](key_type &&k) ;
#else
BOOST_MOVE_CONVERSION_AWARE_CATCH( operator[] , key_type, mapped_type&, priv_subscript)
#endif
//! Returns: A reference to the element whose key is equivalent to x.
//! Throws: An exception object of type out_of_range if no such element is present.
@@ -448,8 +456,8 @@ class flat_map
//!
//! <b>Note</b>: If an element it's inserted it might invalidate elements.
std::pair<iterator,bool> insert(const value_type& x)
{ return force<std::pair<iterator,bool> >(
m_flat_tree.insert_unique(force<impl_value_type>(x))); }
{ return container_detail::force<std::pair<iterator,bool> >(
m_flat_tree.insert_unique(container_detail::force<impl_value_type>(x))); }
//! <b>Effects</b>: Inserts a new value_type move constructed from the pair if and
//! only if there is no element in the container with key equivalent to the key of x.
@@ -463,8 +471,8 @@ class flat_map
//!
//! <b>Note</b>: If an element it's inserted it might invalidate elements.
std::pair<iterator,bool> insert(BOOST_RV_REF(value_type) x)
{ return force<std::pair<iterator,bool> >(
m_flat_tree.insert_unique(boost::move(force<impl_value_type>(x)))); }
{ return container_detail::force<std::pair<iterator,bool> >(
m_flat_tree.insert_unique(boost::move(container_detail::force<impl_value_type>(x)))); }
//! <b>Effects</b>: Inserts a new value_type move constructed from the pair if and
//! only if there is no element in the container with key equivalent to the key of x.
@@ -479,7 +487,7 @@ class flat_map
//! <b>Note</b>: If an element it's inserted it might invalidate elements.
std::pair<iterator,bool> insert(BOOST_RV_REF(impl_value_type) x)
{
return force<std::pair<iterator,bool> >
return container_detail::force<std::pair<iterator,bool> >
(m_flat_tree.insert_unique(boost::move(x)));
}
@@ -495,8 +503,8 @@ class flat_map
//!
//! <b>Note</b>: If an element it's inserted it might invalidate elements.
iterator insert(const_iterator position, const value_type& x)
{ return force_copy<iterator>(
m_flat_tree.insert_unique(force<impl_const_iterator>(position), force<impl_value_type>(x))); }
{ return container_detail::force_copy<iterator>(
m_flat_tree.insert_unique(container_detail::force<impl_const_iterator>(position), container_detail::force<impl_value_type>(x))); }
//! <b>Effects</b>: Inserts an element move constructed from x in the container.
//! p is a hint pointing to where the insert should start to search.
@@ -508,8 +516,8 @@ class flat_map
//!
//! <b>Note</b>: If an element it's inserted it might invalidate elements.
iterator insert(const_iterator position, BOOST_RV_REF(value_type) x)
{ return force_copy<iterator>(
m_flat_tree.insert_unique(force<impl_const_iterator>(position), boost::move(force<impl_value_type>(x)))); }
{ return container_detail::force_copy<iterator>(
m_flat_tree.insert_unique(container_detail::force<impl_const_iterator>(position), boost::move(container_detail::force<impl_value_type>(x)))); }
//! <b>Effects</b>: Inserts an element move constructed from x in the container.
//! p is a hint pointing to where the insert should start to search.
@@ -522,8 +530,8 @@ class flat_map
//! <b>Note</b>: If an element it's inserted it might invalidate elements.
iterator insert(const_iterator position, BOOST_RV_REF(impl_value_type) x)
{
return force_copy<iterator>(
m_flat_tree.insert_unique(force<impl_const_iterator>(position), boost::move(x)));
return container_detail::force_copy<iterator>(
m_flat_tree.insert_unique(container_detail::force<impl_const_iterator>(position), boost::move(x)));
}
//! <b>Requires</b>: first, last are not iterators into *this.
@@ -539,7 +547,7 @@ class flat_map
void insert(InputIterator first, InputIterator last)
{ m_flat_tree.insert_unique(first, last); }
#if defined(BOOST_CONTAINERS_PERFECT_FORWARDING) || defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
#if defined(BOOST_CONTAINER_PERFECT_FORWARDING) || defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
//! <b>Effects</b>: Inserts an object of type T constructed with
//! std::forward<Args>(args)... if and only if there is no element in the container
@@ -555,7 +563,7 @@ class flat_map
//! <b>Note</b>: If an element it's inserted it might invalidate elements.
template <class... Args>
iterator emplace(Args&&... args)
{ return force_copy<iterator>(m_flat_tree.emplace_unique(boost::forward<Args>(args)...)); }
{ return container_detail::force_copy<iterator>(m_flat_tree.emplace_unique(boost::forward<Args>(args)...)); }
//! <b>Effects</b>: Inserts an object of type T constructed with
//! std::forward<Args>(args)... in the container if and only if there is
@@ -571,36 +579,27 @@ class flat_map
//! <b>Note</b>: If an element it's inserted it might invalidate elements.
template <class... Args>
iterator emplace_hint(const_iterator hint, Args&&... args)
{ return force_copy<iterator>(m_flat_tree.emplace_hint_unique(force<impl_const_iterator>(hint), boost::forward<Args>(args)...)); }
{ return container_detail::force_copy<iterator>(m_flat_tree.emplace_hint_unique(container_detail::force<impl_const_iterator>(hint), boost::forward<Args>(args)...)); }
#else //#ifdef BOOST_CONTAINERS_PERFECT_FORWARDING
#else //#ifdef BOOST_CONTAINER_PERFECT_FORWARDING
iterator emplace()
{ return force_copy<iterator>(m_flat_tree.emplace_unique()); }
iterator emplace_hint(const_iterator hint)
{ return force_copy<iterator>(m_flat_tree.emplace_hint_unique(force<impl_const_iterator>(hint))); }
#define BOOST_PP_LOCAL_MACRO(n) \
template<BOOST_PP_ENUM_PARAMS(n, class P)> \
iterator emplace(BOOST_PP_ENUM(n, BOOST_CONTAINERS_PP_PARAM_LIST, _)) \
{ \
return force_copy<iterator>(m_flat_tree.emplace_unique \
(BOOST_PP_ENUM(n, BOOST_CONTAINERS_PP_PARAM_FORWARD, _))); \
} \
\
template<BOOST_PP_ENUM_PARAMS(n, class P)> \
iterator emplace_hint(const_iterator hint, BOOST_PP_ENUM(n, BOOST_CONTAINERS_PP_PARAM_LIST, _)) \
{ \
return force_copy<iterator>(m_flat_tree.emplace_hint_unique \
(force<impl_const_iterator>(hint), \
BOOST_PP_ENUM(n, BOOST_CONTAINERS_PP_PARAM_FORWARD, _))); \
} \
#define BOOST_PP_LOCAL_MACRO(n) \
BOOST_PP_EXPR_IF(n, template<) BOOST_PP_ENUM_PARAMS(n, class P) BOOST_PP_EXPR_IF(n, >) \
iterator emplace(BOOST_PP_ENUM(n, BOOST_CONTAINER_PP_PARAM_LIST, _)) \
{ return container_detail::force_copy<iterator>(m_flat_tree.emplace_unique \
(BOOST_PP_ENUM(n, BOOST_CONTAINER_PP_PARAM_FORWARD, _))); } \
\
BOOST_PP_EXPR_IF(n, template<) BOOST_PP_ENUM_PARAMS(n, class P) BOOST_PP_EXPR_IF(n, >) \
iterator emplace_hint(const_iterator hint \
BOOST_PP_ENUM_TRAILING(n, BOOST_CONTAINER_PP_PARAM_LIST, _)) \
{ return container_detail::force_copy<iterator>(m_flat_tree.emplace_hint_unique \
(container_detail::force<impl_const_iterator>(hint) \
BOOST_PP_ENUM_TRAILING(n, BOOST_CONTAINER_PP_PARAM_FORWARD, _))); } \
//!
#define BOOST_PP_LOCAL_LIMITS (1, BOOST_CONTAINERS_MAX_CONSTRUCTOR_PARAMETERS)
#define BOOST_PP_LOCAL_LIMITS (0, BOOST_CONTAINER_MAX_CONSTRUCTOR_PARAMETERS)
#include BOOST_PP_LOCAL_ITERATE()
#endif //#ifdef BOOST_CONTAINERS_PERFECT_FORWARDING
#endif //#ifdef BOOST_CONTAINER_PERFECT_FORWARDING
//! <b>Effects</b>: Erases the element pointed to by position.
//!
@@ -613,7 +612,7 @@ class flat_map
//! <b>Note</b>: Invalidates elements with keys
//! not less than the erased element.
iterator erase(const_iterator position)
{ return force_copy<iterator>(m_flat_tree.erase(force<impl_const_iterator>(position))); }
{ return container_detail::force_copy<iterator>(m_flat_tree.erase(container_detail::force<impl_const_iterator>(position))); }
//! <b>Effects</b>: Erases all elements in the container with key equivalent to x.
//!
@@ -633,7 +632,7 @@ class flat_map
//! <b>Complexity</b>: Logarithmic search time plus erasure time
//! linear to the elements with bigger keys.
iterator erase(const_iterator first, const_iterator last)
{ return force_copy<iterator>(m_flat_tree.erase(force<impl_const_iterator>(first), force<impl_const_iterator>(last))); }
{ return container_detail::force_copy<iterator>(m_flat_tree.erase(container_detail::force<impl_const_iterator>(first), container_detail::force<impl_const_iterator>(last))); }
//! <b>Effects</b>: erase(a.begin(),a.end()).
//!
@@ -657,14 +656,14 @@ class flat_map
//!
//! <b>Complexity</b>: Logarithmic.
iterator find(const key_type& x)
{ return force_copy<iterator>(m_flat_tree.find(x)); }
{ return container_detail::force_copy<iterator>(m_flat_tree.find(x)); }
//! <b>Returns</b>: A const_iterator pointing to an element with the key
//! equivalent to x, or end() if such an element is not found.
//!
//! <b>Complexity</b>: Logarithmic.s
const_iterator find(const key_type& x) const
{ return force<const_iterator>(m_flat_tree.find(x)); }
{ return container_detail::force<const_iterator>(m_flat_tree.find(x)); }
//! <b>Returns</b>: The number of elements with key equivalent to x.
//!
@@ -677,40 +676,40 @@ class flat_map
//!
//! <b>Complexity</b>: Logarithmic
iterator lower_bound(const key_type& x)
{ return force_copy<iterator>(m_flat_tree.lower_bound(x)); }
{ return container_detail::force_copy<iterator>(m_flat_tree.lower_bound(x)); }
//! <b>Returns</b>: A const iterator pointing to the first element with key not
//! less than k, or a.end() if such an element is not found.
//!
//! <b>Complexity</b>: Logarithmic
const_iterator lower_bound(const key_type& x) const
{ return force<const_iterator>(m_flat_tree.lower_bound(x)); }
{ return container_detail::force<const_iterator>(m_flat_tree.lower_bound(x)); }
//! <b>Returns</b>: An iterator pointing to the first element with key not less
//! than x, or end() if such an element is not found.
//!
//! <b>Complexity</b>: Logarithmic
iterator upper_bound(const key_type& x)
{ return force_copy<iterator>(m_flat_tree.upper_bound(x)); }
{ return container_detail::force_copy<iterator>(m_flat_tree.upper_bound(x)); }
//! <b>Returns</b>: A const iterator pointing to the first element with key not
//! less than x, or end() if such an element is not found.
//!
//! <b>Complexity</b>: Logarithmic
const_iterator upper_bound(const key_type& x) const
{ return force<const_iterator>(m_flat_tree.upper_bound(x)); }
{ return container_detail::force<const_iterator>(m_flat_tree.upper_bound(x)); }
//! <b>Effects</b>: Equivalent to std::make_pair(this->lower_bound(k), this->upper_bound(k)).
//!
//! <b>Complexity</b>: Logarithmic
std::pair<iterator,iterator> equal_range(const key_type& x)
{ return force<std::pair<iterator,iterator> >(m_flat_tree.equal_range(x)); }
{ return container_detail::force<std::pair<iterator,iterator> >(m_flat_tree.equal_range(x)); }
//! <b>Effects</b>: Equivalent to std::make_pair(this->lower_bound(k), this->upper_bound(k)).
//!
//! <b>Complexity</b>: Logarithmic
std::pair<const_iterator,const_iterator> equal_range(const key_type& x) const
{ return force<std::pair<const_iterator,const_iterator> >(m_flat_tree.equal_range(x)); }
{ return container_detail::force<std::pair<const_iterator,const_iterator> >(m_flat_tree.equal_range(x)); }
//! <b>Effects</b>: Number of elements for which memory has been allocated.
//! capacity() is always greater than or equal to size().
@@ -740,6 +739,29 @@ class flat_map
template <class K1, class T1, class C1, class A1>
friend bool operator< (const flat_map<K1, T1, C1, A1>&,
const flat_map<K1, T1, C1, A1>&);
private:
mapped_type &priv_subscript(const key_type& k)
{
iterator i = lower_bound(k);
// i->first is greater than or equivalent to k.
if (i == end() || key_comp()(k, (*i).first)){
container_detail::value_init<mapped_type> m;
i = insert(i, impl_value_type(k, ::boost::move(m.m_t)));
}
return (*i).second;
}
mapped_type &priv_subscript(BOOST_RV_REF(key_type) mk)
{
key_type &k = mk;
iterator i = lower_bound(k);
// i->first is greater than or equivalent to k.
if (i == end() || key_comp()(k, (*i).first)){
container_detail::value_init<mapped_type> m;
i = insert(i, impl_value_type(boost::move(k), ::boost::move(m.m_t)));
}
return (*i).second;
}
/// @endcond
};
@@ -833,18 +855,18 @@ class flat_multimap
/// @cond
private:
BOOST_COPYABLE_AND_MOVABLE(flat_multimap)
typedef containers_detail::flat_tree<Key,
typedef container_detail::flat_tree<Key,
std::pair<Key, T>,
containers_detail::select1st< std::pair<Key, T> >,
container_detail::select1st< std::pair<Key, T> >,
Pred,
A> tree_t;
//This is the real tree stored here. It's based on a movable pair
typedef containers_detail::flat_tree<Key,
containers_detail::pair<Key, T>,
containers_detail::select1st<containers_detail::pair<Key, T> >,
typedef container_detail::flat_tree<Key,
container_detail::pair<Key, T>,
container_detail::select1st<container_detail::pair<Key, T> >,
Pred,
typename A::template
rebind<containers_detail::pair<Key, T> >::other> impl_tree_t;
typename allocator_traits<A>::template portable_rebind_alloc
<container_detail::pair<Key, T> >::type> impl_tree_t;
impl_tree_t m_flat_tree; // flat tree representing flat_map
typedef typename impl_tree_t::value_type impl_value_type;
@@ -858,56 +880,55 @@ class flat_multimap
typedef typename impl_tree_t::reverse_iterator impl_reverse_iterator;
typedef typename impl_tree_t::const_reverse_iterator impl_const_reverse_iterator;
typedef typename impl_tree_t::allocator_type impl_allocator_type;
typedef allocator_traits<A> allocator_traits_type;
template<class D, class S>
static D &force(const S &s)
{ return *const_cast<D*>((reinterpret_cast<const D*>(&s))); }
template<class D, class S>
static D force_copy(S s)
{
value_type *vp = reinterpret_cast<value_type *>(&*s);
return D(vp);
}
/// @endcond
public:
// typedefs:
typedef typename impl_tree_t::key_type key_type;
typedef T mapped_type;
typedef typename std::pair<key_type, mapped_type> value_type;
typedef typename A::pointer pointer;
typedef typename A::const_pointer const_pointer;
typedef typename A::reference reference;
typedef typename A::const_reference const_reference;
typedef containers_detail::flat_tree_value_compare
typedef Key key_type;
typedef T mapped_type;
typedef Pred key_compare;
typedef typename std::pair<key_type, mapped_type> value_type;
typedef typename allocator_traits_type::pointer pointer;
typedef typename allocator_traits_type::const_pointer const_pointer;
typedef typename allocator_traits_type::reference reference;
typedef typename allocator_traits_type::const_reference const_reference;
typedef typename impl_tree_t::size_type size_type;
typedef typename impl_tree_t::difference_type difference_type;
typedef container_detail::flat_tree_value_compare
< Pred
, containers_detail::select1st< std::pair<Key, T> >
, std::pair<Key, T> > value_compare;
typedef Pred key_compare;
typedef typename containers_detail::
get_flat_tree_iterators<pointer>::iterator iterator;
typedef typename containers_detail::
get_flat_tree_iterators<pointer>::const_iterator const_iterator;
typedef typename containers_detail::
, container_detail::select1st< std::pair<Key, T> >
, std::pair<Key, T> > value_compare;
typedef typename container_detail::
get_flat_tree_iterators<pointer>::iterator iterator;
typedef typename container_detail::
get_flat_tree_iterators<pointer>::const_iterator const_iterator;
typedef typename container_detail::
get_flat_tree_iterators
<pointer>::reverse_iterator reverse_iterator;
typedef typename containers_detail::
<pointer>::reverse_iterator reverse_iterator;
typedef typename container_detail::
get_flat_tree_iterators
<pointer>::const_reverse_iterator const_reverse_iterator;
typedef typename impl_tree_t::size_type size_type;
typedef typename impl_tree_t::difference_type difference_type;
typedef A allocator_type;
typedef A stored_allocator_type;
<pointer>::const_reverse_iterator const_reverse_iterator;
typedef A allocator_type;
//Non-standard extension
typedef A stored_allocator_type;
//! <b>Effects</b>: Default constructs an empty flat_map.
//!
//! <b>Complexity</b>: Constant.
flat_multimap()
: m_flat_tree() {}
//! <b>Effects</b>: Constructs an empty flat_multimap using the specified comparison
//! object and allocator.
//!
//! <b>Complexity</b>: Constant.
explicit flat_multimap(const Pred& comp = Pred(),
explicit flat_multimap(const Pred& comp,
const allocator_type& a = allocator_type())
: m_flat_tree(comp, force<impl_allocator_type>(a)) { }
: m_flat_tree(comp, container_detail::force<impl_allocator_type>(a)) { }
//! <b>Effects</b>: Constructs an empty flat_multimap using the specified comparison object
//! and allocator, and inserts elements from the range [first ,last ).
@@ -918,7 +939,7 @@ class flat_multimap
flat_multimap(InputIterator first, InputIterator last,
const Pred& comp = Pred(),
const allocator_type& a = allocator_type())
: m_flat_tree(comp, force<impl_allocator_type>(a))
: m_flat_tree(comp, container_detail::force<impl_allocator_type>(a))
{ m_flat_tree.insert_equal(first, last); }
//! <b>Effects</b>: Constructs an empty flat_multimap using the specified comparison object and
@@ -967,27 +988,27 @@ class flat_multimap
//!
//! <b>Complexity</b>: Constant.
key_compare key_comp() const
{ return force<key_compare>(m_flat_tree.key_comp()); }
{ return container_detail::force<key_compare>(m_flat_tree.key_comp()); }
//! <b>Effects</b>: Returns an object of value_compare constructed out
//! of the comparison object.
//!
//! <b>Complexity</b>: Constant.
value_compare value_comp() const
{ return value_compare(force<key_compare>(m_flat_tree.key_comp())); }
{ return value_compare(container_detail::force<key_compare>(m_flat_tree.key_comp())); }
//! <b>Effects</b>: Returns a copy of the Allocator that
//! was passed to the object's constructor.
//!
//! <b>Complexity</b>: Constant.
allocator_type get_allocator() const
{ return force<allocator_type>(m_flat_tree.get_allocator()); }
{ return container_detail::force<allocator_type>(m_flat_tree.get_allocator()); }
const stored_allocator_type &get_stored_allocator() const
{ return force<stored_allocator_type>(m_flat_tree.get_stored_allocator()); }
{ return container_detail::force<stored_allocator_type>(m_flat_tree.get_stored_allocator()); }
stored_allocator_type &get_stored_allocator()
{ return force<stored_allocator_type>(m_flat_tree.get_stored_allocator()); }
{ return container_detail::force<stored_allocator_type>(m_flat_tree.get_stored_allocator()); }
//! <b>Effects</b>: Returns an iterator to the first element contained in the container.
//!
@@ -995,7 +1016,7 @@ class flat_multimap
//!
//! <b>Complexity</b>: Constant.
iterator begin()
{ return force_copy<iterator>(m_flat_tree.begin()); }
{ return container_detail::force_copy<iterator>(m_flat_tree.begin()); }
//! <b>Effects</b>: Returns a const_iterator to the first element contained in the container.
//!
@@ -1003,7 +1024,7 @@ class flat_multimap
//!
//! <b>Complexity</b>: Constant.
const_iterator begin() const
{ return force<const_iterator>(m_flat_tree.begin()); }
{ return container_detail::force<const_iterator>(m_flat_tree.begin()); }
//! <b>Effects</b>: Returns an iterator to the end of the container.
//!
@@ -1011,7 +1032,7 @@ class flat_multimap
//!
//! <b>Complexity</b>: Constant.
iterator end()
{ return force_copy<iterator>(m_flat_tree.end()); }
{ return container_detail::force_copy<iterator>(m_flat_tree.end()); }
//! <b>Effects</b>: Returns a const_iterator to the end of the container.
//!
@@ -1019,7 +1040,7 @@ class flat_multimap
//!
//! <b>Complexity</b>: Constant.
const_iterator end() const
{ return force<const_iterator>(m_flat_tree.end()); }
{ return container_detail::force<const_iterator>(m_flat_tree.end()); }
//! <b>Effects</b>: Returns a reverse_iterator pointing to the beginning
//! of the reversed container.
@@ -1028,7 +1049,7 @@ class flat_multimap
//!
//! <b>Complexity</b>: Constant.
reverse_iterator rbegin()
{ return force<reverse_iterator>(m_flat_tree.rbegin()); }
{ return container_detail::force<reverse_iterator>(m_flat_tree.rbegin()); }
//! <b>Effects</b>: Returns a const_reverse_iterator pointing to the beginning
//! of the reversed container.
@@ -1037,7 +1058,7 @@ class flat_multimap
//!
//! <b>Complexity</b>: Constant.
const_reverse_iterator rbegin() const
{ return force<const_reverse_iterator>(m_flat_tree.rbegin()); }
{ return container_detail::force<const_reverse_iterator>(m_flat_tree.rbegin()); }
//! <b>Effects</b>: Returns a reverse_iterator pointing to the end
//! of the reversed container.
@@ -1046,7 +1067,7 @@ class flat_multimap
//!
//! <b>Complexity</b>: Constant.
reverse_iterator rend()
{ return force<reverse_iterator>(m_flat_tree.rend()); }
{ return container_detail::force<reverse_iterator>(m_flat_tree.rend()); }
//! <b>Effects</b>: Returns a const_reverse_iterator pointing to the end
//! of the reversed container.
@@ -1055,7 +1076,7 @@ class flat_multimap
//!
//! <b>Complexity</b>: Constant.
const_reverse_iterator rend() const
{ return force<const_reverse_iterator>(m_flat_tree.rend()); }
{ return container_detail::force<const_reverse_iterator>(m_flat_tree.rend()); }
//! <b>Effects</b>: Returns true if the container contains no elements.
//!
@@ -1098,7 +1119,7 @@ class flat_multimap
//!
//! <b>Note</b>: If an element it's inserted it might invalidate elements.
iterator insert(const value_type& x)
{ return force_copy<iterator>(m_flat_tree.insert_equal(force<impl_value_type>(x))); }
{ return container_detail::force_copy<iterator>(m_flat_tree.insert_equal(container_detail::force<impl_value_type>(x))); }
//! <b>Effects</b>: Inserts a new value move-constructed from x and returns
//! the iterator pointing to the newly inserted element.
@@ -1108,7 +1129,7 @@ class flat_multimap
//!
//! <b>Note</b>: If an element it's inserted it might invalidate elements.
iterator insert(BOOST_RV_REF(value_type) x)
{ return force_copy<iterator>(m_flat_tree.insert_equal(boost::move(x))); }
{ return container_detail::force_copy<iterator>(m_flat_tree.insert_equal(boost::move(x))); }
//! <b>Effects</b>: Inserts a new value move-constructed from x and returns
//! the iterator pointing to the newly inserted element.
@@ -1118,7 +1139,7 @@ class flat_multimap
//!
//! <b>Note</b>: If an element it's inserted it might invalidate elements.
iterator insert(BOOST_RV_REF(impl_value_type) x)
{ return force_copy<iterator>(m_flat_tree.insert_equal(boost::move(x))); }
{ return container_detail::force_copy<iterator>(m_flat_tree.insert_equal(boost::move(x))); }
//! <b>Effects</b>: Inserts a copy of x in the container.
//! p is a hint pointing to where the insert should start to search.
@@ -1132,7 +1153,7 @@ class flat_multimap
//!
//! <b>Note</b>: If an element it's inserted it might invalidate elements.
iterator insert(const_iterator position, const value_type& x)
{ return force_copy<iterator>(m_flat_tree.insert_equal(force<impl_const_iterator>(position), force<impl_value_type>(x))); }
{ return container_detail::force_copy<iterator>(m_flat_tree.insert_equal(container_detail::force<impl_const_iterator>(position), container_detail::force<impl_value_type>(x))); }
//! <b>Effects</b>: Inserts a value move constructed from x in the container.
//! p is a hint pointing to where the insert should start to search.
@@ -1147,8 +1168,8 @@ class flat_multimap
//! <b>Note</b>: If an element it's inserted it might invalidate elements.
iterator insert(const_iterator position, BOOST_RV_REF(value_type) x)
{
return force_copy<iterator>
(m_flat_tree.insert_equal(force<impl_const_iterator>(position)
return container_detail::force_copy<iterator>
(m_flat_tree.insert_equal(container_detail::force<impl_const_iterator>(position)
, boost::move(x)));
}
@@ -1165,8 +1186,8 @@ class flat_multimap
//! <b>Note</b>: If an element it's inserted it might invalidate elements.
iterator insert(const_iterator position, BOOST_RV_REF(impl_value_type) x)
{
return force_copy<iterator>(
m_flat_tree.insert_equal(force<impl_const_iterator>(position), boost::move(x)));
return container_detail::force_copy<iterator>(
m_flat_tree.insert_equal(container_detail::force<impl_const_iterator>(position), boost::move(x)));
}
//! <b>Requires</b>: first, last are not iterators into *this.
@@ -1181,7 +1202,7 @@ class flat_multimap
void insert(InputIterator first, InputIterator last)
{ m_flat_tree.insert_equal(first, last); }
#if defined(BOOST_CONTAINERS_PERFECT_FORWARDING) || defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
#if defined(BOOST_CONTAINER_PERFECT_FORWARDING) || defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
//! <b>Effects</b>: Inserts an object of type T constructed with
//! std::forward<Args>(args)... and returns the iterator pointing to the
@@ -1193,7 +1214,7 @@ class flat_multimap
//! <b>Note</b>: If an element it's inserted it might invalidate elements.
template <class... Args>
iterator emplace(Args&&... args)
{ return force_copy<iterator>(m_flat_tree.emplace_equal(boost::forward<Args>(args)...)); }
{ return container_detail::force_copy<iterator>(m_flat_tree.emplace_equal(boost::forward<Args>(args)...)); }
//! <b>Effects</b>: Inserts an object of type T constructed with
//! std::forward<Args>(args)... in the container.
@@ -1210,38 +1231,29 @@ class flat_multimap
template <class... Args>
iterator emplace_hint(const_iterator hint, Args&&... args)
{
return force_copy<iterator>(m_flat_tree.emplace_hint_equal
(force<impl_const_iterator>(hint), boost::forward<Args>(args)...));
return container_detail::force_copy<iterator>(m_flat_tree.emplace_hint_equal
(container_detail::force<impl_const_iterator>(hint), boost::forward<Args>(args)...));
}
#else //#ifdef BOOST_CONTAINERS_PERFECT_FORWARDING
#else //#ifdef BOOST_CONTAINER_PERFECT_FORWARDING
iterator emplace()
{ return force_copy<iterator>(m_flat_tree.emplace_equal()); }
iterator emplace_hint(const_iterator hint)
{ return force_copy<iterator>(m_flat_tree.emplace_hint_equal(force<impl_const_iterator>(hint))); }
#define BOOST_PP_LOCAL_MACRO(n) \
template<BOOST_PP_ENUM_PARAMS(n, class P)> \
iterator emplace(BOOST_PP_ENUM(n, BOOST_CONTAINERS_PP_PARAM_LIST, _)) \
{ \
return force_copy<iterator>(m_flat_tree.emplace_equal \
(BOOST_PP_ENUM(n, BOOST_CONTAINERS_PP_PARAM_FORWARD, _))); \
} \
\
template<BOOST_PP_ENUM_PARAMS(n, class P)> \
iterator emplace_hint(const_iterator hint, BOOST_PP_ENUM(n, BOOST_CONTAINERS_PP_PARAM_LIST, _)) \
{ \
return force_copy<iterator>(m_flat_tree.emplace_hint_equal \
(force<impl_const_iterator>(hint), \
BOOST_PP_ENUM(n, BOOST_CONTAINERS_PP_PARAM_FORWARD, _))); \
} \
#define BOOST_PP_LOCAL_MACRO(n) \
BOOST_PP_EXPR_IF(n, template<) BOOST_PP_ENUM_PARAMS(n, class P) BOOST_PP_EXPR_IF(n, >) \
iterator emplace(BOOST_PP_ENUM(n, BOOST_CONTAINER_PP_PARAM_LIST, _)) \
{ return container_detail::force_copy<iterator>(m_flat_tree.emplace_equal \
(BOOST_PP_ENUM(n, BOOST_CONTAINER_PP_PARAM_FORWARD, _))); } \
\
BOOST_PP_EXPR_IF(n, template<) BOOST_PP_ENUM_PARAMS(n, class P) BOOST_PP_EXPR_IF(n, >) \
iterator emplace_hint(const_iterator hint \
BOOST_PP_ENUM_TRAILING(n, BOOST_CONTAINER_PP_PARAM_LIST, _)) \
{ return container_detail::force_copy<iterator>(m_flat_tree.emplace_hint_equal \
(container_detail::force<impl_const_iterator>(hint) \
BOOST_PP_ENUM_TRAILING(n, BOOST_CONTAINER_PP_PARAM_FORWARD, _))); } \
//!
#define BOOST_PP_LOCAL_LIMITS (1, BOOST_CONTAINERS_MAX_CONSTRUCTOR_PARAMETERS)
#define BOOST_PP_LOCAL_LIMITS (0, BOOST_CONTAINER_MAX_CONSTRUCTOR_PARAMETERS)
#include BOOST_PP_LOCAL_ITERATE()
#endif //#ifdef BOOST_CONTAINERS_PERFECT_FORWARDING
#endif //#ifdef BOOST_CONTAINER_PERFECT_FORWARDING
//! <b>Effects</b>: Erases the element pointed to by position.
//!
@@ -1254,7 +1266,7 @@ class flat_multimap
//! <b>Note</b>: Invalidates elements with keys
//! not less than the erased element.
iterator erase(const_iterator position)
{ return force_copy<iterator>(m_flat_tree.erase(force<impl_const_iterator>(position))); }
{ return container_detail::force_copy<iterator>(m_flat_tree.erase(container_detail::force<impl_const_iterator>(position))); }
//! <b>Effects</b>: Erases all elements in the container with key equivalent to x.
//!
@@ -1274,7 +1286,7 @@ class flat_multimap
//! <b>Complexity</b>: Logarithmic search time plus erasure time
//! linear to the elements with bigger keys.
iterator erase(const_iterator first, const_iterator last)
{ return force_copy<iterator>(m_flat_tree.erase(force<impl_const_iterator>(first), force<impl_const_iterator>(last))); }
{ return container_detail::force_copy<iterator>(m_flat_tree.erase(container_detail::force<impl_const_iterator>(first), container_detail::force<impl_const_iterator>(last))); }
//! <b>Effects</b>: erase(a.begin(),a.end()).
//!
@@ -1298,14 +1310,14 @@ class flat_multimap
//!
//! <b>Complexity</b>: Logarithmic.
iterator find(const key_type& x)
{ return force_copy<iterator>(m_flat_tree.find(x)); }
{ return container_detail::force_copy<iterator>(m_flat_tree.find(x)); }
//! <b>Returns</b>: An const_iterator pointing to an element with the key
//! equivalent to x, or end() if such an element is not found.
//!
//! <b>Complexity</b>: Logarithmic.
const_iterator find(const key_type& x) const
{ return force<const_iterator>(m_flat_tree.find(x)); }
{ return container_detail::force<const_iterator>(m_flat_tree.find(x)); }
//! <b>Returns</b>: The number of elements with key equivalent to x.
//!
@@ -1318,41 +1330,41 @@ class flat_multimap
//!
//! <b>Complexity</b>: Logarithmic
iterator lower_bound(const key_type& x)
{return force_copy<iterator>(m_flat_tree.lower_bound(x)); }
{return container_detail::force_copy<iterator>(m_flat_tree.lower_bound(x)); }
//! <b>Returns</b>: A const iterator pointing to the first element with key
//! not less than k, or a.end() if such an element is not found.
//!
//! <b>Complexity</b>: Logarithmic
const_iterator lower_bound(const key_type& x) const
{ return force<const_iterator>(m_flat_tree.lower_bound(x)); }
{ return container_detail::force<const_iterator>(m_flat_tree.lower_bound(x)); }
//! <b>Returns</b>: An iterator pointing to the first element with key not less
//! than x, or end() if such an element is not found.
//!
//! <b>Complexity</b>: Logarithmic
iterator upper_bound(const key_type& x)
{return force_copy<iterator>(m_flat_tree.upper_bound(x)); }
{return container_detail::force_copy<iterator>(m_flat_tree.upper_bound(x)); }
//! <b>Returns</b>: A const iterator pointing to the first element with key
//! not less than x, or end() if such an element is not found.
//!
//! <b>Complexity</b>: Logarithmic
const_iterator upper_bound(const key_type& x) const
{ return force<const_iterator>(m_flat_tree.upper_bound(x)); }
{ return container_detail::force<const_iterator>(m_flat_tree.upper_bound(x)); }
//! <b>Effects</b>: Equivalent to std::make_pair(this->lower_bound(k), this->upper_bound(k)).
//!
//! <b>Complexity</b>: Logarithmic
std::pair<iterator,iterator> equal_range(const key_type& x)
{ return force_copy<std::pair<iterator,iterator> >(m_flat_tree.equal_range(x)); }
{ return container_detail::force_copy<std::pair<iterator,iterator> >(m_flat_tree.equal_range(x)); }
//! <b>Effects</b>: Equivalent to std::make_pair(this->lower_bound(k), this->upper_bound(k)).
//!
//! <b>Complexity</b>: Logarithmic
std::pair<const_iterator,const_iterator>
equal_range(const key_type& x) const
{ return force_copy<std::pair<const_iterator,const_iterator> >(m_flat_tree.equal_range(x)); }
{ return container_detail::force_copy<std::pair<const_iterator,const_iterator> >(m_flat_tree.equal_range(x)); }
//! <b>Effects</b>: Number of elements for which memory has been allocated.
//! capacity() is always greater than or equal to size().
@@ -1440,4 +1452,4 @@ struct has_trivial_destructor_after_move< boost::container::flat_multimap<K, T,
#include <boost/container/detail/config_end.hpp>
#endif /* BOOST_CONTAINERS_FLAT_MAP_HPP */
#endif /* BOOST_CONTAINER_FLAT_MAP_HPP */