Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-07-14 08:27:35

0001 //////////////////////////////////////////////////////////////////////////////
0002 //
0003 // (C) Copyright Ion Gaztanaga 2005-2013. Distributed under the Boost
0004 // Software License, Version 1.0. (See accompanying file
0005 // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
0006 //
0007 // See http://www.boost.org/libs/container for documentation.
0008 //
0009 //////////////////////////////////////////////////////////////////////////////
0010 #ifndef BOOST_CONTAINER_FLAT_MAP_HPP
0011 #define BOOST_CONTAINER_FLAT_MAP_HPP
0012 
0013 #ifndef BOOST_CONFIG_HPP
0014 #  include <boost/config.hpp>
0015 #endif
0016 
0017 #if defined(BOOST_HAS_PRAGMA_ONCE)
0018 #  pragma once
0019 #endif
0020 
0021 #include <boost/container/detail/config_begin.hpp>
0022 #include <boost/container/detail/workaround.hpp>
0023 // container
0024 #include <boost/container/allocator_traits.hpp>
0025 #include <boost/container/container_fwd.hpp>
0026 #include <boost/container/new_allocator.hpp> //new_allocator
0027 #include <boost/container/throw_exception.hpp>
0028 // container/detail
0029 #include <boost/container/detail/flat_tree.hpp>
0030 #include <boost/container/detail/type_traits.hpp>
0031 #include <boost/container/detail/mpl.hpp>
0032 #include <boost/container/detail/algorithm.hpp> //equal()
0033 #include <boost/container/detail/container_or_allocator_rebind.hpp>
0034 #include <boost/container/detail/pair.hpp>
0035 // move
0036 #include <boost/move/utility_core.hpp>
0037 #include <boost/move/traits.hpp>
0038 // move/detail
0039 #if defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
0040 #include <boost/move/detail/fwd_macros.hpp>
0041 #endif
0042 #include <boost/move/detail/move_helpers.hpp>
0043 #include <boost/move/detail/force_ptr.hpp>
0044 // intrusive
0045 #include <boost/intrusive/detail/minimal_pair_header.hpp>      //pair
0046 #include <boost/intrusive/detail/minimal_less_equal_header.hpp>//less, equal
0047 
0048 
0049 #if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
0050 #include <initializer_list>
0051 #endif
0052 
0053 #if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
0054 #define BOOST_CONTAINER_STD_PAIR_IS_MOVABLE
0055 #endif
0056 
0057 //for C++03 compilers, were type-puning is the only option for std::pair
0058 //disable strict aliasing to reduce problems.
0059 #if defined(BOOST_GCC) && (BOOST_GCC >= 100000) && !defined(BOOST_CONTAINER_STD_PAIR_IS_MOVABLE)
0060 #pragma GCC push_options
0061 #pragma GCC optimize("no-strict-aliasing")
0062 #endif
0063 
0064 namespace boost {
0065 namespace container {
0066 
0067 #ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
0068 
0069 template <class Key, class T, class Compare, class AllocatorOrContainer>
0070 class flat_multimap;
0071 
0072 namespace dtl{
0073 
0074 #if defined(BOOST_CONTAINER_STD_PAIR_IS_MOVABLE)
0075 template<class D, class S>
0076 BOOST_CONTAINER_FORCEINLINE static D &force(S &s)
0077 {  return s; }
0078 
0079 template<class D, class S>
0080 BOOST_CONTAINER_FORCEINLINE static const D &force(const S &s)
0081 {  return s; }
0082 
0083 template<class D>
0084 BOOST_CONTAINER_FORCEINLINE static D force_copy(D s)
0085 {  return s; }
0086 
0087 #else //!BOOST_CONTAINER_DOXYGEN_INVOKED
0088 
0089 template<class D, class S>
0090 BOOST_CONTAINER_FORCEINLINE static D &force(S &s)
0091 {  return *move_detail::launder_cast<D*>(&s); }
0092 
0093 template<class D, class S>
0094 BOOST_CONTAINER_FORCEINLINE static const D &force(const S &s)
0095 {  return *move_detail::launder_cast<const D*>(&s); }
0096 
0097 template<class D, class S>
0098 BOOST_CONTAINER_FORCEINLINE static D force_copy(const S &s)
0099 {
0100    const D *const vp = move_detail::launder_cast<const D *>(&s);
0101    D ret_val(*vp);
0102    return ret_val;
0103 }
0104 #endif   //BOOST_CONTAINER_DOXYGEN_INVOKED
0105 
0106 }  //namespace dtl{
0107 
0108 #endif   //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
0109 
0110 //! A flat_map is a kind of associative container that supports unique keys (contains at
0111 //! most one of each key value) and provides for fast retrieval of values of another
0112 //! type T based on the keys.
0113 //!
0114 //! A flat_map satisfies all of the requirements of a container, a reversible
0115 //! container and an associative container. A flat_map also provides
0116 //! most operations described for unique keys. For a
0117 //! flat_map<Key,T> the key_type is Key and the value_type is std::pair<Key,T>
0118 //! (unlike std::map<Key, T> which value_type is std::pair<<b>const</b> Key, T>).
0119 //!
0120 //! flat_map is similar to std::map but it's implemented by as an ordered sequence container.
0121 //! The underlying sequence container is by default <i>vector</i> but it can also work
0122 //! user-provided vector-like SequenceContainers (like <i>static_vector</i> or <i>small_vector</i>).
0123 //!
0124 //! Using vector-like sequence containers means that inserting a new element into a flat_map might invalidate
0125 //! previous iterators and references (unless that sequence container is <i>stable_vector</i> or a similar
0126 //! container that offers stable pointers and references). Similarly, erasing an element might invalidate
0127 //! iterators and references pointing to elements that come after (their keys are bigger) the erased element.
0128 //!
0129 //! This container provides random-access iterators.
0130 //!
0131 //! \tparam Key is the key_type of the map
0132 //! \tparam Value is the <code>mapped_type</code>
0133 //! \tparam Compare is the ordering function for Keys (e.g. <i>std::less<Key></i>).
0134 //! \tparam AllocatorOrContainer is either:
0135 //!   - The allocator to allocate <code>value_type</code>s (e.g. <i>allocator< std::pair<Key, T> > </i>).
0136 //!     (in this case <i>sequence_type</i> will be vector<value_type, AllocatorOrContainer>)
0137 //!   - The SequenceContainer to be used as the underlying <i>sequence_type</i>. It must be a vector-like
0138 //!     sequence container with random-access iterators.
0139 #ifdef BOOST_CONTAINER_DOXYGEN_INVOKED
0140 template <class Key, class T, class Compare = std::less<Key>, class AllocatorOrContainer = new_allocator< std::pair< Key, T> > >
0141 #else
0142 template <class Key, class T, class Compare, class AllocatorOrContainer>
0143 #endif
0144 class flat_map
0145 {
0146    #ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
0147    private:
0148    BOOST_COPYABLE_AND_MOVABLE(flat_map)
0149    //This is the tree that we should store if pair was movable
0150    typedef std::pair<Key, T> std_pair_t;
0151    typedef dtl::flat_tree<
0152                            std_pair_t,
0153                            dtl::select1st<Key>,
0154                            Compare,
0155                            AllocatorOrContainer> tree_t;
0156 
0157    //This is the real tree stored here. It's based on a movable pair
0158    typedef dtl::pair<Key, T> dtl_pair_t;
0159 
0160    #ifdef BOOST_CONTAINER_STD_PAIR_IS_MOVABLE
0161    typedef std_pair_t impl_pair_t;
0162    #else
0163    typedef dtl_pair_t impl_pair_t;
0164    #endif
0165 
0166    typedef dtl::flat_tree<
0167                            impl_pair_t,
0168                            dtl::select1st<Key>,
0169                            Compare,
0170                            typename dtl::container_or_allocator_rebind<AllocatorOrContainer, impl_pair_t >::type
0171                            > impl_tree_t;
0172    impl_tree_t m_flat_tree;  // flat tree representing flat_map
0173 
0174    typedef typename impl_tree_t::value_type              impl_value_type;
0175    typedef typename impl_tree_t::const_iterator          impl_const_iterator;
0176    typedef typename impl_tree_t::iterator                impl_iterator;
0177    typedef typename impl_tree_t::allocator_type          impl_allocator_type;
0178    #if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
0179    typedef std::initializer_list<impl_value_type>        impl_initializer_list;
0180    #endif
0181 
0182    typedef dtl::flat_tree_value_compare
0183       < Compare
0184       , dtl::select1st<Key>
0185       , std::pair<Key, T> >                              value_compare_t;
0186    typedef typename tree_t::iterator                     iterator_t;
0187    typedef typename tree_t::const_iterator               const_iterator_t;
0188    typedef typename tree_t::reverse_iterator             reverse_iterator_t;
0189    typedef typename tree_t::const_reverse_iterator       const_reverse_iterator_t;
0190 
0191    public:
0192    typedef typename impl_tree_t::stored_allocator_type   impl_stored_allocator_type;
0193    typedef typename impl_tree_t::sequence_type           impl_sequence_type;
0194 
0195    inline impl_tree_t &tree()
0196    {  return m_flat_tree;  }
0197 
0198    inline const impl_tree_t &tree() const
0199    {  return m_flat_tree;  }
0200 
0201    private:
0202    typedef typename tree_t::get_stored_allocator_const_return_t         get_stored_allocator_const_return_t;
0203    typedef typename tree_t::get_stored_allocator_noconst_return_t       get_stored_allocator_noconst_return_t;
0204    typedef typename impl_tree_t::get_stored_allocator_const_return_t    impl_get_stored_allocator_const_return_t;
0205    typedef typename impl_tree_t::get_stored_allocator_noconst_return_t  impl_get_stored_allocator_noconst_return_t;
0206 
0207    #endif   //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
0208 
0209    public:
0210 
0211    //////////////////////////////////////////////
0212    //
0213    //                    types
0214    //
0215    //////////////////////////////////////////////
0216    typedef Key                                                                      key_type;
0217    typedef T                                                                        mapped_type;
0218    typedef Compare                                                                  key_compare;
0219    typedef std::pair<Key, T>                                                        value_type;
0220    typedef typename BOOST_CONTAINER_IMPDEF(tree_t::sequence_type)                   sequence_type;
0221    typedef typename sequence_type::allocator_type                                   allocator_type;
0222    typedef ::boost::container::allocator_traits<allocator_type>                     allocator_traits_type;
0223    typedef typename sequence_type::pointer                                          pointer;
0224    typedef typename sequence_type::const_pointer                                    const_pointer;
0225    typedef typename sequence_type::reference                                        reference;
0226    typedef typename sequence_type::const_reference                                  const_reference;
0227    typedef typename sequence_type::size_type                                        size_type;
0228    typedef typename sequence_type::difference_type                                  difference_type;
0229    typedef typename BOOST_CONTAINER_IMPDEF(tree_t::stored_allocator_type)           stored_allocator_type;
0230    typedef typename BOOST_CONTAINER_IMPDEF(tree_t::value_compare)                   value_compare;
0231 
0232    typedef typename sequence_type::iterator                                         iterator;
0233    typedef typename sequence_type::const_iterator                                   const_iterator;
0234    typedef typename sequence_type::reverse_iterator                                 reverse_iterator;
0235    typedef typename sequence_type::const_reverse_iterator                           const_reverse_iterator;
0236    typedef BOOST_CONTAINER_IMPDEF(impl_value_type)                                  movable_value_type;
0237 
0238    //AllocatorOrContainer::value_type must be std::pair<Key, T>
0239    BOOST_CONTAINER_STATIC_ASSERT((dtl::is_same<std::pair<Key, T>, value_type>::value));
0240 
0241    //////////////////////////////////////////////
0242    //
0243    //          construct/copy/destroy
0244    //
0245    //////////////////////////////////////////////
0246 
0247    //! <b>Effects</b>: Default constructs an empty flat_map.
0248    //!
0249    //! <b>Complexity</b>: Constant.
0250    inline flat_map() BOOST_NOEXCEPT_IF(dtl::is_nothrow_default_constructible<AllocatorOrContainer>::value &&
0251                                                             dtl::is_nothrow_default_constructible<Compare>::value)
0252       : m_flat_tree()
0253    {}
0254 
0255    //! <b>Effects</b>: Constructs an empty flat_map using the specified allocator.
0256    //!
0257    //! <b>Complexity</b>: Constant.
0258    inline explicit flat_map(const allocator_type& a)
0259       : m_flat_tree(dtl::force<const impl_allocator_type>(a))
0260    {}
0261 
0262    //! <b>Effects</b>: Constructs an empty flat_map using the specified
0263    //! comparison object.
0264    //!
0265    //! <b>Complexity</b>: Constant.
0266    inline explicit flat_map(const Compare& comp)
0267       : m_flat_tree(comp)
0268    {}
0269 
0270    //! <b>Effects</b>: Constructs an empty flat_map using the specified
0271    //! comparison object and allocator.
0272    //!
0273    //! <b>Complexity</b>: Constant.
0274    inline flat_map(const Compare& comp, const allocator_type& a)
0275       : m_flat_tree(comp, dtl::force<const impl_allocator_type>(a))
0276    {}
0277 
0278    //! <b>Effects</b>: Constructs an empty flat_map and
0279    //! and inserts elements from the range [first ,last ).
0280    //!
0281    //! <b>Complexity</b>: Linear in N if the range [first ,last ) is already sorted using
0282    //! the predicate and otherwise N logN, where N is last - first.
0283    template <class InputIterator>
0284    inline flat_map(InputIterator first, InputIterator last)
0285       : m_flat_tree(true, first, last)
0286    {}
0287 
0288    //! <b>Effects</b>: Constructs an empty flat_map using the specified
0289    //! allocator, and inserts elements from the range [first ,last ).
0290    //!
0291    //! <b>Complexity</b>: Linear in N if the range [first ,last ) is already sorted using
0292    //! the predicate and otherwise N logN, where N is last - first.
0293    template <class InputIterator>
0294    inline flat_map(InputIterator first, InputIterator last, const allocator_type& a)
0295       : m_flat_tree(true, first, last, dtl::force<const impl_allocator_type>(a))
0296    {}
0297 
0298    //! <b>Effects</b>: Constructs an empty flat_map using the specified comparison object and
0299    //! and inserts elements from the range [first ,last ).
0300    //!
0301    //! <b>Complexity</b>: Linear in N if the range [first ,last ) is already sorted using
0302    //! the predicate and otherwise N logN, where N is last - first.
0303    template <class InputIterator>
0304    inline flat_map(InputIterator first, InputIterator last, const Compare& comp)
0305       : m_flat_tree(true, first, last, comp)
0306    {}
0307 
0308    //! <b>Effects</b>: Constructs an empty flat_map using the specified comparison object and
0309    //! allocator, and inserts elements from the range [first ,last ).
0310    //!
0311    //! <b>Complexity</b>: Linear in N if the range [first ,last ) is already sorted using
0312    //! the predicate and otherwise N logN, where N is last - first.
0313    template <class InputIterator>
0314    inline flat_map(InputIterator first, InputIterator last, const Compare& comp, const allocator_type& a)
0315       : m_flat_tree(true, first, last, comp, dtl::force<const impl_allocator_type>(a))
0316    {}
0317 
0318    //! <b>Effects</b>: Constructs an empty flat_map
0319    //! and inserts elements from the ordered range [first ,last). This function
0320    //! is more efficient than the normal range creation for ordered ranges.
0321    //!
0322    //! <b>Requires</b>: [first ,last) must be ordered according to the predicate.
0323    //!
0324    //! <b>Complexity</b>: Linear in N.
0325    //!
0326    //! <b>Note</b>: Non-standard extension.
0327    template <class InputIterator>
0328    inline
0329    flat_map(ordered_unique_range_t, InputIterator first, InputIterator last)
0330       : m_flat_tree(ordered_range, first, last)
0331    {}
0332 
0333    //! <b>Effects</b>: Constructs an empty flat_map using the specified comparison object and
0334    //! inserts elements from the ordered range [first ,last). This function
0335    //! is more efficient than the normal range creation for ordered ranges.
0336    //!
0337    //! <b>Requires</b>: [first ,last) must be ordered according to the predicate.
0338    //!
0339    //! <b>Complexity</b>: Linear in N.
0340    //!
0341    //! <b>Note</b>: Non-standard extension.
0342    template <class InputIterator>
0343    inline
0344    flat_map(ordered_unique_range_t, InputIterator first, InputIterator last, const Compare& comp)
0345       : m_flat_tree(ordered_range, first, last, comp)
0346    {}
0347 
0348    //! <b>Effects</b>: Constructs an empty flat_map using the specified comparison object and
0349    //! allocator, and inserts elements from the ordered range [first ,last). This function
0350    //! is more efficient than the normal range creation for ordered ranges.
0351    //!
0352    //! <b>Requires</b>: [first ,last) must be ordered according to the predicate.
0353    //!
0354    //! <b>Complexity</b>: Linear in N.
0355    //!
0356    //! <b>Note</b>: Non-standard extension.
0357    template <class InputIterator>
0358    inline
0359    flat_map(ordered_unique_range_t, InputIterator first, InputIterator last, const Compare& comp, const allocator_type& a)
0360       : m_flat_tree(ordered_range, first, last, comp, dtl::force<const impl_allocator_type>(a))
0361    {}
0362 
0363    //! <b>Effects</b>: Constructs an empty flat_map using the specified allocator and
0364    //! inserts elements from the ordered range [first ,last). This function
0365    //! is more efficient than the normal range creation for ordered ranges.
0366    //!
0367    //! <b>Requires</b>: [first ,last) must be ordered according to the predicate.
0368    //!
0369    //! <b>Complexity</b>: Linear in N.
0370    //!
0371    //! <b>Note</b>: Non-standard extension.
0372    template <class InputIterator>
0373    inline
0374       flat_map(ordered_unique_range_t, InputIterator first, InputIterator last, const allocator_type& a)
0375       : m_flat_tree(ordered_range, first, last, Compare(), a)
0376    {}
0377 
0378 #if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
0379    //! <b>Effects</b>: Constructs an empty flat_map and
0380    //! inserts elements from the range [il.begin() ,il.end()).
0381    //!
0382    //! <b>Complexity</b>: Linear in N if the range [il.begin(), il.end()) is already sorted using
0383    //! the predicate and otherwise N logN, where N is last - first.
0384    inline flat_map(std::initializer_list<value_type> il)
0385      : m_flat_tree( true
0386                   , dtl::force<impl_initializer_list>(il).begin()
0387                   , dtl::force<impl_initializer_list>(il).end())
0388    {}
0389 
0390    //! <b>Effects</b>: Constructs an empty flat_map using the specified
0391    //! allocator, and inserts elements from the range [il.begin() ,il.end()).
0392    //!
0393    //! <b>Complexity</b>: Linear in N if the range [il.begin(), il.end()) is already sorted using
0394    //! the predicate and otherwise N logN, where N is last - first.
0395    inline flat_map(std::initializer_list<value_type> il, const allocator_type& a)
0396      : m_flat_tree( true
0397                   , dtl::force<impl_initializer_list>(il).begin()
0398                   , dtl::force<impl_initializer_list>(il).end()
0399                   , dtl::force<const impl_allocator_type>(a))
0400    {}
0401 
0402    //! <b>Effects</b>: Constructs an empty flat_map using the specified comparison object and
0403    //! inserts elements from the range [il.begin() ,il.end()).
0404    //!
0405    //! <b>Complexity</b>: Linear in N if the range [il.begin(), il.end()) is already sorted using
0406    //! the predicate and otherwise N logN, where N is last - first.
0407    inline flat_map(std::initializer_list<value_type> il, const Compare& comp)
0408      : m_flat_tree(true
0409                   , dtl::force<impl_initializer_list>(il).begin()
0410                   , dtl::force<impl_initializer_list>(il).end()
0411                   , comp)
0412    {}
0413 
0414    //! <b>Effects</b>: Constructs an empty flat_map using the specified comparison object and
0415    //! allocator, and inserts elements from the range [il.begin() ,il.end()).
0416    //!
0417    //! <b>Complexity</b>: Linear in N if the range [il.begin(), il.end()) is already sorted using
0418    //! the predicate and otherwise N logN, where N is last - first.
0419    inline flat_map(std::initializer_list<value_type> il, const Compare& comp, const allocator_type& a)
0420      : m_flat_tree(true
0421                   , dtl::force<impl_initializer_list>(il).begin()
0422                   , dtl::force<impl_initializer_list>(il).end()
0423                   , comp
0424                   , dtl::force<const impl_allocator_type>(a))
0425    {}
0426 
0427    //! <b>Effects</b>: Constructs an empty flat_map using and
0428    //! inserts elements from the ordered unique range [il.begin(), il.end()). This function
0429    //! is more efficient than the normal range creation for ordered ranges.
0430    //!
0431    //! <b>Requires</b>: [il.begin(), il.end()) must be ordered according to the predicate and must be
0432    //! unique values.
0433    //!
0434    //! <b>Complexity</b>: Linear in N.
0435    //!
0436    //! <b>Note</b>: Non-standard extension.
0437    inline flat_map(ordered_unique_range_t, std::initializer_list<value_type> il)
0438      : m_flat_tree(ordered_unique_range
0439                   , dtl::force<impl_initializer_list>(il).begin()
0440                   , dtl::force<impl_initializer_list>(il).end())
0441    {}
0442 
0443    //! <b>Effects</b>: Constructs an empty flat_map using the specified comparison object and
0444    //! inserts elements from the ordered unique range [il.begin(), il.end()). This function
0445    //! is more efficient than the normal range creation for ordered ranges.
0446    //!
0447    //! <b>Requires</b>: [il.begin(), il.end()) must be ordered according to the predicate and must be
0448    //! unique values.
0449    //!
0450    //! <b>Complexity</b>: Linear in N.
0451    //!
0452    //! <b>Note</b>: Non-standard extension.
0453    inline flat_map(ordered_unique_range_t, std::initializer_list<value_type> il, const Compare& comp)
0454      : m_flat_tree(ordered_unique_range
0455                   , dtl::force<impl_initializer_list>(il).begin()
0456                   , dtl::force<impl_initializer_list>(il).end()
0457                   , comp)
0458    {}
0459 
0460    //! <b>Effects</b>: Constructs an empty flat_map using the specified comparison object and
0461    //! allocator, and inserts elements from the ordered unique range [il.begin(), il.end()). This function
0462    //! is more efficient than the normal range creation for ordered ranges.
0463    //!
0464    //! <b>Requires</b>: [il.begin(), il.end()) must be ordered according to the predicate and must be
0465    //! unique values.
0466    //!
0467    //! <b>Complexity</b>: Linear in N.
0468    //!
0469    //! <b>Note</b>: Non-standard extension.
0470    inline flat_map(ordered_unique_range_t, std::initializer_list<value_type> il, const Compare& comp, const allocator_type& a)
0471      : m_flat_tree( ordered_unique_range
0472                   , dtl::force<impl_initializer_list>(il).begin()
0473                   , dtl::force<impl_initializer_list>(il).end()
0474                   , comp
0475                   , dtl::force<const impl_allocator_type>(a))
0476    {}
0477 #endif
0478 
0479    //! <b>Effects</b>: Copy constructs a flat_map.
0480    //!
0481    //! <b>Complexity</b>: Linear in x.size().
0482    inline flat_map(const flat_map& x)
0483       : m_flat_tree(x.m_flat_tree)
0484    {}
0485 
0486    //! <b>Effects</b>: Move constructs a flat_map.
0487    //!   Constructs *this using x's resources.
0488    //!
0489    //! <b>Complexity</b>: Constant.
0490    //!
0491    //! <b>Postcondition</b>: x is emptied.
0492    inline flat_map(BOOST_RV_REF(flat_map) x)
0493       BOOST_NOEXCEPT_IF(boost::container::dtl::is_nothrow_move_constructible<Compare>::value)
0494       : m_flat_tree(boost::move(x.m_flat_tree))
0495    {}
0496 
0497    //! <b>Effects</b>: Copy constructs a flat_map using the specified allocator.
0498    //!
0499    //! <b>Complexity</b>: Linear in x.size().
0500    inline flat_map(const flat_map& x, const allocator_type &a)
0501       : m_flat_tree(x.m_flat_tree, dtl::force<const impl_allocator_type>(a))
0502    {}
0503 
0504    //! <b>Effects</b>: Move constructs a flat_map using the specified allocator.
0505    //!   Constructs *this using x's resources.
0506    //!
0507    //! <b>Complexity</b>: Constant if x.get_allocator() == a, linear otherwise.
0508    inline flat_map(BOOST_RV_REF(flat_map) x, const allocator_type &a)
0509       : m_flat_tree(boost::move(x.m_flat_tree), dtl::force<const impl_allocator_type>(a))
0510    {}
0511 
0512    //! <b>Effects</b>: Makes *this a copy of x.
0513    //!
0514    //! <b>Complexity</b>: Linear in x.size().
0515    inline flat_map& operator=(BOOST_COPY_ASSIGN_REF(flat_map) x)
0516    {  m_flat_tree = x.m_flat_tree;   return *this;  }
0517 
0518    //! <b>Effects</b>: Move constructs a flat_map.
0519    //!   Constructs *this using x's resources.
0520    //!
0521    //! <b>Throws</b>: If allocator_traits_type::propagate_on_container_move_assignment
0522    //!   is false and (allocation throws or value_type's move constructor throws)
0523    //!
0524    //! <b>Complexity</b>: Constant if allocator_traits_type::
0525    //!   propagate_on_container_move_assignment is true or
0526    //!   this->get>allocator() == x.get_allocator(). Linear otherwise.
0527    inline flat_map& operator=(BOOST_RV_REF(flat_map) x)
0528       BOOST_NOEXCEPT_IF( (allocator_traits_type::propagate_on_container_move_assignment::value ||
0529                           allocator_traits_type::is_always_equal::value) &&
0530                            boost::container::dtl::is_nothrow_move_assignable<Compare>::value)
0531    {  m_flat_tree = boost::move(x.m_flat_tree);   return *this;  }
0532 
0533 #if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
0534    //! <b>Effects</b>: Assign elements from il to *this
0535    flat_map& operator=(std::initializer_list<value_type> il)
0536    {
0537       this->clear();
0538       this->insert(il.begin(), il.end());
0539       return *this;
0540    }
0541 #endif
0542 
0543    //! <b>Effects</b>: Returns a copy of the allocator that
0544    //!   was passed to the object's constructor.
0545    //!
0546    //! <b>Complexity</b>: Constant.
0547    BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline
0548       allocator_type get_allocator() const BOOST_NOEXCEPT_OR_NOTHROW
0549       { return dtl::force_copy<allocator_type>(m_flat_tree.get_allocator()); }
0550 
0551    //! <b>Effects</b>: Returns a reference to the internal allocator.
0552    //!
0553    //! <b>Throws</b>: Nothing
0554    //!
0555    //! <b>Complexity</b>: Constant.
0556    //!
0557    //! <b>Note</b>: Non-standard extension.
0558    BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline
0559       get_stored_allocator_noconst_return_t get_stored_allocator() BOOST_NOEXCEPT_OR_NOTHROW
0560    {
0561       impl_get_stored_allocator_noconst_return_t r = m_flat_tree.get_stored_allocator();
0562       return dtl::force<stored_allocator_type>(r);
0563    }
0564 
0565    //! <b>Effects</b>: Returns a reference to the internal allocator.
0566    //!
0567    //! <b>Throws</b>: Nothing
0568    //!
0569    //! <b>Complexity</b>: Constant.
0570    //!
0571    //! <b>Note</b>: Non-standard extension.
0572    BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline
0573       get_stored_allocator_const_return_t get_stored_allocator() const BOOST_NOEXCEPT_OR_NOTHROW
0574    {
0575       impl_get_stored_allocator_const_return_t r = m_flat_tree.get_stored_allocator();
0576       return dtl::force<const stored_allocator_type>(r);
0577    }
0578 
0579    //////////////////////////////////////////////
0580    //
0581    //                iterators
0582    //
0583    //////////////////////////////////////////////
0584 
0585    //! <b>Effects</b>: Returns an iterator to the first element contained in the container.
0586    //!
0587    //! <b>Throws</b>: Nothing.
0588    //!
0589    //! <b>Complexity</b>: Constant.
0590    BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline
0591       iterator begin() BOOST_NOEXCEPT_OR_NOTHROW
0592       { return dtl::force_copy<iterator>(m_flat_tree.begin()); }
0593 
0594    //! <b>Effects</b>: Returns a const_iterator to the first element contained in the container.
0595    //!
0596    //! <b>Throws</b>: Nothing.
0597    //!
0598    //! <b>Complexity</b>: Constant.
0599    BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline
0600       const_iterator begin() const BOOST_NOEXCEPT_OR_NOTHROW
0601       { return dtl::force_copy<const_iterator>(m_flat_tree.begin()); }
0602 
0603    //! <b>Effects</b>: Returns an iterator to the end of the container.
0604    //!
0605    //! <b>Throws</b>: Nothing.
0606    //!
0607    //! <b>Complexity</b>: Constant.
0608    BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline
0609       iterator end() BOOST_NOEXCEPT_OR_NOTHROW
0610       { return dtl::force_copy<iterator>(m_flat_tree.end()); }
0611 
0612    //! <b>Effects</b>: Returns a const_iterator to the end of the container.
0613    //!
0614    //! <b>Throws</b>: Nothing.
0615    //!
0616    //! <b>Complexity</b>: Constant.
0617    BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline
0618       const_iterator end() const BOOST_NOEXCEPT_OR_NOTHROW
0619       { return dtl::force_copy<const_iterator>(m_flat_tree.end()); }
0620 
0621    //! <b>Effects</b>: Returns a reverse_iterator pointing to the beginning
0622    //! of the reversed container.
0623    //!
0624    //! <b>Throws</b>: Nothing.
0625    //!
0626    //! <b>Complexity</b>: Constant.
0627    BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline
0628       reverse_iterator rbegin() BOOST_NOEXCEPT_OR_NOTHROW
0629       { return dtl::force_copy<reverse_iterator>(m_flat_tree.rbegin()); }
0630 
0631    //! <b>Effects</b>: Returns a const_reverse_iterator pointing to the beginning
0632    //! of the reversed container.
0633    //!
0634    //! <b>Throws</b>: Nothing.
0635    //!
0636    //! <b>Complexity</b>: Constant.
0637    BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline
0638       const_reverse_iterator rbegin() const BOOST_NOEXCEPT_OR_NOTHROW
0639       { return dtl::force_copy<const_reverse_iterator>(m_flat_tree.rbegin()); }
0640 
0641    //! <b>Effects</b>: Returns a reverse_iterator pointing to the end
0642    //! of the reversed container.
0643    //!
0644    //! <b>Throws</b>: Nothing.
0645    //!
0646    //! <b>Complexity</b>: Constant.
0647    BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline
0648       reverse_iterator rend() BOOST_NOEXCEPT_OR_NOTHROW
0649       { return dtl::force_copy<reverse_iterator>(m_flat_tree.rend()); }
0650 
0651    //! <b>Effects</b>: Returns a const_reverse_iterator pointing to the end
0652    //! of the reversed container.
0653    //!
0654    //! <b>Throws</b>: Nothing.
0655    //!
0656    //! <b>Complexity</b>: Constant.
0657    BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline
0658       const_reverse_iterator rend() const BOOST_NOEXCEPT_OR_NOTHROW
0659       { return dtl::force_copy<const_reverse_iterator>(m_flat_tree.rend()); }
0660 
0661    //! <b>Effects</b>: Returns a const_iterator to the first element contained in the container.
0662    //!
0663    //! <b>Throws</b>: Nothing.
0664    //!
0665    //! <b>Complexity</b>: Constant.
0666    BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline
0667       const_iterator cbegin() const BOOST_NOEXCEPT_OR_NOTHROW
0668       { return dtl::force_copy<const_iterator>(m_flat_tree.cbegin()); }
0669 
0670    //! <b>Effects</b>: Returns a const_iterator to the end of the container.
0671    //!
0672    //! <b>Throws</b>: Nothing.
0673    //!
0674    //! <b>Complexity</b>: Constant.
0675    BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline
0676       const_iterator cend() const BOOST_NOEXCEPT_OR_NOTHROW
0677       { return dtl::force_copy<const_iterator>(m_flat_tree.cend()); }
0678 
0679    //! <b>Effects</b>: Returns a const_reverse_iterator pointing to the beginning
0680    //! of the reversed container.
0681    //!
0682    //! <b>Throws</b>: Nothing.
0683    //!
0684    //! <b>Complexity</b>: Constant.
0685    BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline
0686       const_reverse_iterator crbegin() const BOOST_NOEXCEPT_OR_NOTHROW
0687       { return dtl::force_copy<const_reverse_iterator>(m_flat_tree.crbegin()); }
0688 
0689    //! <b>Effects</b>: Returns a const_reverse_iterator pointing to the end
0690    //! of the reversed container.
0691    //!
0692    //! <b>Throws</b>: Nothing.
0693    //!
0694    //! <b>Complexity</b>: Constant.
0695    BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline
0696       const_reverse_iterator crend() const BOOST_NOEXCEPT_OR_NOTHROW
0697       { return dtl::force_copy<const_reverse_iterator>(m_flat_tree.crend()); }
0698 
0699    //////////////////////////////////////////////
0700    //
0701    //                capacity
0702    //
0703    //////////////////////////////////////////////
0704 
0705    //! <b>Effects</b>: Returns true if the container contains no elements.
0706    //!
0707    //! <b>Throws</b>: Nothing.
0708    //!
0709    //! <b>Complexity</b>: Constant.
0710    BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline
0711       bool empty() const BOOST_NOEXCEPT_OR_NOTHROW
0712       { return m_flat_tree.empty(); }
0713 
0714    //! <b>Effects</b>: Returns the number of the elements contained in the container.
0715    //!
0716    //! <b>Throws</b>: Nothing.
0717    //!
0718    //! <b>Complexity</b>: Constant.
0719    BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline
0720       size_type size() const BOOST_NOEXCEPT_OR_NOTHROW
0721       { return m_flat_tree.size(); }
0722 
0723    //! <b>Effects</b>: Returns the largest possible size of the container.
0724    //!
0725    //! <b>Throws</b>: Nothing.
0726    //!
0727    //! <b>Complexity</b>: Constant.
0728    BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline
0729       size_type max_size() const BOOST_NOEXCEPT_OR_NOTHROW
0730       { return m_flat_tree.max_size(); }
0731 
0732    //! <b>Effects</b>: Number of elements for which memory has been allocated.
0733    //!   capacity() is always greater than or equal to size().
0734    //!
0735    //! <b>Throws</b>: Nothing.
0736    //!
0737    //! <b>Complexity</b>: Constant.
0738    BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline
0739       size_type capacity() const BOOST_NOEXCEPT_OR_NOTHROW
0740       { return m_flat_tree.capacity(); }
0741 
0742    //! <b>Effects</b>: If n is less than or equal to capacity(), or the
0743    //!   underlying container has no `reserve` member, this call has no
0744    //!   effect. Otherwise, it is a request for allocation of additional memory.
0745    //!   If the request is successful, then capacity() is greater than or equal to
0746    //!   n; otherwise, capacity() is unchanged. In either case, size() is unchanged.
0747    //!
0748    //! <b>Throws</b>: If memory allocation allocation throws or T's copy constructor throws.
0749    //!
0750    //! <b>Note</b>: If capacity() is less than "cnt", iterators and references to
0751    //!   to values might be invalidated.
0752    inline void reserve(size_type cnt)
0753       { m_flat_tree.reserve(cnt);   }
0754 
0755    //! <b>Effects</b>: Tries to deallocate the excess of memory created
0756    //    with previous allocations. The size of the vector is unchanged
0757    //!
0758    //! <b>Throws</b>: If memory allocation throws, or T's copy constructor throws.
0759    //!
0760    //! <b>Complexity</b>: Linear to size().
0761    inline void shrink_to_fit()
0762       { m_flat_tree.shrink_to_fit(); }
0763 
0764    //////////////////////////////////////////////
0765    //
0766    //               element access
0767    //
0768    //////////////////////////////////////////////
0769 
0770    #if defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
0771    //! Effects: If there is no key equivalent to x in the flat_map, inserts
0772    //!   value_type(x, T()) into the flat_map.
0773    //!
0774    //! Returns: A reference to the mapped_type corresponding to x in *this.
0775    //!
0776    //! Complexity: Logarithmic search time plus linear insertion time in case no equivalent key is present.
0777    mapped_type &operator[](const key_type& k);
0778 
0779    //! Effects: If there is no key equivalent to x in the flat_map, inserts
0780    //! value_type(move(x), T()) into the flat_map (the key is move-constructed)
0781    //!
0782    //! Returns: A reference to the mapped_type corresponding to x in *this.
0783    //!
0784    //! Complexity: Logarithmic search time plus linear insertion time in case no equivalent key is present.
0785    mapped_type &operator[](key_type &&k);
0786    #elif defined(BOOST_MOVE_HELPERS_RETURN_SFINAE_BROKEN)
0787       //in compilers like GCC 3.4, we can't catch temporaries
0788       inline mapped_type& operator[](const key_type &k)         {  return this->priv_subscript(k);  }
0789       inline mapped_type& operator[](BOOST_RV_REF(key_type) k)  {  return this->priv_subscript(::boost::move(k));  }
0790    #else
0791       BOOST_MOVE_CONVERSION_AWARE_CATCH( operator[] , key_type, mapped_type&, this->priv_subscript)
0792    #endif
0793 
0794    //! Effects: If a key equivalent to k already exists in the container, assigns forward<M>(obj)
0795    //! to the mapped_type corresponding to the key k. If the key does not exist, inserts the new value
0796    //! as if by insert, constructing it from value_type(k, forward<M>(obj)).
0797    //! 
0798    //! No iterators or references are invalidated. If the insertion is successful, pointers and references
0799    //! to the element obtained while it is held in the node handle are invalidated, and pointers and
0800    //! references obtained to that element before it was extracted become valid.
0801    //!
0802    //! Returns: The bool component is true if the insertion took place and false if the assignment
0803    //!   took place. The iterator component is pointing at the element that was inserted or updated.
0804    //!
0805    //! Complexity: Logarithmic search time plus linear insertion time in case no equivalent key is present.
0806    template <class M>
0807    inline std::pair<iterator, bool> insert_or_assign(const key_type& k, BOOST_FWD_REF(M) obj)
0808    {
0809       return dtl::force_copy< std::pair<iterator, bool> >
0810          (this->m_flat_tree.insert_or_assign
0811             ( impl_const_iterator(), k, ::boost::forward<M>(obj))
0812          );
0813    }
0814 
0815    //! Effects: If a key equivalent to k already exists in the container, assigns forward<M>(obj)
0816    //! to the mapped_type corresponding to the key k. If the key does not exist, inserts the new value
0817    //! as if by insert, constructing it from value_type(k, move(obj)).
0818    //! 
0819    //! No iterators or references are invalidated. If the insertion is successful, pointers and references
0820    //! to the element obtained while it is held in the node handle are invalidated, and pointers and
0821    //! references obtained to that element before it was extracted become valid.
0822    //!
0823    //! Returns: The bool component is true if the insertion took place and false if the assignment
0824    //!   took place. The iterator component is pointing at the element that was inserted or updated.
0825    //!
0826    //! Complexity: Logarithmic in the size of the container.
0827    template <class M>
0828    inline std::pair<iterator, bool> insert_or_assign(BOOST_RV_REF(key_type) k, BOOST_FWD_REF(M) obj)
0829    {
0830       return dtl::force_copy< std::pair<iterator, bool> >
0831          (this->m_flat_tree.insert_or_assign
0832             ( impl_const_iterator(), ::boost::move(k), ::boost::forward<M>(obj))
0833          );
0834    }
0835 
0836    //! Effects: If a key equivalent to k already exists in the container, assigns forward<M>(obj)
0837    //! to the mapped_type corresponding to the key k. If the key does not exist, inserts the new value
0838    //! as if by insert, constructing it from value_type(k, forward<M>(obj)) and the new element
0839    //! to the container as close as possible to the position just before hint.
0840    //! 
0841    //! No iterators or references are invalidated. If the insertion is successful, pointers and references
0842    //! to the element obtained while it is held in the node handle are invalidated, and pointers and
0843    //! references obtained to that element before it was extracted become valid.
0844    //!
0845    //! Returns: The bool component is true if the insertion took place and false if the assignment
0846    //!   took place. The iterator component is pointing at the element that was inserted or updated.
0847    //!
0848    //! Complexity: Logarithmic in the size of the container in general, but amortized constant if
0849    //! the new element is inserted just before hint.
0850    template <class M>
0851    inline iterator insert_or_assign(const_iterator hint, const key_type& k, BOOST_FWD_REF(M) obj)
0852    {
0853       return dtl::force_copy<iterator>
0854          (this->m_flat_tree.insert_or_assign
0855             ( dtl::force_copy<impl_const_iterator>(hint)
0856             , k, ::boost::forward<M>(obj)).first
0857          );
0858    }
0859 
0860    //! Effects: If a key equivalent to k already exists in the container, assigns forward<M>(obj)
0861    //! to the mapped_type corresponding to the key k. If the key does not exist, inserts the new value
0862    //! as if by insert, constructing it from value_type(k, move(obj)) and the new element
0863    //! to the container as close as possible to the position just before hint.
0864    //! 
0865    //! No iterators or references are invalidated. If the insertion is successful, pointers and references
0866    //! to the element obtained while it is held in the node handle are invalidated, and pointers and
0867    //! references obtained to that element before it was extracted become valid.
0868    //!
0869    //! Returns: The bool component is true if the insertion took place and false if the assignment
0870    //!   took place. The iterator component is pointing at the element that was inserted or updated.
0871    //!
0872    //! Complexity: Logarithmic in the size of the container in general, but amortized constant if
0873    //! the new element is inserted just before hint.
0874    template <class M>
0875    inline iterator insert_or_assign(const_iterator hint, BOOST_RV_REF(key_type) k, BOOST_FWD_REF(M) obj)
0876    {
0877       return dtl::force_copy<iterator>
0878          (this->m_flat_tree.insert_or_assign
0879             ( dtl::force_copy<impl_const_iterator>(hint)
0880             , ::boost::move(k), ::boost::forward<M>(obj)).first
0881          );
0882    }
0883 
0884    //! @copydoc ::boost::container::flat_set::nth(size_type)
0885    BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline
0886       iterator nth(size_type n) BOOST_NOEXCEPT_OR_NOTHROW
0887    {  return dtl::force_copy<iterator>(m_flat_tree.nth(n));  }
0888 
0889    //! @copydoc ::boost::container::flat_set::nth(size_type) const
0890    BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline
0891       const_iterator nth(size_type n) const BOOST_NOEXCEPT_OR_NOTHROW
0892    {  return dtl::force_copy<const_iterator>(m_flat_tree.nth(n));  }
0893 
0894    //! @copydoc ::boost::container::flat_set::index_of(iterator)
0895    BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline
0896       size_type index_of(iterator p) BOOST_NOEXCEPT_OR_NOTHROW
0897    {  return m_flat_tree.index_of(dtl::force_copy<impl_iterator>(p));  }
0898 
0899    //! @copydoc ::boost::container::flat_set::index_of(const_iterator) const
0900    BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline
0901       size_type index_of(const_iterator p) const BOOST_NOEXCEPT_OR_NOTHROW
0902    {  return m_flat_tree.index_of(dtl::force_copy<impl_const_iterator>(p));  }
0903 
0904    //! Returns: A reference to the element whose key is equivalent to x.
0905    //!
0906    //! Throws: An exception object of type out_of_range if no such element is present.
0907    //!
0908    //! Complexity: logarithmic.
0909    BOOST_CONTAINER_ATTRIBUTE_NODISCARD T& at(const key_type& k)
0910    {
0911       iterator i = this->find(k);
0912       if(i == this->end()){
0913          throw_out_of_range("flat_map::at key not found");
0914       }
0915       return i->second;
0916    }
0917 
0918    //! Returns: A reference to the element whose key is equivalent to x.
0919    //!
0920    //! Throws: An exception object of type out_of_range if no such element is present.
0921    //!
0922    //! Complexity: logarithmic.
0923    BOOST_CONTAINER_ATTRIBUTE_NODISCARD const T& at(const key_type& k) const
0924    {
0925       const_iterator i = this->find(k);
0926       if(i == this->end()){
0927          throw_out_of_range("flat_map::at key not found");
0928       }
0929       return i->second;
0930    }
0931 
0932    //////////////////////////////////////////////
0933    //
0934    //                modifiers
0935    //
0936    //////////////////////////////////////////////
0937 
0938    #if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) || defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
0939 
0940    //! <b>Effects</b>: Inserts an object x of type T constructed with
0941    //!   std::forward<Args>(args)... if and only if there is no element in the container
0942    //!   with key equivalent to the key of x.
0943    //!
0944    //! <b>Returns</b>: The bool component of the returned pair is true if and only
0945    //!   if the insertion takes place, and the iterator component of the pair
0946    //!   points to the element with key equivalent to the key of x.
0947    //!
0948    //! <b>Complexity</b>: Logarithmic search time plus linear insertion
0949    //!   to the elements with bigger keys than x.
0950    //!
0951    //! <b>Note</b>: If an element is inserted it might invalidate elements.
0952    template <class... Args>
0953    inline std::pair<iterator,bool> emplace(BOOST_FWD_REF(Args)... args)
0954    {  return dtl::force_copy< std::pair<iterator, bool> >(m_flat_tree.emplace_unique(boost::forward<Args>(args)...)); }
0955 
0956    //! <b>Effects</b>: Inserts an object of type T constructed with
0957    //!   std::forward<Args>(args)... in the container if and only if there is
0958    //!   no element in the container with key equivalent to the key of x.
0959    //!   p is a hint pointing to where the insert should start to search.
0960    //!
0961    //! <b>Returns</b>: An iterator pointing to the element with key equivalent
0962    //!   to the key of x.
0963    //!
0964    //! <b>Complexity</b>: Logarithmic search time (constant if x is inserted
0965    //!   right before p) plus insertion linear to the elements with bigger keys than x.
0966    //!
0967    //! <b>Note</b>: If an element is inserted it might invalidate elements.
0968    template <class... Args>
0969    inline iterator emplace_hint(const_iterator hint, BOOST_FWD_REF(Args)... args)
0970    {
0971       return dtl::force_copy<iterator>
0972          (m_flat_tree.emplace_hint_unique( dtl::force_copy<impl_const_iterator>(hint)
0973                                          , boost::forward<Args>(args)...));
0974    }
0975 
0976    //! <b>Requires</b>: value_type shall be EmplaceConstructible into map from piecewise_construct, 
0977    //! forward_as_tuple(k), forward_as_tuple(forward<Args>(args)...).
0978    //! 
0979    //! <b>Effects</b>: If the map already contains an element whose key is equivalent to k, there is no effect. Otherwise
0980    //! inserts an object of type value_type constructed with piecewise_construct, forward_as_tuple(k),
0981    //! forward_as_tuple(forward<Args>(args)...).
0982    //! 
0983    //! <b>Returns</b>: The bool component of the returned pair is true if and only if the
0984    //! insertion took place. The returned iterator points to the map element whose key is equivalent to k.
0985    //! 
0986    //! <b>Complexity</b>: Logarithmic.
0987    template <class... Args>
0988    inline std::pair<iterator, bool> try_emplace(const key_type& k, BOOST_FWD_REF(Args)... args)
0989    {
0990       return dtl::force_copy< std::pair<iterator, bool> >(
0991          m_flat_tree.try_emplace(impl_const_iterator(), k, boost::forward<Args>(args)...));
0992    }
0993 
0994    //! <b>Requires</b>: value_type shall be EmplaceConstructible into map from piecewise_construct, 
0995    //! forward_as_tuple(k), forward_as_tuple(forward<Args>(args)...).
0996    //! 
0997    //! <b>Effects</b>: If the map already contains an element whose key is equivalent to k, there is no effect. Otherwise
0998    //! inserts an object of type value_type constructed with piecewise_construct, forward_as_tuple(k),
0999    //! forward_as_tuple(forward<Args>(args)...).
1000    //! 
1001    //! <b>Returns</b>: The returned iterator points to the map element whose key is equivalent to k.
1002    //! 
1003    //! <b>Complexity</b>: Logarithmic in general, but amortized constant if value
1004    //!   is inserted right before p.
1005    template <class... Args>
1006    inline iterator try_emplace(const_iterator hint, const key_type &k, BOOST_FWD_REF(Args)... args)
1007    {
1008       return dtl::force_copy<iterator>(m_flat_tree.try_emplace
1009          (dtl::force_copy<impl_const_iterator>(hint), k, boost::forward<Args>(args)...).first);
1010    }
1011 
1012    //! <b>Requires</b>: value_type shall be EmplaceConstructible into map from piecewise_construct, 
1013    //! forward_as_tuple(move(k)), forward_as_tuple(forward<Args>(args)...).
1014    //! 
1015    //! <b>Effects</b>: If the map already contains an element whose key is equivalent to k, there is no effect. Otherwise
1016    //! inserts an object of type value_type constructed with piecewise_construct, forward_as_tuple(move(k)),
1017    //! forward_as_tuple(forward<Args>(args)...).
1018    //! 
1019    //! <b>Returns</b>: The bool component of the returned pair is true if and only if the
1020    //! insertion took place. The returned iterator points to the map element whose key is equivalent to k.
1021    //! 
1022    //! <b>Complexity</b>: Logarithmic search time plus linear insertion time in case the key is not present.
1023    template <class... Args>
1024    inline std::pair<iterator, bool> try_emplace(BOOST_RV_REF(key_type) k, BOOST_FWD_REF(Args)... args)
1025    {
1026       return dtl::force_copy< std::pair<iterator, bool> >
1027          (m_flat_tree.try_emplace(impl_const_iterator(), boost::move(k), boost::forward<Args>(args)...));
1028    }
1029 
1030    //! <b>Requires</b>: value_type shall be EmplaceConstructible into map from piecewise_construct, 
1031    //! forward_as_tuple(move(k)), forward_as_tuple(forward<Args>(args)...).
1032    //! 
1033    //! <b>Effects</b>: If the map already contains an element whose key is equivalent to k, there is no effect. Otherwise
1034    //! inserts an object of type value_type constructed with piecewise_construct, forward_as_tuple(move(k)),
1035    //! forward_as_tuple(forward<Args>(args)...).
1036    //! 
1037    //! <b>Returns</b>: The returned iterator points to the map element whose key is equivalent to k.
1038    //! 
1039    //! <b>Complexity</b>: Logarithmic in general, but amortized constant if value
1040    //!   is inserted right before p. Linear insertion time in case no equivalent key is present.
1041    template <class... Args>
1042    inline iterator try_emplace(const_iterator hint, BOOST_RV_REF(key_type) k, BOOST_FWD_REF(Args)... args)
1043    {
1044       return dtl::force_copy<iterator>
1045          (m_flat_tree.try_emplace(dtl::force_copy
1046             <impl_const_iterator>(hint), boost::move(k), boost::forward<Args>(args)...).first);
1047    }
1048 
1049    #else // !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
1050 
1051    #define BOOST_CONTAINER_FLAT_MAP_EMPLACE_CODE(N) \
1052    BOOST_MOVE_TMPL_LT##N BOOST_MOVE_CLASS##N BOOST_MOVE_GT##N \
1053    inline std::pair<iterator,bool> emplace(BOOST_MOVE_UREF##N)\
1054    {\
1055       return dtl::force_copy< std::pair<iterator, bool> >\
1056          (m_flat_tree.emplace_unique(BOOST_MOVE_FWD##N));\
1057    }\
1058    \
1059    BOOST_MOVE_TMPL_LT##N BOOST_MOVE_CLASS##N BOOST_MOVE_GT##N \
1060    inline iterator emplace_hint(const_iterator hint BOOST_MOVE_I##N BOOST_MOVE_UREF##N)\
1061    {\
1062       return dtl::force_copy<iterator>(m_flat_tree.emplace_hint_unique\
1063          (dtl::force_copy<impl_const_iterator>(hint) BOOST_MOVE_I##N BOOST_MOVE_FWD##N));\
1064    }\
1065    BOOST_MOVE_TMPL_LT##N BOOST_MOVE_CLASS##N BOOST_MOVE_GT##N \
1066    inline std::pair<iterator, bool> try_emplace(const key_type& k BOOST_MOVE_I##N BOOST_MOVE_UREF##N)\
1067    {\
1068       return dtl::force_copy< std::pair<iterator, bool> >\
1069          (m_flat_tree.try_emplace(impl_const_iterator(), k BOOST_MOVE_I##N BOOST_MOVE_FWD##N));\
1070    }\
1071    \
1072    BOOST_MOVE_TMPL_LT##N BOOST_MOVE_CLASS##N BOOST_MOVE_GT##N \
1073    inline iterator try_emplace(const_iterator hint, const key_type &k BOOST_MOVE_I##N BOOST_MOVE_UREF##N)\
1074    {  return dtl::force_copy<iterator>(m_flat_tree.try_emplace\
1075          (dtl::force_copy<impl_const_iterator>(hint), k BOOST_MOVE_I##N BOOST_MOVE_FWD##N).first); }\
1076    \
1077    BOOST_MOVE_TMPL_LT##N BOOST_MOVE_CLASS##N BOOST_MOVE_GT##N \
1078    inline std::pair<iterator, bool> try_emplace(BOOST_RV_REF(key_type) k BOOST_MOVE_I##N BOOST_MOVE_UREF##N)\
1079    {\
1080       return dtl::force_copy< std::pair<iterator, bool> >\
1081          (m_flat_tree.try_emplace(impl_const_iterator(), boost::move(k) BOOST_MOVE_I##N BOOST_MOVE_FWD##N));\
1082    }\
1083    \
1084    BOOST_MOVE_TMPL_LT##N BOOST_MOVE_CLASS##N BOOST_MOVE_GT##N \
1085    inline iterator try_emplace(const_iterator hint, BOOST_RV_REF(key_type) k BOOST_MOVE_I##N BOOST_MOVE_UREF##N)\
1086    {  return dtl::force_copy<iterator>(m_flat_tree.try_emplace\
1087       (dtl::force_copy<impl_const_iterator>(hint), boost::move(k) BOOST_MOVE_I##N BOOST_MOVE_FWD##N).first); }\
1088    //
1089    BOOST_MOVE_ITERATE_0TO9(BOOST_CONTAINER_FLAT_MAP_EMPLACE_CODE)
1090    #undef BOOST_CONTAINER_FLAT_MAP_EMPLACE_CODE
1091 
1092    #endif   // !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
1093 
1094    //! <b>Effects</b>: Inserts x if and only if there is no element in the container
1095    //!   with key equivalent to the key of x.
1096    //!
1097    //! <b>Returns</b>: The bool component of the returned pair is true if and only
1098    //!   if the insertion takes place, and the iterator component of the pair
1099    //!   points to the element with key equivalent to the key of x.
1100    //!
1101    //! <b>Complexity</b>: Logarithmic search time plus linear insertion
1102    //!   to the elements with bigger keys than x.
1103    //!
1104    //! <b>Note</b>: If an element is inserted it might invalidate elements.
1105    inline std::pair<iterator,bool> insert(const value_type& x)
1106    {  return dtl::force_copy<std::pair<iterator,bool> >(
1107          m_flat_tree.insert_unique(dtl::force<const impl_value_type>(x))); }
1108 
1109    //! <b>Effects</b>: Inserts a new value_type move constructed from the pair if and
1110    //! only if there is no element in the container with key equivalent to the key of x.
1111    //!
1112    //! <b>Returns</b>: The bool component of the returned pair is true if and only
1113    //!   if the insertion takes place, and the iterator component of the pair
1114    //!   points to the element with key equivalent to the key of x.
1115    //!
1116    //! <b>Complexity</b>: Logarithmic search time plus linear insertion
1117    //!   to the elements with bigger keys than x.
1118    //!
1119    //! <b>Note</b>: If an element is inserted it might invalidate elements.
1120    inline std::pair<iterator,bool> insert(BOOST_RV_REF(value_type) x)
1121    {
1122       return dtl::force_copy<std::pair<iterator,bool> >(
1123          m_flat_tree.insert_unique(boost::move(dtl::force<impl_value_type>(x))));
1124    }
1125 
1126    //! <b>Effects</b>: Inserts a new value_type constructed from the pair if and
1127    //! only if there is no element in the container with key equivalent to the key of x.
1128    //!
1129    //! <b>Returns</b>: The bool component of the returned pair is true if and only
1130    //!   if the insertion takes place, and the iterator component of the pair
1131    //!   points to the element with key equivalent to the key of x.
1132    //!
1133    //! <b>Complexity</b>: Logarithmic search time plus linear insertion
1134    //!   to the elements with bigger keys than x.
1135    //!
1136    //! <b>Note</b>: If an element is inserted it might invalidate elements.
1137    template <class Pair>
1138    inline BOOST_CONTAINER_DOC1ST
1139          ( std::pair<iterator BOOST_MOVE_I bool>
1140          , typename dtl::enable_if_c<dtl::is_convertible<Pair BOOST_MOVE_I dtl_pair_t>::value
1141             BOOST_MOVE_I std::pair<iterator BOOST_MOVE_I bool> >::type)
1142       insert(BOOST_FWD_REF(Pair) x)
1143    {
1144       return dtl::force_copy<std::pair<iterator,bool> >
1145          (m_flat_tree.emplace_unique(boost::forward<Pair>(x)));
1146    }
1147 
1148    //! <b>Effects</b>: Inserts a copy of x in the container if and only if there is
1149    //!   no element in the container with key equivalent to the key of x.
1150    //!   p is a hint pointing to where the insert should start to search.
1151    //!
1152    //! <b>Returns</b>: An iterator pointing to the element with key equivalent
1153    //!   to the key of x.
1154    //!
1155    //! <b>Complexity</b>: Logarithmic search time (constant if x is inserted
1156    //!   right before p) plus insertion linear to the elements with bigger keys than x.
1157    //!
1158    //! <b>Note</b>: If an element is inserted it might invalidate elements.
1159    inline iterator insert(const_iterator p, const value_type& x)
1160    {
1161       return dtl::force_copy<iterator>(
1162          m_flat_tree.insert_unique( dtl::force_copy<impl_const_iterator>(p)
1163                                   , dtl::force<const impl_value_type>(x)));
1164    }
1165 
1166    //! <b>Effects</b>: Inserts an element move constructed from x in the container.
1167    //!   p is a hint pointing to where the insert should start to search.
1168    //!
1169    //! <b>Returns</b>: An iterator pointing to the element with key equivalent to the key of x.
1170    //!
1171    //! <b>Complexity</b>: Logarithmic search time (constant if x is inserted
1172    //!   right before p) plus insertion linear to the elements with bigger keys than x.
1173    //!
1174    //! <b>Note</b>: If an element is inserted it might invalidate elements.
1175    inline iterator insert(const_iterator p, BOOST_RV_REF(value_type) x)
1176    {
1177       return dtl::force_copy<iterator>
1178          (m_flat_tree.insert_unique( dtl::force_copy<impl_const_iterator>(p)
1179                                    , boost::move(dtl::force<impl_value_type>(x))));
1180    }
1181 
1182    //! <b>Effects</b>: Inserts an element constructed from x in the container.
1183    //!   p is a hint pointing to where the insert should start to search.
1184    //!
1185    //! <b>Returns</b>: An iterator pointing to the element with key equivalent to the key of x.
1186    //!
1187    //! <b>Complexity</b>: Logarithmic search time (constant if x is inserted
1188    //!   right before p) plus insertion linear to the elements with bigger keys than x.
1189    //!
1190    //! <b>Note</b>: If an element is inserted it might invalidate elements.
1191    template <class Pair>
1192    inline BOOST_CONTAINER_DOC1ST
1193          ( iterator
1194          , typename dtl::enable_if_c<dtl::is_convertible<Pair BOOST_MOVE_I dtl_pair_t>::value
1195             BOOST_MOVE_I iterator>::type)
1196       insert(const_iterator p, BOOST_FWD_REF(Pair) x)
1197    {
1198       return dtl::force_copy<iterator>(
1199          m_flat_tree.emplace_hint_unique(dtl::force_copy<impl_const_iterator>(p), boost::forward<Pair>(x)));
1200    }
1201 
1202    //! <b>Requires</b>: first, last are not iterators into *this.
1203    //!
1204    //! <b>Effects</b>: inserts each element from the range [first,last) if and only
1205    //!   if there is no element with key equivalent to the key of that element.
1206    //!
1207    //! <b>Complexity</b>: N log(size()+N).
1208    //!
1209    //! <b>Note</b>: If an element is inserted it might invalidate elements.
1210    template <class InputIterator>
1211    inline void insert(InputIterator first, InputIterator last)
1212    {  m_flat_tree.insert_unique(first, last);  }
1213 
1214    //! <b>Requires</b>: first, last are not iterators into *this.
1215    //!
1216    //! <b>Requires</b>: [first ,last) must be ordered according to the predicate and must be
1217    //! unique values.
1218    //!
1219    //! <b>Effects</b>: inserts each element from the range [first,last) if and only
1220    //!   if there is no element with key equivalent to the key of that element. This
1221    //!   function is more efficient than the normal range creation for ordered ranges.
1222    //!
1223    //! <b>Complexity</b>: Linear.
1224    //!
1225    //! <b>Note</b>: If an element is inserted it might invalidate elements.
1226    //!
1227    //! <b>Note</b>: Non-standard extension.
1228    template <class InputIterator>
1229    inline void insert(ordered_unique_range_t, InputIterator first, InputIterator last)
1230       {  m_flat_tree.insert_unique(ordered_unique_range, first, last); }
1231 
1232 #if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
1233    //! <b>Effects</b>: inserts each element from the range [il.begin(), il.end()) if and only
1234    //!   if there is no element with key equivalent to the key of that element.
1235    //!
1236    //! <b>Complexity</b>: N log(N).
1237    //!
1238    //! <b>Note</b>: If an element is inserted it might invalidate elements.
1239    inline void insert(std::initializer_list<value_type> il)
1240    {
1241       m_flat_tree.insert_unique( dtl::force<impl_initializer_list>(il).begin()
1242                                , dtl::force<impl_initializer_list>(il).end());
1243    }
1244 
1245    //! <b>Requires</b>: [il.begin(), il.end()) must be ordered according to the predicate and must be
1246    //! unique values.
1247    //!
1248    //! <b>Effects</b>: inserts each element from the range [il.begin(), il.end()) if and only
1249    //!   if there is no element with key equivalent to the key of that element. This
1250    //!   function is more efficient than the normal range creation for ordered ranges.
1251    //!
1252    //! <b>Complexity</b>: Linear.
1253    //!
1254    //! <b>Note</b>: If an element is inserted it might invalidate elements.
1255    //!
1256    //! <b>Note</b>: Non-standard extension.
1257    inline void insert(ordered_unique_range_t, std::initializer_list<value_type> il)
1258    {
1259       m_flat_tree.insert_unique(ordered_unique_range
1260                                , dtl::force<impl_initializer_list>(il).begin()
1261                                , dtl::force<impl_initializer_list>(il).end());
1262    }
1263 #endif
1264 
1265    //! <b>Requires</b>: this->get_allocator() == source.get_allocator().
1266    //!
1267    //! <b>Effects</b>: Move-inserts each element from source into *this a using
1268    //!   the comparison object of *this. If there is an element in a with key equivalent to the
1269    //!   key of an element from source, then that element is not moved from source.
1270    //!
1271    //! <b>Complexity</b>: Linear in this->size() + source.size().
1272    //!
1273    //! <b>Note</b>: Invalidates all iterators and references.
1274    template<class C2>
1275    inline void merge(flat_map<Key, T, C2, AllocatorOrContainer>& source)
1276    {  m_flat_tree.merge_unique(source.tree());   }
1277 
1278    //! @copydoc ::boost::container::flat_map::merge(flat_map<Key, T, C2, AllocatorOrContainer>&)
1279    template<class C2>
1280    inline void merge(BOOST_RV_REF_BEG flat_map<Key, T, C2, AllocatorOrContainer> BOOST_RV_REF_END source)
1281    {  return this->merge(static_cast<flat_map<Key, T, C2, AllocatorOrContainer>&>(source)); }
1282 
1283    //! @copydoc ::boost::container::flat_map::merge(flat_map<Key, T, C2, AllocatorOrContainer>&)
1284    template<class C2>
1285    inline void merge(flat_multimap<Key, T, C2, AllocatorOrContainer>& source)
1286    {  m_flat_tree.merge_unique(source.tree());   }
1287 
1288    //! @copydoc ::boost::container::flat_map::merge(flat_map<Key, T, C2, AllocatorOrContainer>&)
1289    template<class C2>
1290    inline void merge(BOOST_RV_REF_BEG flat_multimap<Key, T, C2, AllocatorOrContainer> BOOST_RV_REF_END source)
1291    {  return this->merge(static_cast<flat_multimap<Key, T, C2, AllocatorOrContainer>&>(source));  }
1292 
1293    //! <b>Effects</b>: Erases the element pointed to by p.
1294    //!
1295    //! <b>Returns</b>: Returns an iterator pointing to the element immediately
1296    //!   following q prior to the element being erased. If no such element exists,
1297    //!   returns end().
1298    //!
1299    //! <b>Complexity</b>: Linear to the elements with keys bigger than p
1300    //!
1301    //! <b>Note</b>: Invalidates elements with keys
1302    //!   not less than the erased element.
1303    inline iterator erase(const_iterator p)
1304    {
1305       return dtl::force_copy<iterator>
1306          (m_flat_tree.erase(dtl::force_copy<impl_const_iterator>(p)));
1307    }
1308 
1309    //! <b>Effects</b>: If present, erases the element in the container with key equivalent to x.
1310    //!
1311    //! <b>Returns</b>: Returns the number of erased elements (0/1).
1312    //!
1313    //! <b>Complexity</b>: Logarithmic search time plus erasure time
1314    //!   linear to the elements with bigger keys.
1315    inline size_type erase(const key_type& x)
1316       { return m_flat_tree.erase_unique(x); }
1317 
1318    //! <b>Requires</b>: This overload is available only if
1319    //! key_compare::is_transparent exists.
1320    //!
1321    //! <b>Effects</b>: If present, erases the element in the container with key equivalent to x.
1322    //!
1323    //! <b>Returns</b>: Returns the number of erased elements (0/1).
1324    template <class K>
1325    inline BOOST_CONTAINER_DOC1ST
1326    (size_type
1327       , typename dtl::enable_if_c<
1328       dtl::is_transparent<key_compare>::value &&                  //transparent
1329       !dtl::is_convertible<K BOOST_MOVE_I iterator>::value &&     //not convertible to iterator
1330       !dtl::is_convertible<K BOOST_MOVE_I const_iterator>::value  //not convertible to const_iterator
1331       BOOST_MOVE_I size_type>::type)
1332       erase(const K& x)
1333    {  return m_flat_tree.erase_unique(x); }
1334 
1335    //! <b>Effects</b>: Erases all the elements in the range [first, last).
1336    //!
1337    //! <b>Returns</b>: Returns last.
1338    //!
1339    //! <b>Complexity</b>: size()*N where N is the distance from first to last.
1340    //!
1341    //! <b>Complexity</b>: Logarithmic search time plus erasure time
1342    //!   linear to the elements with bigger keys.
1343    inline iterator erase(const_iterator first, const_iterator last)
1344    {
1345       return dtl::force_copy<iterator>(
1346          m_flat_tree.erase( dtl::force_copy<impl_const_iterator>(first)
1347                           , dtl::force_copy<impl_const_iterator>(last)));
1348    }
1349 
1350    //! <b>Effects</b>: Swaps the contents of *this and x.
1351    //!
1352    //! <b>Throws</b>: Nothing.
1353    //!
1354    //! <b>Complexity</b>: Constant.
1355    inline void swap(flat_map& x)
1356       BOOST_NOEXCEPT_IF(  allocator_traits_type::is_always_equal::value
1357                                  && boost::container::dtl::is_nothrow_swappable<Compare>::value )
1358    { m_flat_tree.swap(x.m_flat_tree); }
1359 
1360    //! <b>Effects</b>: erase(begin(),end()).
1361    //!
1362    //! <b>Postcondition</b>: size() == 0.
1363    //!
1364    //! <b>Complexity</b>: linear in size().
1365    inline void clear() BOOST_NOEXCEPT_OR_NOTHROW
1366       { m_flat_tree.clear(); }
1367 
1368    //////////////////////////////////////////////
1369    //
1370    //                observers
1371    //
1372    //////////////////////////////////////////////
1373 
1374    //! <b>Effects</b>: Returns the comparison object out
1375    //!   of which a was constructed.
1376    //!
1377    //! <b>Complexity</b>: Constant.
1378    BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline
1379       key_compare key_comp() const
1380       { return dtl::force_copy<key_compare>(m_flat_tree.key_comp()); }
1381 
1382    //! <b>Effects</b>: Returns an object of value_compare constructed out
1383    //!   of the comparison object.
1384    //!
1385    //! <b>Complexity</b>: Constant.
1386    BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline
1387       value_compare value_comp() const
1388       { return value_compare(dtl::force_copy<key_compare>(m_flat_tree.key_comp())); }
1389 
1390    //////////////////////////////////////////////
1391    //
1392    //              map operations
1393    //
1394    //////////////////////////////////////////////
1395 
1396    //! <b>Returns</b>: An iterator pointing to an element with the key
1397    //!   equivalent to x, or end() if such an element is not found.
1398    //!
1399    //! <b>Complexity</b>: Logarithmic.
1400    BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline
1401       iterator find(const key_type& x)
1402       { return dtl::force_copy<iterator>(m_flat_tree.find(x)); }
1403 
1404    //! <b>Returns</b>: A const_iterator pointing to an element with the key
1405    //!   equivalent to x, or end() if such an element is not found.
1406    //!
1407    //! <b>Complexity</b>: Logarithmic.
1408    BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline
1409       const_iterator find(const key_type& x) const
1410       { return dtl::force_copy<const_iterator>(m_flat_tree.find(x)); }
1411 
1412    //! <b>Requires</b>: This overload is available only if
1413    //! key_compare::is_transparent exists.
1414    //!
1415    //! <b>Returns</b>: An iterator pointing to an element with the key
1416    //!   equivalent to x, or end() if such an element is not found.
1417    //!
1418    //! <b>Complexity</b>: Logarithmic.
1419    template<class K>
1420    BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline
1421       iterator find(const K& x)
1422       { return dtl::force_copy<iterator>(m_flat_tree.find(x)); }
1423 
1424    //! <b>Requires</b>: This overload is available only if
1425    //! key_compare::is_transparent exists.
1426    //!
1427    //! <b>Returns</b>: A const_iterator pointing to an element with the key
1428    //!   equivalent to x, or end() if such an element is not found.
1429    //!
1430    //! <b>Complexity</b>: Logarithmic.
1431    template<class K>
1432    BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline
1433       const_iterator find(const K& x) const
1434       { return dtl::force_copy<const_iterator>(m_flat_tree.find(x)); }
1435 
1436    //! <b>Returns</b>: The number of elements with key equivalent to x.
1437    //!
1438    //! <b>Complexity</b>: log(size())+count(k)
1439    BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline
1440       size_type count(const key_type& x) const
1441       {  return static_cast<size_type>(m_flat_tree.find(x) != m_flat_tree.end());  }
1442 
1443    //! <b>Requires</b>: This overload is available only if
1444    //! key_compare::is_transparent exists.
1445    //!
1446    //! <b>Returns</b>: The number of elements with key equivalent to x.
1447    //!
1448    //! <b>Complexity</b>: log(size())+count(k)
1449    template<class K>
1450    BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline
1451       size_type count(const K& x) const
1452       //Don't use find() != end optimization here as transparent comparators with key K might
1453       //return a different range than key_type (which can only return a single element range)
1454       {  return m_flat_tree.count(x);  }
1455 
1456    //! <b>Returns</b>: Returns true if there is an element with key
1457    //!   equivalent to key in the container, otherwise false.
1458    //!
1459    //! <b>Complexity</b>: log(size()).
1460    BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline
1461       bool contains(const key_type& x) const
1462       {  return m_flat_tree.find(x) != m_flat_tree.end();  }
1463 
1464    //! <b>Requires</b>: This overload is available only if
1465    //! key_compare::is_transparent exists.
1466    //!
1467    //! <b>Returns</b>: Returns true if there is an element with key
1468    //!   equivalent to key in the container, otherwise false.
1469    //!
1470    //! <b>Complexity</b>: log(size()).
1471    template<typename K>
1472    BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline
1473       bool contains(const K& x) const
1474       {  return m_flat_tree.find(x) != m_flat_tree.end();  }
1475 
1476    //! <b>Returns</b>: An iterator pointing to the first element with key not less
1477    //!   than x, or end() if such an element is not found.
1478    //!
1479    //! <b>Complexity</b>: Logarithmic.
1480    BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline
1481       iterator lower_bound(const key_type& x)
1482       {  return dtl::force_copy<iterator>(m_flat_tree.lower_bound(x)); }
1483 
1484    //! <b>Returns</b>: A const iterator pointing to the first element with key not
1485    //!   less than x, or end() if such an element is not found.
1486    //!
1487    //! <b>Complexity</b>: Logarithmic.
1488    BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline
1489       const_iterator lower_bound(const key_type& x) const
1490       {  return dtl::force_copy<const_iterator>(m_flat_tree.lower_bound(x)); }
1491 
1492    //! <b>Requires</b>: This overload is available only if
1493    //! key_compare::is_transparent exists.
1494    //!
1495    //! <b>Returns</b>: An iterator pointing to the first element with key not less
1496    //!   than x, or end() if such an element is not found.
1497    //!
1498    //! <b>Complexity</b>: Logarithmic.
1499    template<class K>
1500    BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline
1501       iterator lower_bound(const K& x)
1502       {  return dtl::force_copy<iterator>(m_flat_tree.lower_bound(x)); }
1503 
1504    //! <b>Requires</b>: This overload is available only if
1505    //! key_compare::is_transparent exists.
1506    //!
1507    //! <b>Returns</b>: A const iterator pointing to the first element with key not
1508    //!   less than x, or end() if such an element is not found.
1509    //!
1510    //! <b>Complexity</b>: Logarithmic.
1511    template<class K>
1512    BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline
1513       const_iterator lower_bound(const K& x) const
1514       {  return dtl::force_copy<const_iterator>(m_flat_tree.lower_bound(x)); }
1515 
1516    //! <b>Returns</b>: An iterator pointing to the first element with key greater
1517    //!   than x, or end() if such an element is not found.
1518    //!
1519    //! <b>Complexity</b>: Logarithmic.
1520    BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline
1521       iterator upper_bound(const key_type& x)
1522       {  return dtl::force_copy<iterator>(m_flat_tree.upper_bound(x)); }
1523 
1524    //! <b>Returns</b>: A const iterator pointing to the first element with key
1525    //!   greater than x, or end() if such an element is not found.
1526    //!
1527    //! <b>Complexity</b>: Logarithmic.
1528    BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline
1529       const_iterator upper_bound(const key_type& x) const
1530       {  return dtl::force_copy<const_iterator>(m_flat_tree.upper_bound(x)); }
1531 
1532    //! <b>Requires</b>: This overload is available only if
1533    //! key_compare::is_transparent exists.
1534    //!
1535    //! <b>Returns</b>: An iterator pointing to the first element with key greater
1536    //!   than x, or end() if such an element is not found.
1537    //!
1538    //! <b>Complexity</b>: Logarithmic.
1539    template<class K>
1540    BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline
1541       iterator upper_bound(const K& x)
1542       {  return dtl::force_copy<iterator>(m_flat_tree.upper_bound(x)); }
1543 
1544    //! <b>Requires</b>: This overload is available only if
1545    //! key_compare::is_transparent exists.
1546    //!
1547    //! <b>Returns</b>: A const iterator pointing to the first element with key
1548    //!   greater than x, or end() if such an element is not found.
1549    //!
1550    //! <b>Complexity</b>: Logarithmic.
1551    template<class K>
1552    BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline
1553       const_iterator upper_bound(const K& x) const
1554       {  return dtl::force_copy<const_iterator>(m_flat_tree.upper_bound(x)); }
1555 
1556    //! <b>Effects</b>: Equivalent to std::make_pair(this->lower_bound(k), this->upper_bound(k)).
1557    //!
1558    //! <b>Complexity</b>: Logarithmic.
1559    BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline
1560       std::pair<iterator,iterator> equal_range(const key_type& x)
1561       {  return dtl::force_copy<std::pair<iterator,iterator> >(m_flat_tree.lower_bound_range(x)); }
1562 
1563    //! <b>Effects</b>: Equivalent to std::make_pair(this->lower_bound(k), this->upper_bound(k)).
1564    //!
1565    //! <b>Complexity</b>: Logarithmic.
1566    BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline
1567       std::pair<const_iterator, const_iterator> equal_range(const key_type& x) const
1568       {  return dtl::force_copy<std::pair<const_iterator,const_iterator> >(m_flat_tree.lower_bound_range(x)); }
1569 
1570    //! <b>Requires</b>: This overload is available only if
1571    //! key_compare::is_transparent exists.
1572    //!
1573    //! <b>Effects</b>: Equivalent to std::make_pair(this->lower_bound(k), this->upper_bound(k)).
1574    //!
1575    //! <b>Complexity</b>: Logarithmic.
1576    template<class K>
1577    BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline
1578       std::pair<iterator,iterator> equal_range(const K& x)
1579       //Don't use lower_bound_range optimization here as transparent comparators with key K might
1580       //return a different range than key_type (which can only return a single element range)
1581       {  return dtl::force_copy<std::pair<iterator,iterator> >(m_flat_tree.equal_range(x)); }
1582 
1583    //! <b>Requires</b>: This overload is available only if
1584    //! key_compare::is_transparent exists.
1585    //!
1586    //! <b>Effects</b>: Equivalent to std::make_pair(this->lower_bound(k), this->upper_bound(k)).
1587    //!
1588    //! <b>Complexity</b>: Logarithmic.
1589    template<class K>
1590    BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline
1591       std::pair<const_iterator, const_iterator> equal_range(const K& x) const
1592       //Don't use lower_bound_range optimization here as transparent comparators with key K might
1593       //return a different range than key_type (which can only return a single element range)
1594       {  return dtl::force_copy<std::pair<const_iterator,const_iterator> >(m_flat_tree.equal_range(x)); }
1595 
1596    //! <b>Effects</b>: Extracts the internal sequence container.
1597    //!
1598    //! <b>Complexity</b>: Same as the move constructor of sequence_type, usually constant.
1599    //!
1600    //! <b>Postcondition</b>: this->empty()
1601    //!
1602    //! <b>Throws</b>: If secuence_type's move constructor throws 
1603    BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline sequence_type extract_sequence()
1604    {
1605       return boost::move(dtl::force<sequence_type>(m_flat_tree.get_sequence_ref()));
1606    }
1607 
1608    //! <b>Effects</b>: Discards the internally hold sequence container and adopts the
1609    //!   one passed externally using the move assignment. Erases non-unique elements.
1610    //!
1611    //! <b>Complexity</b>: Assuming O(1) move assignment, O(NlogN) with N = seq.size()
1612    //!
1613    //! <b>Throws</b>: If the comparison or the move constructor throws
1614    inline void adopt_sequence(BOOST_RV_REF(sequence_type) seq)
1615    {  this->m_flat_tree.adopt_sequence_unique(boost::move(dtl::force<impl_sequence_type>(seq)));  }
1616 
1617    //! <b>Requires</b>: seq shall be ordered according to this->compare()
1618    //!   and shall contain unique elements.
1619    //!
1620    //! <b>Effects</b>: Discards the internally hold sequence container and adopts the
1621    //!   one passed externally using the move assignment.
1622    //!
1623    //! <b>Complexity</b>: Assuming O(1) move assignment, O(1)
1624    //!
1625    //! <b>Throws</b>: If the move assignment throws
1626    inline void adopt_sequence(ordered_unique_range_t, BOOST_RV_REF(sequence_type) seq)
1627    {  this->m_flat_tree.adopt_sequence_unique(ordered_unique_range_t(), boost::move(dtl::force<impl_sequence_type>(seq)));  }
1628 
1629    //! <b>Effects</b>: Returns a const view of the underlying sequence.
1630    //!
1631    //! <b>Complexity</b>: Constant
1632    //!
1633    //! <b>Throws</b>: Nothing
1634    inline const sequence_type & sequence() const BOOST_NOEXCEPT
1635    {  return dtl::force<sequence_type>(m_flat_tree.get_sequence_cref());  }
1636 
1637    //! <b>Effects</b>: Returns true if x and y are equal
1638    //!
1639    //! <b>Complexity</b>: Linear to the number of elements in the container.
1640    BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline
1641       friend bool operator==(const flat_map& x, const flat_map& y)
1642    {  return x.size() == y.size() && ::boost::container::algo_equal(x.begin(), x.end(), y.begin());  }
1643 
1644    //! <b>Effects</b>: Returns true if x and y are unequal
1645    //!
1646    //! <b>Complexity</b>: Linear to the number of elements in the container.
1647    BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline
1648       friend bool operator!=(const flat_map& x, const flat_map& y)
1649    {  return !(x == y); }
1650 
1651    //! <b>Effects</b>: Returns true if x is less than y
1652    //!
1653    //! <b>Complexity</b>: Linear to the number of elements in the container.
1654    BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline
1655       friend bool operator<(const flat_map& x, const flat_map& y)
1656    {  return ::boost::container::algo_lexicographical_compare(x.begin(), x.end(), y.begin(), y.end());  }
1657 
1658    //! <b>Effects</b>: Returns true if x is greater than y
1659    //!
1660    //! <b>Complexity</b>: Linear to the number of elements in the container.
1661    BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline
1662       friend bool operator>(const flat_map& x, const flat_map& y)
1663    {  return y < x;  }
1664 
1665    //! <b>Effects</b>: Returns true if x is equal or less than y
1666    //!
1667    //! <b>Complexity</b>: Linear to the number of elements in the container.
1668    BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline
1669       friend bool operator<=(const flat_map& x, const flat_map& y)
1670    {  return !(y < x);  }
1671 
1672    //! <b>Effects</b>: Returns true if x is equal or greater than y
1673    //!
1674    //! <b>Complexity</b>: Linear to the number of elements in the container.
1675    BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline
1676       friend bool operator>=(const flat_map& x, const flat_map& y)
1677    {  return !(x < y);  }
1678 
1679    //! <b>Effects</b>: x.swap(y)
1680    //!
1681    //! <b>Complexity</b>: Constant.
1682    inline friend void swap(flat_map& x, flat_map& y)
1683        BOOST_NOEXCEPT_IF(BOOST_NOEXCEPT(x.swap(y)))
1684    {  x.swap(y);  }
1685 
1686    #ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
1687    private:
1688    mapped_type &priv_subscript(const key_type& k)
1689    {
1690       iterator i = this->lower_bound(k);
1691       // i->first is greater than or equivalent to k.
1692       if (i == end() || key_comp()(k, (*i).first)){
1693          dtl::value_init<mapped_type> m;
1694          impl_value_type v(k, ::boost::move(m.m_t));
1695          i = dtl::force_copy<iterator>(this->m_flat_tree.insert_equal(::boost::move(v)));
1696       }
1697       return (*i).second;
1698    }
1699    mapped_type &priv_subscript(BOOST_RV_REF(key_type) mk)
1700    {
1701       key_type &k = mk;
1702       iterator i = this->lower_bound(k);
1703       // i->first is greater than or equivalent to k.
1704       if (i == end() || key_comp()(k, (*i).first)) {
1705          dtl::value_init<mapped_type> m;
1706          impl_value_type v(::boost::move(k), ::boost::move(m.m_t));
1707          i = dtl::force_copy<iterator>(this->m_flat_tree.insert_equal(::boost::move(v)));
1708       }
1709       return (*i).second;
1710    }
1711    #endif   //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
1712 };
1713 
1714 #ifndef BOOST_CONTAINER_NO_CXX17_CTAD
1715 
1716 template <typename InputIterator>
1717 flat_map(InputIterator, InputIterator) ->
1718    flat_map< it_based_non_const_first_type_t<InputIterator>
1719            , it_based_second_type_t<InputIterator>>;
1720 
1721 template < typename InputIterator, typename AllocatorOrCompare>
1722     flat_map(InputIterator, InputIterator, AllocatorOrCompare const&) ->
1723     flat_map< it_based_non_const_first_type_t<InputIterator>
1724             , it_based_second_type_t<InputIterator>
1725             , typename dtl::if_c< // Compare
1726                 dtl::is_allocator<AllocatorOrCompare>::value
1727                 , std::less<it_based_non_const_first_type_t<InputIterator>>
1728                 , AllocatorOrCompare
1729             >::type
1730             , typename dtl::if_c< // Allocator
1731                 dtl::is_allocator<AllocatorOrCompare>::value
1732                 , AllocatorOrCompare
1733                 , new_allocator<std::pair<it_based_non_const_first_type_t<InputIterator>, it_based_second_type_t<InputIterator>>>
1734                 >::type
1735             >;
1736 
1737 template < typename InputIterator, typename Compare, typename Allocator
1738          , typename = dtl::require_nonallocator_t<Compare>
1739          , typename = dtl::require_allocator_t<Allocator>>
1740 flat_map(InputIterator, InputIterator, Compare const&, Allocator const&) ->
1741    flat_map< it_based_non_const_first_type_t<InputIterator>
1742            , it_based_second_type_t<InputIterator>
1743            , Compare
1744            , Allocator>;
1745 
1746 template <typename InputIterator>
1747 flat_map(ordered_unique_range_t, InputIterator, InputIterator) ->
1748    flat_map< it_based_non_const_first_type_t<InputIterator>
1749            , it_based_second_type_t<InputIterator>>;
1750 
1751 template < typename InputIterator, typename AllocatorOrCompare>
1752 flat_map(ordered_unique_range_t, InputIterator, InputIterator, AllocatorOrCompare const&) ->
1753    flat_map< it_based_non_const_first_type_t<InputIterator>
1754            , it_based_second_type_t<InputIterator>
1755            , typename dtl::if_c<   // Compare
1756                dtl::is_allocator<AllocatorOrCompare>::value
1757                , std::less<it_based_non_const_first_type_t<InputIterator>>
1758                , AllocatorOrCompare
1759                >::type
1760            , typename dtl::if_c<   // Allocator
1761                dtl::is_allocator<AllocatorOrCompare>::value
1762                , AllocatorOrCompare
1763                , new_allocator<std::pair<it_based_non_const_first_type_t<InputIterator>, it_based_second_type_t<InputIterator>>>
1764                >::type
1765            >;
1766 
1767 template < typename InputIterator, typename Compare, typename Allocator
1768          , typename = dtl::require_nonallocator_t<Compare>
1769          , typename = dtl::require_allocator_t<Allocator>>
1770 flat_map(ordered_unique_range_t, InputIterator, InputIterator, Compare const&, Allocator const&) ->
1771    flat_map< it_based_non_const_first_type_t<InputIterator>
1772            , it_based_second_type_t<InputIterator>
1773            , Compare
1774            , Allocator>;
1775 
1776 #endif
1777 
1778 #ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
1779 
1780 }  //namespace container {
1781 
1782 //!has_trivial_destructor_after_move<> == true_type
1783 //!specialization for optimizations
1784 template <class Key, class T, class Compare, class AllocatorOrContainer>
1785 struct has_trivial_destructor_after_move<boost::container::flat_map<Key, T, Compare, AllocatorOrContainer> >
1786 {
1787    typedef typename boost::container::flat_map<Key, T, Compare, AllocatorOrContainer>::value_type value_t;
1788    typedef typename ::boost::container::dtl::container_or_allocator_rebind<AllocatorOrContainer, value_t>::type alloc_or_cont_t;
1789    typedef ::boost::container::dtl::flat_tree<value_t,::boost::container::dtl::select1st<Key>, Compare, alloc_or_cont_t> tree;
1790    BOOST_STATIC_CONSTEXPR bool value = ::boost::has_trivial_destructor_after_move<tree>::value;
1791 };
1792 
1793 namespace container {
1794 
1795 #endif   //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
1796 
1797 //! A flat_multimap is a kind of associative container that supports equivalent keys
1798 //! (possibly containing multiple copies of the same key value) and provides for
1799 //! fast retrieval of values of another type T based on the keys. 
1800 //!
1801 //! A flat_multimap satisfies all of the requirements of a container and of a reversible
1802 //! container and of an associative container. For a
1803 //! flat_multimap<Key,T> the key_type is Key and the value_type is std::pair<Key,T>
1804 //! (unlike std::multimap<Key, T> which value_type is std::pair<<b>const</b> Key, T>).
1805 //!
1806 //! flat_multimap is similar to std::multimap but it's implemented by as an ordered sequence container.
1807 //! The underlying sequence container is by default <i>vector</i> but it can also work
1808 //! user-provided vector-like SequenceContainers (like <i>static_vector</i> or <i>small_vector</i>).
1809 //!
1810 //! Using vector-like sequence containers means that inserting a new element into a flat_multimap might invalidate
1811 //! previous iterators and references (unless that sequence container is <i>stable_vector</i> or a similar
1812 //! container that offers stable pointers and references). Similarly, erasing an element might invalidate
1813 //! iterators and references pointing to elements that come after (their keys are bigger) the erased element.
1814 //!
1815 //! This container provides random-access iterators.
1816 //!
1817 //! \tparam Key is the key_type of the map
1818 //! \tparam Value is the <code>mapped_type</code>
1819 //! \tparam Compare is the ordering function for Keys (e.g. <i>std::less<Key></i>).
1820 //! \tparam AllocatorOrContainer is either:
1821 //!   - The allocator to allocate <code>value_type</code>s (e.g. <i>allocator< std::pair<Key, T> > </i>).
1822 //!     (in this case <i>sequence_type</i> will be vector<value_type, AllocatorOrContainer>)
1823 //!   - The SequenceContainer to be used as the underlying <i>sequence_type</i>. It must be a vector-like
1824 //!     sequence container with random-access iterators.
1825 #ifdef BOOST_CONTAINER_DOXYGEN_INVOKED
1826 template <class Key, class T, class Compare = std::less<Key>, class AllocatorOrContainer = new_allocator< std::pair< Key, T> > >
1827 #else
1828 template <class Key, class T, class Compare, class AllocatorOrContainer>
1829 #endif
1830 class flat_multimap
1831 {
1832    #ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
1833    private:
1834    BOOST_COPYABLE_AND_MOVABLE(flat_multimap)
1835    typedef std::pair<Key, T> std_pair_t;
1836    typedef dtl::flat_tree<
1837                            std_pair_t,
1838                            dtl::select1st<Key>,
1839                            Compare,
1840                            AllocatorOrContainer> tree_t;
1841    //This is the real tree stored here. It's based on a movable pair
1842    typedef dtl::pair<Key, T> dtl_pair_t;
1843    #ifdef BOOST_CONTAINER_STD_PAIR_IS_MOVABLE
1844    typedef std_pair_t impl_pair_t;
1845    #else
1846    typedef dtl_pair_t impl_pair_t;
1847    #endif
1848    typedef dtl::flat_tree<
1849                            impl_pair_t,
1850                            dtl::select1st<Key>,
1851                            Compare,
1852                            typename dtl::container_or_allocator_rebind<AllocatorOrContainer, impl_pair_t >::type
1853                            > impl_tree_t;
1854    impl_tree_t m_flat_tree;  // flat tree representing flat_map
1855 
1856    typedef typename impl_tree_t::value_type              impl_value_type;
1857    typedef typename impl_tree_t::const_iterator          impl_const_iterator;
1858    typedef typename impl_tree_t::iterator                impl_iterator;
1859    typedef typename impl_tree_t::allocator_type          impl_allocator_type;
1860    #if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
1861    typedef std::initializer_list<impl_value_type>        impl_initializer_list;
1862    #endif
1863 
1864    typedef dtl::flat_tree_value_compare
1865       < Compare
1866       , dtl::select1st<Key>
1867       , std::pair<Key, T> >                                 value_compare_t;
1868    typedef typename tree_t::iterator                        iterator_t;
1869    typedef typename tree_t::const_iterator                  const_iterator_t;
1870    typedef typename tree_t::reverse_iterator                reverse_iterator_t;
1871    typedef typename tree_t::const_reverse_iterator          const_reverse_iterator_t;
1872 
1873    public:
1874    typedef typename impl_tree_t::stored_allocator_type      impl_stored_allocator_type;
1875    typedef typename impl_tree_t::sequence_type              impl_sequence_type;
1876 
1877    inline impl_tree_t &tree()
1878    {  return m_flat_tree;  }
1879 
1880    inline const impl_tree_t &tree() const
1881    {  return m_flat_tree;  }
1882 
1883    private:
1884    #endif   //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
1885 
1886    public:
1887 
1888    //////////////////////////////////////////////
1889    //
1890    //                    types
1891    //
1892    //////////////////////////////////////////////
1893    typedef Key                                                                      key_type;
1894    typedef T                                                                        mapped_type;
1895    typedef Compare                                                                  key_compare;
1896    typedef std::pair<Key, T>                                                        value_type;
1897    typedef typename BOOST_CONTAINER_IMPDEF(tree_t::sequence_type)                   sequence_type;
1898    typedef typename sequence_type::allocator_type                                   allocator_type;
1899    typedef ::boost::container::allocator_traits<allocator_type>                     allocator_traits_type;
1900    typedef typename sequence_type::pointer                                          pointer;
1901    typedef typename sequence_type::const_pointer                                    const_pointer;
1902    typedef typename sequence_type::reference                                        reference;
1903    typedef typename sequence_type::const_reference                                  const_reference;
1904    typedef typename sequence_type::size_type                                        size_type;
1905    typedef typename sequence_type::difference_type                                  difference_type;
1906    typedef typename BOOST_CONTAINER_IMPDEF(tree_t::stored_allocator_type)           stored_allocator_type;
1907    typedef typename BOOST_CONTAINER_IMPDEF(tree_t::value_compare)                   value_compare;
1908 
1909    typedef typename sequence_type::iterator                                         iterator;
1910    typedef typename sequence_type::const_iterator                                   const_iterator;
1911    typedef typename sequence_type::reverse_iterator                                 reverse_iterator;
1912    typedef typename sequence_type::const_reverse_iterator                           const_reverse_iterator;
1913    typedef BOOST_CONTAINER_IMPDEF(impl_value_type)                                  movable_value_type;
1914 
1915    //AllocatorOrContainer::value_type must be std::pair<Key, T>
1916    BOOST_CONTAINER_STATIC_ASSERT((dtl::is_same<std::pair<Key, T>, value_type>::value));
1917 
1918    //////////////////////////////////////////////
1919    //
1920    //          construct/copy/destroy
1921    //
1922    //////////////////////////////////////////////
1923 
1924    //! <b>Effects</b>: Default constructs an empty flat_map.
1925    //!
1926    //! <b>Complexity</b>: Constant.
1927    inline flat_multimap()
1928       BOOST_NOEXCEPT_IF(dtl::is_nothrow_default_constructible<AllocatorOrContainer>::value &&
1929                         dtl::is_nothrow_default_constructible<Compare>::value)
1930       : m_flat_tree()
1931    {}
1932 
1933    //! <b>Effects</b>: Constructs an empty flat_multimap using the specified allocator.
1934    //!
1935    //! <b>Complexity</b>: Constant.
1936    inline explicit flat_multimap(const allocator_type& a)
1937       : m_flat_tree(dtl::force<const impl_allocator_type>(a))
1938    {}
1939 
1940    //! <b>Effects</b>: Constructs an empty flat_multimap using the specified comparison
1941    //!   object .
1942    //!
1943    //! <b>Complexity</b>: Constant.
1944    inline explicit flat_multimap(const Compare& comp)
1945       : m_flat_tree(comp)
1946    {}
1947 
1948    //! <b>Effects</b>: Constructs an empty flat_multimap using the specified comparison
1949    //!   object and allocator.
1950    //!
1951    //! <b>Complexity</b>: Constant.
1952    inline
1953    flat_multimap(const Compare& comp, const allocator_type& a)
1954       : m_flat_tree(comp, dtl::force<const impl_allocator_type>(a))
1955    {}
1956 
1957    //! <b>Effects</b>: Constructs an empty flat_multimap
1958    //!   and inserts elements from the range [first ,last ).
1959    //!
1960    //! <b>Complexity</b>: Linear in N if the range [first ,last ) is already sorted using
1961    //! the predicate and otherwise N logN, where N is last - first.
1962    template <class InputIterator>
1963    inline
1964    flat_multimap(InputIterator first, InputIterator last)
1965       : m_flat_tree(false, first, last)
1966    {}
1967 
1968    //! <b>Effects</b>: Constructs an empty flat_multimap using the specified
1969    //!   allocator, and inserts elements from the range [first ,last ).
1970    //!
1971    //! <b>Complexity</b>: Linear in N if the range [first ,last ) is already sorted using
1972    //! the predicate and otherwise N logN, where N is last - first.
1973    template <class InputIterator>
1974    inline
1975    flat_multimap(InputIterator first, InputIterator last, const allocator_type& a)
1976       : m_flat_tree(false, first, last, dtl::force<const impl_allocator_type>(a))
1977    {}
1978 
1979    //! <b>Effects</b>: Constructs an empty flat_multimap using the specified comparison object
1980    //!   and inserts elements from the range [first ,last ).
1981    //!
1982    //! <b>Complexity</b>: Linear in N if the range [first ,last ) is already sorted using
1983    //! the predicate and otherwise N logN, where N is last - first.
1984    template <class InputIterator>
1985    inline
1986    flat_multimap(InputIterator first, InputIterator last, const Compare& comp)
1987       : m_flat_tree(false, first, last, comp)
1988    {}
1989 
1990    //! <b>Effects</b>: Constructs an empty flat_multimap using the specified comparison object
1991    //!   and allocator, and inserts elements from the range [first ,last ).
1992    //!
1993    //! <b>Complexity</b>: Linear in N if the range [first ,last ) is already sorted using
1994    //! the predicate and otherwise N logN, where N is last - first.
1995    template <class InputIterator>
1996    inline
1997    flat_multimap(InputIterator first, InputIterator last, const Compare& comp, const allocator_type& a)
1998       : m_flat_tree(false, first, last, comp, dtl::force<const impl_allocator_type>(a))
1999    {}
2000 
2001    //! <b>Effects</b>: Constructs an empty flat_multimap
2002    //! and inserts elements from the ordered range [first ,last). This function
2003    //! is more efficient than the normal range creation for ordered ranges.
2004    //!
2005    //! <b>Requires</b>: [first ,last) must be ordered according to the predicate.
2006    //!
2007    //! <b>Complexity</b>: Linear in N.
2008    //!
2009    //! <b>Note</b>: Non-standard extension.
2010    template <class InputIterator>
2011    inline
2012    flat_multimap(ordered_range_t, InputIterator first, InputIterator last)
2013       : m_flat_tree(ordered_range, first, last)
2014    {}
2015 
2016    //! <b>Effects</b>: Constructs an empty flat_multimap using the specified comparison object and
2017    //! inserts elements from the ordered range [first ,last). This function
2018    //! is more efficient than the normal range creation for ordered ranges.
2019    //!
2020    //! <b>Requires</b>: [first ,last) must be ordered according to the predicate.
2021    //!
2022    //! <b>Complexity</b>: Linear in N.
2023    //!
2024    //! <b>Note</b>: Non-standard extension.
2025    template <class InputIterator>
2026    inline
2027    flat_multimap(ordered_range_t, InputIterator first, InputIterator last, const Compare& comp)
2028       : m_flat_tree(ordered_range, first, last, comp)
2029    {}
2030 
2031    //! <b>Effects</b>: Constructs an empty flat_multimap using the specified comparison object and
2032    //! allocator, and inserts elements from the ordered range [first ,last). This function
2033    //! is more efficient than the normal range creation for ordered ranges.
2034    //!
2035    //! <b>Requires</b>: [first ,last) must be ordered according to the predicate.
2036    //!
2037    //! <b>Complexity</b>: Linear in N.
2038    //!
2039    //! <b>Note</b>: Non-standard extension.
2040    template <class InputIterator>
2041    inline
2042    flat_multimap(ordered_range_t, InputIterator first, InputIterator last, const Compare& comp, const allocator_type& a)
2043       : m_flat_tree(ordered_range, first, last, comp, a)
2044    {}
2045 
2046    //! <b>Effects</b>: Constructs an empty flat_multimap using the specified comparison object and
2047    //! inserts elements from the ordered range [first ,last). This function
2048    //! is more efficient than the normal range creation for ordered ranges.
2049    //!
2050    //! <b>Requires</b>: [first ,last) must be ordered according to the predicate.
2051    //!
2052    //! <b>Complexity</b>: Linear in N.
2053    //!
2054    //! <b>Note</b>: Non-standard extension.
2055    template <class InputIterator>
2056    inline
2057       flat_multimap(ordered_range_t, InputIterator first, InputIterator last, const allocator_type &a)
2058       : m_flat_tree(ordered_range, first, last, Compare(), a)
2059    {}
2060 
2061 #if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
2062    //! <b>Effects</b>: Constructs an empty flat_map and
2063    //! inserts elements from the range [il.begin(), il.end()).
2064    //!
2065    //! <b>Complexity</b>: Linear in N if the range [il.begin(), il.end()) is already sorted using
2066    //! the predicate and otherwise N logN, where N is last - first.
2067    inline
2068    flat_multimap(std::initializer_list<value_type> il)
2069       : m_flat_tree( false
2070                    , dtl::force<impl_initializer_list>(il).begin()
2071                    , dtl::force<impl_initializer_list>(il).end())
2072    {}
2073 
2074    //! <b>Effects</b>: Constructs an empty flat_map using the specified
2075    //! allocator, and inserts elements from the range [il.begin(), il.end()).
2076    //!
2077    //! <b>Complexity</b>: Linear in N if the range [il.begin(), il.end()) is already sorted using
2078    //! the predicate and otherwise N logN, where N is last - first.
2079    inline
2080    flat_multimap(std::initializer_list<value_type> il, const allocator_type& a)
2081       : m_flat_tree(false
2082                    , dtl::force<impl_initializer_list>(il).begin()
2083                    , dtl::force<impl_initializer_list>(il).end()
2084                    , dtl::force<const impl_allocator_type>(a))
2085    {}
2086 
2087    //! <b>Effects</b>: Constructs an empty flat_map using the specified comparison object and
2088    //! inserts elements from the range [il.begin(), il.end()).
2089    //!
2090    //! <b>Complexity</b>: Linear in N if the range [il.begin(), il.end()) is already sorted using
2091    //! the predicate and otherwise N logN, where N is last - first.
2092    inline
2093    flat_multimap(std::initializer_list<value_type> il, const Compare& comp)
2094       : m_flat_tree(false
2095                    , dtl::force<impl_initializer_list>(il).begin()
2096                    , dtl::force<impl_initializer_list>(il).end(), comp)
2097    {}
2098 
2099    //! <b>Effects</b>: Constructs an empty flat_map using the specified comparison object and
2100    //! allocator, and inserts elements from the range [il.begin(), il.end()).
2101    //!
2102    //! <b>Complexity</b>: Linear in N if the range [il.begin(), il.end()) is already sorted using
2103    //! the predicate and otherwise N logN, where N is last - first.
2104    inline
2105    flat_multimap(std::initializer_list<value_type> il, const Compare& comp, const allocator_type& a)
2106       : m_flat_tree( false
2107                    , dtl::force<impl_initializer_list>(il).begin()
2108                    , dtl::force<impl_initializer_list>(il).end()
2109                    , comp, dtl::force<const impl_allocator_type>(a))
2110    {}
2111 
2112    //! <b>Effects</b>: Constructs an empty flat_multimap and
2113    //! inserts elements from the ordered range [il.begin(), il.end()). This function
2114    //! is more efficient than the normal range creation for ordered ranges.
2115    //!
2116    //! <b>Requires</b>: [il.begin(), il.end()) must be ordered according to the predicate.
2117    //!
2118    //! <b>Complexity</b>: Linear in N.
2119    //!
2120    //! <b>Note</b>: Non-standard extension.
2121    inline
2122    flat_multimap(ordered_range_t, std::initializer_list<value_type> il)
2123       : m_flat_tree( ordered_range
2124                    , dtl::force<impl_initializer_list>(il).begin()
2125                    , dtl::force<impl_initializer_list>(il).end())
2126    {}
2127 
2128    //! <b>Effects</b>: Constructs an empty flat_multimap using the specified comparison object and
2129    //! inserts elements from the ordered range [il.begin(), il.end()). This function
2130    //! is more efficient than the normal range creation for ordered ranges.
2131    //!
2132    //! <b>Requires</b>: [il.begin(), il.end()) must be ordered according to the predicate.
2133    //!
2134    //! <b>Complexity</b>: Linear in N.
2135    //!
2136    //! <b>Note</b>: Non-standard extension.
2137    inline
2138    flat_multimap(ordered_range_t, std::initializer_list<value_type> il, const Compare& comp)
2139       : m_flat_tree( ordered_range
2140                    , dtl::force<impl_initializer_list>(il).begin()
2141                    , dtl::force<impl_initializer_list>(il).end(), comp)
2142    {}
2143 
2144    //! <b>Effects</b>: Constructs an empty flat_multimap using the specified comparison object and
2145    //! allocator, and inserts elements from the ordered range [il.begin(), il.end()). This function
2146    //! is more efficient than the normal range creation for ordered ranges.
2147    //!
2148    //! <b>Requires</b>: [il.begin(), il.end()) must be ordered according to the predicate.
2149    //!
2150    //! <b>Complexity</b>: Linear in N.
2151    //!
2152    //! <b>Note</b>: Non-standard extension.
2153    inline
2154    flat_multimap(ordered_range_t, std::initializer_list<value_type> il, const Compare& comp, const allocator_type& a)
2155       : m_flat_tree( ordered_range
2156                    , dtl::force<impl_initializer_list>(il).begin()
2157                    , dtl::force<impl_initializer_list>(il).end()
2158                    , comp, dtl::force<const impl_allocator_type>(a))
2159    {}
2160 #endif
2161 
2162    //! <b>Effects</b>: Copy constructs a flat_multimap.
2163    //!
2164    //! <b>Complexity</b>: Linear in x.size().
2165    inline
2166    flat_multimap(const flat_multimap& x)
2167       : m_flat_tree(x.m_flat_tree)
2168    {}
2169 
2170    //! <b>Effects</b>: Move constructs a flat_multimap. Constructs *this using x's resources.
2171    //!
2172    //! <b>Complexity</b>: Constant.
2173    //!
2174    //! <b>Postcondition</b>: x is emptied.
2175    inline
2176    flat_multimap(BOOST_RV_REF(flat_multimap) x)
2177       BOOST_NOEXCEPT_IF(boost::container::dtl::is_nothrow_move_constructible<Compare>::value)
2178       : m_flat_tree(boost::move(x.m_flat_tree))
2179    {}
2180 
2181    //! <b>Effects</b>: Copy constructs a flat_multimap using the specified allocator.
2182    //!
2183    //! <b>Complexity</b>: Linear in x.size().
2184    inline
2185    flat_multimap(const flat_multimap& x, const allocator_type &a)
2186       : m_flat_tree(x.m_flat_tree, dtl::force<const impl_allocator_type>(a))
2187    {}
2188 
2189    //! <b>Effects</b>: Move constructs a flat_multimap using the specified allocator.
2190    //!                 Constructs *this using x's resources.
2191    //!
2192    //! <b>Complexity</b>: Constant if a == x.get_allocator(), linear otherwise.
2193    inline
2194    flat_multimap(BOOST_RV_REF(flat_multimap) x, const allocator_type &a)
2195       : m_flat_tree(boost::move(x.m_flat_tree), dtl::force<const impl_allocator_type>(a))
2196    {}
2197 
2198    //! <b>Effects</b>: Makes *this a copy of x.
2199    //!
2200    //! <b>Complexity</b>: Linear in x.size().
2201    inline
2202    flat_multimap& operator=(BOOST_COPY_ASSIGN_REF(flat_multimap) x)
2203       {  m_flat_tree = x.m_flat_tree;   return *this;  }
2204 
2205    //! <b>Effects</b>: this->swap(x.get()).
2206    //!
2207    //! <b>Complexity</b>: Constant.
2208    inline
2209    flat_multimap& operator=(BOOST_RV_REF(flat_multimap) x)
2210       BOOST_NOEXCEPT_IF( (allocator_traits_type::propagate_on_container_move_assignment::value ||
2211                           allocator_traits_type::is_always_equal::value) &&
2212                            boost::container::dtl::is_nothrow_move_assignable<Compare>::value)
2213       {  m_flat_tree = boost::move(x.m_flat_tree);   return *this;  }
2214 
2215 #if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
2216    //! <b>Effects</b>: Assign content of il to *this
2217    //!
2218    //! <b>Complexity</b>: Linear in il.size().
2219    inline
2220    flat_multimap& operator=(std::initializer_list<value_type> il)
2221    {
2222       this->clear();
2223       this->insert(il.begin(), il.end());
2224       return *this;
2225    }
2226 #endif
2227 
2228    //! <b>Effects</b>: Returns a copy of the allocator that
2229    //!   was passed to the object's constructor.
2230    //!
2231    //! <b>Complexity</b>: Constant.
2232    BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline
2233    allocator_type get_allocator() const BOOST_NOEXCEPT_OR_NOTHROW
2234       { return dtl::force_copy<allocator_type>(m_flat_tree.get_allocator()); }
2235 
2236    //! <b>Effects</b>: Returns a reference to the internal allocator.
2237    //!
2238    //! <b>Throws</b>: Nothing
2239    //!
2240    //! <b>Complexity</b>: Constant.
2241    //!
2242    //! <b>Note</b>: Non-standard extension.
2243    BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline
2244    stored_allocator_type &get_stored_allocator() BOOST_NOEXCEPT_OR_NOTHROW
2245       { return dtl::force<stored_allocator_type>(m_flat_tree.get_stored_allocator()); }
2246 
2247    //! <b>Effects</b>: Returns a reference to the internal allocator.
2248    //!
2249    //! <b>Throws</b>: Nothing
2250    //!
2251    //! <b>Complexity</b>: Constant.
2252    //!
2253    //! <b>Note</b>: Non-standard extension.
2254    BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline
2255    const stored_allocator_type &get_stored_allocator() const BOOST_NOEXCEPT_OR_NOTHROW
2256       { return dtl::force<const stored_allocator_type>(m_flat_tree.get_stored_allocator()); }
2257 
2258    //////////////////////////////////////////////
2259    //
2260    //                iterators
2261    //
2262    //////////////////////////////////////////////
2263 
2264    //! <b>Effects</b>: Returns an iterator to the first element contained in the container.
2265    //!
2266    //! <b>Throws</b>: Nothing.
2267    //!
2268    //! <b>Complexity</b>: Constant.
2269    BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline
2270    iterator begin() BOOST_NOEXCEPT_OR_NOTHROW
2271       { return dtl::force_copy<iterator>(m_flat_tree.begin()); }
2272 
2273    //! <b>Effects</b>: Returns a const_iterator to the first element contained in the container.
2274    //!
2275    //! <b>Throws</b>: Nothing.
2276    //!
2277    //! <b>Complexity</b>: Constant.
2278    BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline
2279    const_iterator begin() const BOOST_NOEXCEPT_OR_NOTHROW
2280       { return dtl::force_copy<const_iterator>(m_flat_tree.begin()); }
2281 
2282    //! <b>Effects</b>: Returns an iterator to the end of the container.
2283    //!
2284    //! <b>Throws</b>: Nothing.
2285    //!
2286    //! <b>Complexity</b>: Constant.
2287    BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline
2288    iterator end() BOOST_NOEXCEPT_OR_NOTHROW
2289       { return dtl::force_copy<iterator>(m_flat_tree.end()); }
2290 
2291    //! <b>Effects</b>: Returns a const_iterator to the end of the container.
2292    //!
2293    //! <b>Throws</b>: Nothing.
2294    //!
2295    //! <b>Complexity</b>: Constant.
2296    BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline
2297    const_iterator end() const BOOST_NOEXCEPT_OR_NOTHROW
2298       { return dtl::force_copy<const_iterator>(m_flat_tree.end()); }
2299 
2300    //! <b>Effects</b>: Returns a reverse_iterator pointing to the beginning
2301    //! of the reversed container.
2302    //!
2303    //! <b>Throws</b>: Nothing.
2304    //!
2305    //! <b>Complexity</b>: Constant.
2306    BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline
2307    reverse_iterator rbegin() BOOST_NOEXCEPT_OR_NOTHROW
2308       { return dtl::force_copy<reverse_iterator>(m_flat_tree.rbegin()); }
2309 
2310    //! <b>Effects</b>: Returns a const_reverse_iterator pointing to the beginning
2311    //! of the reversed container.
2312    //!
2313    //! <b>Throws</b>: Nothing.
2314    //!
2315    //! <b>Complexity</b>: Constant.
2316    BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline
2317    const_reverse_iterator rbegin() const BOOST_NOEXCEPT_OR_NOTHROW
2318       { return dtl::force_copy<const_reverse_iterator>(m_flat_tree.rbegin()); }
2319 
2320    //! <b>Effects</b>: Returns a reverse_iterator pointing to the end
2321    //! of the reversed container.
2322    //!
2323    //! <b>Throws</b>: Nothing.
2324    //!
2325    //! <b>Complexity</b>: Constant.
2326    BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline
2327    reverse_iterator rend() BOOST_NOEXCEPT_OR_NOTHROW
2328       { return dtl::force_copy<reverse_iterator>(m_flat_tree.rend()); }
2329 
2330    //! <b>Effects</b>: Returns a const_reverse_iterator pointing to the end
2331    //! of the reversed container.
2332    //!
2333    //! <b>Throws</b>: Nothing.
2334    //!
2335    //! <b>Complexity</b>: Constant.
2336    BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline
2337    const_reverse_iterator rend() const BOOST_NOEXCEPT_OR_NOTHROW
2338       { return dtl::force_copy<const_reverse_iterator>(m_flat_tree.rend()); }
2339 
2340    //! <b>Effects</b>: Returns a const_iterator to the first element contained in the container.
2341    //!
2342    //! <b>Throws</b>: Nothing.
2343    //!
2344    //! <b>Complexity</b>: Constant.
2345    BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline
2346    const_iterator cbegin() const BOOST_NOEXCEPT_OR_NOTHROW
2347       { return dtl::force_copy<const_iterator>(m_flat_tree.cbegin()); }
2348 
2349    //! <b>Effects</b>: Returns a const_iterator to the end of the container.
2350    //!
2351    //! <b>Throws</b>: Nothing.
2352    //!
2353    //! <b>Complexity</b>: Constant.
2354    BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline
2355    const_iterator cend() const BOOST_NOEXCEPT_OR_NOTHROW
2356       { return dtl::force_copy<const_iterator>(m_flat_tree.cend()); }
2357 
2358    //! <b>Effects</b>: Returns a const_reverse_iterator pointing to the beginning
2359    //! of the reversed container.
2360    //!
2361    //! <b>Throws</b>: Nothing.
2362    //!
2363    //! <b>Complexity</b>: Constant.
2364    BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline
2365    const_reverse_iterator crbegin() const BOOST_NOEXCEPT_OR_NOTHROW
2366       { return dtl::force_copy<const_reverse_iterator>(m_flat_tree.crbegin()); }
2367 
2368    //! <b>Effects</b>: Returns a const_reverse_iterator pointing to the end
2369    //! of the reversed container.
2370    //!
2371    //! <b>Throws</b>: Nothing.
2372    //!
2373    //! <b>Complexity</b>: Constant.
2374    BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline
2375    const_reverse_iterator crend() const BOOST_NOEXCEPT_OR_NOTHROW
2376       { return dtl::force_copy<const_reverse_iterator>(m_flat_tree.crend()); }
2377 
2378    //////////////////////////////////////////////
2379    //
2380    //                capacity
2381    //
2382    //////////////////////////////////////////////
2383 
2384    //! <b>Effects</b>: Returns true if the container contains no elements.
2385    //!
2386    //! <b>Throws</b>: Nothing.
2387    //!
2388    //! <b>Complexity</b>: Constant.
2389    BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline
2390    bool empty() const BOOST_NOEXCEPT_OR_NOTHROW
2391       { return m_flat_tree.empty(); }
2392 
2393    //! <b>Effects</b>: Returns the number of the elements contained in the container.
2394    //!
2395    //! <b>Throws</b>: Nothing.
2396    //!
2397    //! <b>Complexity</b>: Constant.
2398    BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline
2399    size_type size() const BOOST_NOEXCEPT_OR_NOTHROW
2400       { return m_flat_tree.size(); }
2401 
2402    //! <b>Effects</b>: Returns the largest possible size of the container.
2403    //!
2404    //! <b>Throws</b>: Nothing.
2405    //!
2406    //! <b>Complexity</b>: Constant.
2407    BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline
2408    size_type max_size() const BOOST_NOEXCEPT_OR_NOTHROW
2409       { return m_flat_tree.max_size(); }
2410 
2411    //! <b>Effects</b>: Number of elements for which memory has been allocated.
2412    //!   capacity() is always greater than or equal to size().
2413    //!
2414    //! <b>Throws</b>: Nothing.
2415    //!
2416    //! <b>Complexity</b>: Constant.
2417    BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline
2418    size_type capacity() const BOOST_NOEXCEPT_OR_NOTHROW
2419       { return m_flat_tree.capacity(); }
2420 
2421    //! <b>Effects</b>: If n is less than or equal to capacity(), or the
2422    //!   underlying container has no `reserve` member, this call has no
2423    //!   effect. Otherwise, it is a request for allocation of additional memory.
2424    //!   If the request is successful, then capacity() is greater than or equal to
2425    //!   n; otherwise, capacity() is unchanged. In either case, size() is unchanged.
2426    //!
2427    //! <b>Throws</b>: If memory allocation allocation throws or T's copy constructor throws.
2428    //!
2429    //! <b>Note</b>: If capacity() is less than "cnt", iterators and references to
2430    //!   to values might be invalidated.
2431    inline
2432    void reserve(size_type cnt)
2433       { m_flat_tree.reserve(cnt);   }
2434 
2435    //! <b>Effects</b>: Tries to deallocate the excess of memory created
2436    //    with previous allocations. The size of the vector is unchanged
2437    //!
2438    //! <b>Throws</b>: If memory allocation throws, or T's copy constructor throws.
2439    //!
2440    //! <b>Complexity</b>: Linear to size().
2441    inline
2442    void shrink_to_fit()
2443       { m_flat_tree.shrink_to_fit(); }
2444 
2445    //! @copydoc ::boost::container::flat_set::nth(size_type)
2446    BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline
2447    iterator nth(size_type n) BOOST_NOEXCEPT_OR_NOTHROW
2448    {  return dtl::force_copy<iterator>(m_flat_tree.nth(n));  }
2449 
2450    //! @copydoc ::boost::container::flat_set::nth(size_type) const
2451    BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline
2452    const_iterator nth(size_type n) const BOOST_NOEXCEPT_OR_NOTHROW
2453    {  return dtl::force_copy<const_iterator>(m_flat_tree.nth(n));  }
2454 
2455    //! @copydoc ::boost::container::flat_set::index_of(iterator)
2456    BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline
2457    size_type index_of(iterator p) BOOST_NOEXCEPT_OR_NOTHROW
2458    {  return m_flat_tree.index_of(dtl::force_copy<impl_iterator>(p));  }
2459 
2460    //! @copydoc ::boost::container::flat_set::index_of(const_iterator) const
2461    BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline
2462    size_type index_of(const_iterator p) const BOOST_NOEXCEPT_OR_NOTHROW
2463    {  return m_flat_tree.index_of(dtl::force_copy<impl_const_iterator>(p));  }
2464 
2465    #if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) || defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
2466 
2467    //! <b>Effects</b>: Inserts an object of type T constructed with
2468    //!   std::forward<Args>(args)... and returns the iterator pointing to the
2469    //!   newly inserted element.
2470    //!
2471    //! <b>Complexity</b>: Logarithmic search time plus linear insertion
2472    //!   to the elements with bigger keys than x.
2473    //!
2474    //! <b>Note</b>: If an element is inserted it might invalidate elements.
2475    template <class... Args>
2476    inline
2477    iterator emplace(BOOST_FWD_REF(Args)... args)
2478    {  return dtl::force_copy<iterator>(m_flat_tree.emplace_equal(boost::forward<Args>(args)...)); }
2479 
2480    //! <b>Effects</b>: Inserts an object of type T constructed with
2481    //!   std::forward<Args>(args)... in the container.
2482    //!   p is a hint pointing to where the insert should start to search.
2483    //!
2484    //! <b>Returns</b>: An iterator pointing to the element with key equivalent
2485    //!   to the key of x.
2486    //!
2487    //! <b>Complexity</b>: Logarithmic search time (constant time if the value
2488    //!   is to be inserted before p) plus linear insertion
2489    //!   to the elements with bigger keys than x.
2490    //!
2491    //! <b>Note</b>: If an element is inserted it might invalidate elements.
2492    template <class... Args>
2493    inline
2494    iterator emplace_hint(const_iterator hint, BOOST_FWD_REF(Args)... args)
2495    {
2496       return dtl::force_copy<iterator>(m_flat_tree.emplace_hint_equal
2497          (dtl::force_copy<impl_const_iterator>(hint), boost::forward<Args>(args)...));
2498    }
2499 
2500    #else // !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
2501 
2502    #define BOOST_CONTAINER_FLAT_MULTIMAP_EMPLACE_CODE(N) \
2503    BOOST_MOVE_TMPL_LT##N BOOST_MOVE_CLASS##N BOOST_MOVE_GT##N \
2504    inline iterator emplace(BOOST_MOVE_UREF##N)\
2505    {  return dtl::force_copy<iterator>(m_flat_tree.emplace_equal(BOOST_MOVE_FWD##N));  }\
2506    \
2507    BOOST_MOVE_TMPL_LT##N BOOST_MOVE_CLASS##N BOOST_MOVE_GT##N \
2508    inline iterator emplace_hint(const_iterator hint BOOST_MOVE_I##N BOOST_MOVE_UREF##N)\
2509    {\
2510       return dtl::force_copy<iterator>(m_flat_tree.emplace_hint_equal\
2511          (dtl::force_copy<impl_const_iterator>(hint) BOOST_MOVE_I##N BOOST_MOVE_FWD##N));\
2512    }\
2513    //
2514    BOOST_MOVE_ITERATE_0TO9(BOOST_CONTAINER_FLAT_MULTIMAP_EMPLACE_CODE)
2515    #undef BOOST_CONTAINER_FLAT_MULTIMAP_EMPLACE_CODE
2516 
2517    #endif   // !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
2518 
2519    //! <b>Effects</b>: Inserts x and returns the iterator pointing to the
2520    //!   newly inserted element.
2521    //!
2522    //! <b>Complexity</b>: Logarithmic search time plus linear insertion
2523    //!   to the elements with bigger keys than x.
2524    //!
2525    //! <b>Note</b>: If an element is inserted it might invalidate elements.
2526    inline iterator insert(const value_type& x)
2527    {
2528       return dtl::force_copy<iterator>(
2529          m_flat_tree.insert_equal(dtl::force<const impl_value_type>(x)));
2530    }
2531 
2532    //! <b>Effects</b>: Inserts a new value constructed from x and returns
2533    //!   the iterator pointing to the newly inserted element.
2534    //!
2535    //! <b>Complexity</b>: Logarithmic search time plus linear insertion
2536    //!   to the elements with bigger keys than x.
2537    //!
2538    //! <b>Note</b>: If an element is inserted it might invalidate elements.
2539    template<class Pair>
2540    inline BOOST_CONTAINER_DOC1ST
2541          ( iterator
2542          , typename dtl::enable_if_c<dtl::is_convertible<Pair BOOST_MOVE_I dtl_pair_t>::value
2543             BOOST_MOVE_I iterator >::type)
2544       insert(BOOST_FWD_REF(Pair) x)
2545    { return dtl::force_copy<iterator>(m_flat_tree.emplace_equal(boost::forward<Pair>(x))); }
2546 
2547    //! <b>Effects</b>: Inserts a copy of x in the container.
2548    //!   p is a hint pointing to where the insert should start to search.
2549    //!
2550    //! <b>Returns</b>: An iterator pointing to the element with key equivalent
2551    //!   to the key of x.
2552    //!
2553    //! <b>Complexity</b>: Logarithmic search time (constant time if the value
2554    //!   is to be inserted before p) plus linear insertion
2555    //!   to the elements with bigger keys than x.
2556    //!
2557    //! <b>Note</b>: If an element is inserted it might invalidate elements.
2558    inline iterator insert(const_iterator p, const value_type& x)
2559    {
2560       return dtl::force_copy<iterator>
2561          (m_flat_tree.insert_equal( dtl::force_copy<impl_const_iterator>(p)
2562                                   , dtl::force<const impl_value_type>(x)));
2563    }
2564 
2565    //! <b>Effects</b>: Inserts a value constructed from x in the container.
2566    //!   p is a hint pointing to where the insert should start to search.
2567    //!
2568    //! <b>Returns</b>: An iterator pointing to the element with key equivalent
2569    //!   to the key of x.
2570    //!
2571    //! <b>Complexity</b>: Logarithmic search time (constant time if the value
2572    //!   is to be inserted before p) plus linear insertion
2573    //!   to the elements with bigger keys than x.
2574    //!
2575    //! <b>Note</b>: If an element is inserted it might invalidate elements.
2576    template<class Pair>
2577    inline BOOST_CONTAINER_DOC1ST
2578          ( iterator
2579          , typename dtl::enable_if_c<dtl::is_convertible<Pair BOOST_MOVE_I dtl_pair_t>::value
2580             BOOST_MOVE_I iterator>::type)
2581       insert(const_iterator p, BOOST_FWD_REF(Pair) x)
2582    {
2583       return dtl::force_copy<iterator>(
2584          m_flat_tree.emplace_hint_equal(dtl::force_copy<impl_const_iterator>(p), boost::forward<Pair>(x)));
2585    }
2586 
2587    //! <b>Requires</b>: first, last are not iterators into *this.
2588    //!
2589    //! <b>Effects</b>: inserts each element from the range [first,last) .
2590    //!
2591    //! <b>Complexity</b>: N log(N).
2592    //!
2593    //! <b>Note</b>: If an element is inserted it might invalidate elements.
2594    template <class InputIterator>
2595    inline void insert(InputIterator first, InputIterator last)
2596       {  m_flat_tree.insert_equal(first, last); }
2597 
2598    //! <b>Requires</b>: first, last are not iterators into *this.
2599    //!
2600    //! <b>Requires</b>: [first ,last) must be ordered according to the predicate.
2601    //!
2602    //! <b>Effects</b>: inserts each element from the range [first,last) if and only
2603    //!   if there is no element with key equivalent to the key of that element. This
2604    //!   function is more efficient than the normal range creation for ordered ranges.
2605    //!
2606    //! <b>Complexity</b>: Linear.
2607    //!
2608    //! <b>Note</b>: If an element is inserted it might invalidate elements.
2609    //!
2610    //! <b>Note</b>: Non-standard extension.
2611    template <class InputIterator>
2612    inline void insert(ordered_range_t, InputIterator first, InputIterator last)
2613       {  m_flat_tree.insert_equal(ordered_range, first, last); }
2614 
2615 #if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
2616    //! <b>Effects</b>: inserts each element from the range [il.begin(), il.end()) .
2617    //!
2618    //! <b>Complexity</b>: N log(N).
2619    //!
2620    //! <b>Note</b>: If an element is inserted it might invalidate elements.
2621    inline void insert(std::initializer_list<value_type> il)
2622    {
2623       m_flat_tree.insert_equal( dtl::force<impl_initializer_list>(il).begin()
2624                               , dtl::force<impl_initializer_list>(il).end());
2625    }
2626 
2627    //! <b>Requires</b>: [il.begin(), il.end()) must be ordered according to the predicate.
2628    //!
2629    //! <b>Effects</b>: inserts each element from the range [il.begin(), il.end()) if and only
2630    //!   if there is no element with key equivalent to the key of that element. This
2631    //!   function is more efficient than the normal range creation for ordered ranges.
2632    //!
2633    //! <b>Complexity</b>: Linear.
2634    //!
2635    //! <b>Note</b>: If an element is inserted it might invalidate elements.
2636    //!
2637    //! <b>Note</b>: Non-standard extension.
2638    inline void insert(ordered_range_t, std::initializer_list<value_type> il)
2639    {
2640       m_flat_tree.insert_equal( ordered_range
2641                               , dtl::force<impl_initializer_list>(il).begin()
2642                               , dtl::force<impl_initializer_list>(il).end());
2643    }
2644 #endif
2645 
2646    //! <b>Requires</b>: this->get_allocator() == source.get_allocator().
2647    //!
2648    //! <b>Effects</b>: Move-inserts each element from source into *this a using
2649    //!   the comparison object of *this.
2650    //!
2651    //! <b>Complexity</b>: Linear in this->size() + source.size().
2652    //!
2653    //! <b>Note</b>: Invalidates all iterators and references.
2654    template<class C2>
2655    inline void merge(flat_multimap<Key, T, C2, AllocatorOrContainer>& source)
2656    {  m_flat_tree.merge_equal(source.tree());   }
2657 
2658    //! @copydoc ::boost::container::flat_multimap::merge(flat_multimap<Key, T, C2, AllocatorOrContainer>&)
2659    template<class C2>
2660    inline void merge(BOOST_RV_REF_BEG flat_multimap<Key, T, C2, AllocatorOrContainer> BOOST_RV_REF_END source)
2661    {  return this->merge(static_cast<flat_multimap<Key, T, C2, AllocatorOrContainer>&>(source)); }
2662 
2663    //! @copydoc ::boost::container::flat_multimap::merge(flat_multimap<Key, T, C2, AllocatorOrContainer>&)
2664    template<class C2>
2665    inline void merge(flat_map<Key, T, C2, AllocatorOrContainer>& source)
2666    {  m_flat_tree.merge_equal(source.tree());   }
2667 
2668    //! @copydoc ::boost::container::flat_multimap::merge(flat_map<Key, T, C2, AllocatorOrContainer>&)
2669    template<class C2>
2670    inline void merge(BOOST_RV_REF_BEG flat_map<Key, T, C2, AllocatorOrContainer> BOOST_RV_REF_END source)
2671    {  return this->merge(static_cast<flat_map<Key, T, C2, AllocatorOrContainer>&>(source)); }
2672 
2673    //! <b>Effects</b>: Erases the element pointed to by p.
2674    //!
2675    //! <b>Returns</b>: Returns an iterator pointing to the element immediately
2676    //!   following q prior to the element being erased. If no such element exists,
2677    //!   returns end().
2678    //!
2679    //! <b>Complexity</b>: Linear to the elements with keys bigger than p
2680    //!
2681    //! <b>Note</b>: Invalidates elements with keys
2682    //!   not less than the erased element.
2683    inline iterator erase(const_iterator p)
2684    {
2685       return dtl::force_copy<iterator>(
2686          m_flat_tree.erase(dtl::force_copy<impl_const_iterator>(p)));
2687    }
2688 
2689    //! <b>Effects</b>: Erases all elements in the container with key equivalent to x.
2690    //!
2691    //! <b>Returns</b>: Returns the number of erased elements.
2692    //!
2693    //! <b>Complexity</b>: Logarithmic search time plus erasure time
2694    //!   linear to the elements with bigger keys.
2695    inline size_type erase(const key_type& x)
2696       { return m_flat_tree.erase(x); }
2697 
2698    //! <b>Requires</b>: This overload is available only if
2699    //! key_compare::is_transparent exists.
2700    //!
2701    //! <b>Effects</b>: Erases all elements in the container with key equivalent to x.
2702    //!
2703    //! <b>Returns</b>: Returns the number of erased elements.
2704    template <class K>
2705    inline BOOST_CONTAINER_DOC1ST
2706    (size_type
2707       , typename dtl::enable_if_c<
2708       dtl::is_transparent<key_compare>::value &&                  //transparent
2709       !dtl::is_convertible<K BOOST_MOVE_I iterator>::value &&     //not convertible to iterator
2710       !dtl::is_convertible<K BOOST_MOVE_I const_iterator>::value  //not convertible to const_iterator
2711       BOOST_MOVE_I size_type>::type)
2712       erase(const K& x)
2713       { return m_flat_tree.erase(x); }
2714 
2715    //! <b>Effects</b>: Erases all the elements in the range [first, last).
2716    //!
2717    //! <b>Returns</b>: Returns last.
2718    //!
2719    //! <b>Complexity</b>: size()*N where N is the distance from first to last.
2720    //!
2721    //! <b>Complexity</b>: Logarithmic search time plus erasure time
2722    //!   linear to the elements with bigger keys.
2723    inline iterator erase(const_iterator first, const_iterator last)
2724    {
2725       return dtl::force_copy<iterator>
2726          (m_flat_tree.erase( dtl::force_copy<impl_const_iterator>(first)
2727                            , dtl::force_copy<impl_const_iterator>(last)));
2728    }
2729 
2730    //! <b>Effects</b>: Swaps the contents of *this and x.
2731    //!
2732    //! <b>Throws</b>: Nothing.
2733    //!
2734    //! <b>Complexity</b>: Constant.
2735    inline void swap(flat_multimap& x)
2736       BOOST_NOEXCEPT_IF(  allocator_traits_type::is_always_equal::value
2737                                  && boost::container::dtl::is_nothrow_swappable<Compare>::value )
2738    { m_flat_tree.swap(x.m_flat_tree); }
2739 
2740    //! <b>Effects</b>: erase(begin(),end()).
2741    //!
2742    //! <b>Postcondition</b>: size() == 0.
2743    //!
2744    //! <b>Complexity</b>: linear in size().
2745    inline void clear() BOOST_NOEXCEPT_OR_NOTHROW
2746       { m_flat_tree.clear(); }
2747 
2748    //////////////////////////////////////////////
2749    //
2750    //                observers
2751    //
2752    //////////////////////////////////////////////
2753 
2754    //! <b>Effects</b>: Returns the comparison object out
2755    //!   of which a was constructed.
2756    //!
2757    //! <b>Complexity</b>: Constant.
2758    BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline
2759       key_compare key_comp() const
2760       { return dtl::force_copy<key_compare>(m_flat_tree.key_comp()); }
2761 
2762    //! <b>Effects</b>: Returns an object of value_compare constructed out
2763    //!   of the comparison object.
2764    //!
2765    //! <b>Complexity</b>: Constant.
2766    BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline
2767       value_compare value_comp() const
2768       { return value_compare(dtl::force_copy<key_compare>(m_flat_tree.key_comp())); }
2769 
2770    //////////////////////////////////////////////
2771    //
2772    //              map operations
2773    //
2774    //////////////////////////////////////////////
2775 
2776    //! <b>Returns</b>: An iterator pointing to an element with the key
2777    //!   equivalent to x, or end() if such an element is not found.
2778    //!
2779    //! <b>Complexity</b>: Logarithmic.
2780    BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline
2781       iterator find(const key_type& x)
2782       { return dtl::force_copy<iterator>(m_flat_tree.find(x)); }
2783 
2784    //! <b>Returns</b>: An const_iterator pointing to an element with the key
2785    //!   equivalent to x, or end() if such an element is not found.
2786    //!
2787    //! <b>Complexity</b>: Logarithmic.
2788    BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline
2789       const_iterator find(const key_type& x) const
2790       { return dtl::force_copy<const_iterator>(m_flat_tree.find(x)); }
2791 
2792    //! <b>Requires</b>: This overload is available only if
2793    //! key_compare::is_transparent exists.
2794    //!
2795    //! <b>Returns</b>: An iterator pointing to an element with the key
2796    //!   equivalent to x, or end() if such an element is not found.
2797    //!
2798    //! <b>Complexity</b>: Logarithmic.
2799    template<class K>
2800    BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline
2801       iterator find(const K& x)
2802       { return dtl::force_copy<iterator>(m_flat_tree.find(x)); }
2803 
2804    //! <b>Requires</b>: This overload is available only if
2805    //! key_compare::is_transparent exists.
2806    //!
2807    //! <b>Returns</b>: An const_iterator pointing to an element with the key
2808    //!   equivalent to x, or end() if such an element is not found.
2809    //!
2810    //! <b>Complexity</b>: Logarithmic.
2811    template<class K>
2812    BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline
2813       const_iterator find(const K& x) const
2814       { return dtl::force_copy<const_iterator>(m_flat_tree.find(x)); }
2815 
2816    //! <b>Returns</b>: The number of elements with key equivalent to x.
2817    //!
2818    //! <b>Complexity</b>: log(size())+count(k)
2819    BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline
2820       size_type count(const key_type& x) const
2821       { return m_flat_tree.count(x); }
2822 
2823    //! <b>Requires</b>: This overload is available only if
2824    //! key_compare::is_transparent exists.
2825    //!
2826    //! <b>Returns</b>: The number of elements with key equivalent to x.
2827    //!
2828    //! <b>Complexity</b>: log(size())+count(k)
2829    template<class K>
2830    BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline
2831       size_type count(const K& x) const
2832       { return m_flat_tree.count(x); }
2833 
2834    //! <b>Returns</b>: Returns true if there is an element with key
2835    //!   equivalent to key in the container, otherwise false.
2836    //!
2837    //! <b>Complexity</b>: log(size()).
2838    BOOST_CONTAINER_ATTRIBUTE_NODISCARD  inline
2839       bool contains(const key_type& x) const
2840       {  return m_flat_tree.find(x) != m_flat_tree.end();  }
2841 
2842    //! <b>Requires</b>: This overload is available only if
2843    //! key_compare::is_transparent exists.
2844    //!
2845    //! <b>Returns</b>: Returns true if there is an element with key
2846    //!   equivalent to key in the container, otherwise false.
2847    //!
2848    //! <b>Complexity</b>: log(size()).
2849    template<typename K>
2850    BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline
2851       bool contains(const K& x) const
2852       {  return m_flat_tree.find(x) != m_flat_tree.end();  }
2853 
2854    //! <b>Returns</b>: An iterator pointing to the first element with key not less
2855    //!   than x, or end() if such an element is not found.
2856    //!
2857    //! <b>Complexity</b>: Logarithmic
2858    BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline
2859       iterator lower_bound(const key_type& x)
2860       {  return dtl::force_copy<iterator>(m_flat_tree.lower_bound(x)); }
2861 
2862    //! <b>Returns</b>: An iterator pointing to the first element with key not less
2863    //!   than x, or end() if such an element is not found.
2864    //!
2865    //! <b>Complexity</b>: Logarithmic
2866    BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline
2867       const_iterator lower_bound(const key_type& x) const
2868       {  return dtl::force_copy<const_iterator>(m_flat_tree.lower_bound(x)); }
2869 
2870    //! <b>Requires</b>: This overload is available only if
2871    //! key_compare::is_transparent exists.
2872    //!
2873    //! <b>Returns</b>: An iterator pointing to the first element with key not less
2874    //!   than x, or end() if such an element is not found.
2875    //!
2876    //! <b>Complexity</b>: Logarithmic
2877    template<class K>
2878    BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline
2879       iterator lower_bound(const K& x)
2880       {  return dtl::force_copy<iterator>(m_flat_tree.lower_bound(x)); }
2881 
2882    //! <b>Requires</b>: This overload is available only if
2883    //! key_compare::is_transparent exists.
2884    //!
2885    //! <b>Returns</b>: An iterator pointing to the first element with key not less
2886    //!   than x, or end() if such an element is not found.
2887    //!
2888    //! <b>Complexity</b>: Logarithmic
2889    template<class K>
2890    BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline
2891       const_iterator lower_bound(const K& x) const
2892       {  return dtl::force_copy<const_iterator>(m_flat_tree.lower_bound(x)); }
2893 
2894    //! <b>Returns</b>: An iterator pointing to the first element with key greater
2895    //!   than x, or end() if such an element is not found.
2896    //!
2897    //! <b>Complexity</b>: Logarithmic
2898    BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline
2899       iterator upper_bound(const key_type& x)
2900       {return dtl::force_copy<iterator>(m_flat_tree.upper_bound(x)); }
2901 
2902    //! <b>Returns</b>: A const iterator pointing to the first element with key
2903    //!   greater than x, or end() if such an element is not found.
2904    //!
2905    //! <b>Complexity</b>: Logarithmic
2906    BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline
2907       const_iterator upper_bound(const key_type& x) const
2908       {  return dtl::force_copy<const_iterator>(m_flat_tree.upper_bound(x)); }
2909 
2910    //! <b>Requires</b>: This overload is available only if
2911    //! key_compare::is_transparent exists.
2912    //!
2913    //! <b>Returns</b>: An iterator pointing to the first element with key greater
2914    //!   than x, or end() if such an element is not found.
2915    //!
2916    //! <b>Complexity</b>: Logarithmic
2917    template<class K>
2918    BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline
2919       iterator upper_bound(const K& x)
2920       {return dtl::force_copy<iterator>(m_flat_tree.upper_bound(x)); }
2921 
2922    //! <b>Requires</b>: This overload is available only if
2923    //! key_compare::is_transparent exists.
2924    //!
2925    //! <b>Returns</b>: A const iterator pointing to the first element with key
2926    //!   greater than x, or end() if such an element is not found.
2927    //!
2928    //! <b>Complexity</b>: Logarithmic
2929    template<class K>
2930    BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline
2931       const_iterator upper_bound(const K& x) const
2932       {  return dtl::force_copy<const_iterator>(m_flat_tree.upper_bound(x)); }
2933 
2934    //! <b>Effects</b>: Equivalent to std::make_pair(this->lower_bound(k), this->upper_bound(k)).
2935    //!
2936    //! <b>Complexity</b>: Logarithmic
2937    BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline
2938       std::pair<iterator,iterator> equal_range(const key_type& x)
2939       {  return dtl::force_copy<std::pair<iterator,iterator> >(m_flat_tree.equal_range(x));   }
2940 
2941    //! <b>Effects</b>: Equivalent to std::make_pair(this->lower_bound(k), this->upper_bound(k)).
2942    //!
2943    //! <b>Complexity</b>: Logarithmic
2944    BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline
2945       std::pair<const_iterator, const_iterator> equal_range(const key_type& x) const
2946       {  return dtl::force_copy<std::pair<const_iterator,const_iterator> >(m_flat_tree.equal_range(x));   }
2947 
2948    //! <b>Requires</b>: This overload is available only if
2949    //! key_compare::is_transparent exists.
2950    //!
2951    //! <b>Effects</b>: Equivalent to std::make_pair(this->lower_bound(k), this->upper_bound(k)).
2952    //!
2953    //! <b>Complexity</b>: Logarithmic
2954    template<class K>
2955    BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline
2956       std::pair<iterator,iterator> equal_range(const K& x)
2957       {  return dtl::force_copy<std::pair<iterator,iterator> >(m_flat_tree.equal_range(x));   }
2958 
2959    //! <b>Requires</b>: This overload is available only if
2960    //! key_compare::is_transparent exists.
2961    //!
2962    //! <b>Effects</b>: Equivalent to std::make_pair(this->lower_bound(k), this->upper_bound(k)).
2963    //!
2964    //! <b>Complexity</b>: Logarithmic
2965    template<class K>
2966    BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline
2967       std::pair<const_iterator, const_iterator> equal_range(const K& x) const
2968       {  return dtl::force_copy<std::pair<const_iterator,const_iterator> >(m_flat_tree.equal_range(x));   }
2969 
2970    //! <b>Effects</b>: Extracts the internal sequence container.
2971    //!
2972    //! <b>Complexity</b>: Same as the move constructor of sequence_type, usually constant.
2973    //!
2974    //! <b>Postcondition</b>: this->empty()
2975    //!
2976    //! <b>Throws</b>: If secuence_type's move constructor throws 
2977    BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline
2978       sequence_type extract_sequence()
2979    {  return boost::move(dtl::force<sequence_type>(m_flat_tree.get_sequence_ref()));   }
2980 
2981    //! <b>Effects</b>: Discards the internally hold sequence container and adopts the
2982    //!   one passed externally using the move assignment.
2983    //!
2984    //! <b>Complexity</b>: Assuming O(1) move assignment, O(NlogN) with N = seq.size()
2985    //!
2986    //! <b>Throws</b>: If the comparison or the move constructor throws
2987    inline void adopt_sequence(BOOST_RV_REF(sequence_type) seq)
2988    {  this->m_flat_tree.adopt_sequence_equal(boost::move(dtl::force<impl_sequence_type>(seq)));  }
2989 
2990    //! <b>Requires</b>: seq shall be ordered according to this->compare().
2991    //!
2992    //! <b>Effects</b>: Discards the internally hold sequence container and adopts the
2993    //!   one passed externally using the move assignment.
2994    //!
2995    //! <b>Complexity</b>: Assuming O(1) move assignment, O(1)
2996    //!
2997    //! <b>Throws</b>: If the move assignment throws
2998    inline void adopt_sequence(ordered_range_t, BOOST_RV_REF(sequence_type) seq)
2999    {  this->m_flat_tree.adopt_sequence_equal(ordered_range_t(), boost::move(dtl::force<impl_sequence_type>(seq)));  }
3000 
3001    //! <b>Effects</b>: Returns a const view of the underlying sequence.
3002    //!
3003    //! <b>Complexity</b>: Constant
3004    //!
3005    //! <b>Throws</b>: Nothing
3006    inline const sequence_type & sequence() const BOOST_NOEXCEPT
3007    {  return dtl::force<sequence_type>(m_flat_tree.get_sequence_cref());  }
3008 
3009    //! <b>Effects</b>: Returns true if x and y are equal
3010    //!
3011    //! <b>Complexity</b>: Linear to the number of elements in the container.
3012    BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline
3013       friend bool operator==(const flat_multimap& x, const flat_multimap& y)
3014    {  return x.size() == y.size() && ::boost::container::algo_equal(x.begin(), x.end(), y.begin());  }
3015 
3016    //! <b>Effects</b>: Returns true if x and y are unequal
3017    //!
3018    //! <b>Complexity</b>: Linear to the number of elements in the container.
3019    BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline
3020       friend bool operator!=(const flat_multimap& x, const flat_multimap& y)
3021    {  return !(x == y); }
3022 
3023    //! <b>Effects</b>: Returns true if x is less than y
3024    //!
3025    //! <b>Complexity</b>: Linear to the number of elements in the container.
3026    BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline
3027       friend bool operator<(const flat_multimap& x, const flat_multimap& y)
3028    {  return ::boost::container::algo_lexicographical_compare(x.begin(), x.end(), y.begin(), y.end());  }
3029 
3030    //! <b>Effects</b>: Returns true if x is greater than y
3031    //!
3032    //! <b>Complexity</b>: Linear to the number of elements in the container.
3033    BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline
3034       friend bool operator>(const flat_multimap& x, const flat_multimap& y)
3035    {  return y < x;  }
3036 
3037    //! <b>Effects</b>: Returns true if x is equal or less than y
3038    //!
3039    //! <b>Complexity</b>: Linear to the number of elements in the container.
3040    BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline
3041       friend bool operator<=(const flat_multimap& x, const flat_multimap& y)
3042    {  return !(y < x);  }
3043 
3044    //! <b>Effects</b>: Returns true if x is equal or greater than y
3045    //!
3046    //! <b>Complexity</b>: Linear to the number of elements in the container.
3047    BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline
3048       friend bool operator>=(const flat_multimap& x, const flat_multimap& y)
3049    {  return !(x < y);  }
3050 
3051    //! <b>Effects</b>: x.swap(y)
3052    //!
3053    //! <b>Complexity</b>: Constant.
3054    inline friend void swap(flat_multimap& x, flat_multimap& y)
3055        BOOST_NOEXCEPT_IF(BOOST_NOEXCEPT(x.swap(y)))
3056    {  x.swap(y);  }
3057 };
3058 
3059 #if defined(BOOST_GCC) && (BOOST_GCC >= 100000) && !defined(BOOST_CONTAINER_STD_PAIR_IS_MOVABLE)
3060 #pragma GCC pop_options
3061 #endif
3062 
3063 #ifndef BOOST_CONTAINER_NO_CXX17_CTAD
3064 
3065 template <typename InputIterator>
3066 flat_multimap(InputIterator, InputIterator) ->
3067    flat_multimap< it_based_non_const_first_type_t<InputIterator>
3068                 , it_based_second_type_t<InputIterator>>;
3069 
3070 template < typename InputIterator, typename AllocatorOrCompare>
3071 flat_multimap(InputIterator, InputIterator, AllocatorOrCompare const&) ->
3072    flat_multimap< it_based_non_const_first_type_t<InputIterator>
3073                 , it_based_second_type_t<InputIterator>
3074                 , typename dtl::if_c<   // Compare
3075                     dtl::is_allocator<AllocatorOrCompare>::value
3076                     , std::less<it_based_non_const_first_type_t<InputIterator>>
3077                     , AllocatorOrCompare
3078                     >::type
3079                 , typename dtl::if_c<   // Allocator
3080                     dtl::is_allocator<AllocatorOrCompare>::value
3081                     , AllocatorOrCompare
3082                     , new_allocator<std::pair<it_based_non_const_first_type_t<InputIterator>, it_based_second_type_t<InputIterator>>>
3083                     >::type
3084                 >;
3085 
3086 template < typename InputIterator, typename Compare, typename Allocator
3087          , typename = dtl::require_nonallocator_t<Compare>
3088          , typename = dtl::require_allocator_t<Allocator>>
3089 flat_multimap(InputIterator, InputIterator, Compare const&, Allocator const&) ->
3090    flat_multimap< it_based_non_const_first_type_t<InputIterator>
3091                 , it_based_second_type_t<InputIterator>
3092                 , Compare
3093                 , Allocator>;
3094 
3095 template <typename InputIterator>
3096 flat_multimap(ordered_range_t, InputIterator, InputIterator) ->
3097    flat_multimap< it_based_non_const_first_type_t<InputIterator>
3098                 , it_based_second_type_t<InputIterator>>;
3099 
3100 template < typename InputIterator, typename AllocatorOrCompare>
3101 flat_multimap(ordered_range_t, InputIterator, InputIterator, AllocatorOrCompare const&) ->
3102    flat_multimap< it_based_non_const_first_type_t<InputIterator>
3103                 , it_based_second_type_t<InputIterator>
3104                 , typename dtl::if_c<   // Compare
3105                     dtl::is_allocator<AllocatorOrCompare>::value
3106                     , std::less<it_based_non_const_first_type_t<InputIterator>>
3107                     , AllocatorOrCompare
3108                     >::type
3109                 , typename dtl::if_c<   // Allocator
3110                     dtl::is_allocator<AllocatorOrCompare>::value
3111                     , AllocatorOrCompare
3112                     , new_allocator<std::pair<it_based_non_const_first_type_t<InputIterator>, it_based_second_type_t<InputIterator>>>
3113                     >::type
3114                 >;
3115 
3116 template < typename InputIterator, typename Compare, typename Allocator
3117          , typename = dtl::require_nonallocator_t<Compare>
3118          , typename = dtl::require_allocator_t<Allocator>>
3119 flat_multimap(ordered_range_t, InputIterator, InputIterator, Compare const&, Allocator const&) ->
3120    flat_multimap< it_based_non_const_first_type_t<InputIterator>
3121                 , it_based_second_type_t<InputIterator>
3122                 , Compare
3123                 , Allocator>;
3124 
3125 #endif
3126 
3127 }}
3128 
3129 #ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
3130 
3131 namespace boost {
3132 
3133 //!has_trivial_destructor_after_move<> == true_type
3134 //!specialization for optimizations
3135 template <class Key, class T, class Compare, class AllocatorOrContainer>
3136 struct has_trivial_destructor_after_move< boost::container::flat_multimap<Key, T, Compare, AllocatorOrContainer> >
3137 {
3138    typedef typename boost::container::flat_multimap<Key, T, Compare, AllocatorOrContainer>::value_type value_t;
3139    typedef typename ::boost::container::dtl::container_or_allocator_rebind<AllocatorOrContainer, value_t>::type alloc_or_cont_t;
3140    typedef ::boost::container::dtl::flat_tree<value_t,::boost::container::dtl::select1st<Key>, Compare, alloc_or_cont_t> tree;
3141    BOOST_STATIC_CONSTEXPR bool value = ::boost::has_trivial_destructor_after_move<tree>::value;
3142 };
3143 
3144 }  //namespace boost {
3145 
3146 #endif   //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
3147 
3148 #include <boost/container/detail/config_end.hpp>
3149 
3150 #endif   // BOOST_CONTAINER_FLAT_MAP_HPP