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