Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-09-16 08:30:13

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