Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-18 09:30:17

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