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