File indexing completed on 2025-07-05 08:28:40
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011 #ifndef BOOST_CONTAINER_FLAT_TREE_HPP
0012 #define BOOST_CONTAINER_FLAT_TREE_HPP
0013
0014 #ifndef BOOST_CONFIG_HPP
0015 # include <boost/config.hpp>
0016 #endif
0017
0018 #if defined(BOOST_HAS_PRAGMA_ONCE)
0019 # pragma once
0020 #endif
0021
0022 #include <boost/container/detail/config_begin.hpp>
0023 #include <boost/container/detail/workaround.hpp>
0024
0025 #include <boost/container/container_fwd.hpp>
0026
0027 #include <boost/move/utility_core.hpp>
0028
0029 #include <boost/container/vector.hpp>
0030 #include <boost/container/allocator_traits.hpp>
0031
0032 #include <boost/container/detail/value_init.hpp>
0033 #include <boost/container/detail/destroyers.hpp>
0034 #include <boost/container/detail/algorithm.hpp> //algo_equal(), algo_lexicographical_compare
0035 #include <boost/container/detail/iterator.hpp>
0036 #include <boost/container/detail/is_sorted.hpp>
0037 #include <boost/container/detail/type_traits.hpp>
0038 #include <boost/container/detail/iterators.hpp>
0039 #include <boost/container/detail/mpl.hpp>
0040 #include <boost/container/detail/is_contiguous_container.hpp>
0041 #include <boost/container/detail/is_container.hpp>
0042
0043 #include <boost/intrusive/detail/minimal_pair_header.hpp> //pair
0044
0045 #include <boost/move/iterator.hpp>
0046 #include <boost/move/adl_move_swap.hpp>
0047 #include <boost/move/detail/iterator_to_raw_pointer.hpp>
0048 #include <boost/move/detail/force_ptr.hpp>
0049 #include <boost/move/detail/launder.hpp>
0050 #include <boost/move/algo/adaptive_sort.hpp>
0051 #include <boost/move/algo/detail/pdqsort.hpp>
0052
0053 #if defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
0054 #include <boost/move/detail/fwd_macros.hpp>
0055 #endif
0056
0057 #ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
0058
0059 #if defined(BOOST_GCC) && (BOOST_GCC >= 40600)
0060 #pragma GCC diagnostic push
0061 #pragma GCC diagnostic ignored "-Wunused-result"
0062 #endif
0063
0064
0065 #define BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_FUNCNAME merge_unique
0066 #define BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_NS_BEG namespace boost { namespace container { namespace dtl {
0067 #define BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_NS_END }}}
0068 #define BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_MIN 3
0069 #define BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_MAX 3
0070 #include <boost/intrusive/detail/has_member_function_callable_with.hpp>
0071
0072
0073 #define BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_FUNCNAME merge
0074 #define BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_NS_BEG namespace boost { namespace container { namespace dtl {
0075 #define BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_NS_END }}}
0076 #define BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_MIN 3
0077 #define BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_MAX 3
0078 #include <boost/intrusive/detail/has_member_function_callable_with.hpp>
0079
0080
0081 #define BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_FUNCNAME index_of
0082 #define BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_NS_BEG namespace boost { namespace container { namespace dtl {
0083 #define BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_NS_END }}}
0084 #define BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_MIN 1
0085 #define BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_MAX 1
0086 #include <boost/intrusive/detail/has_member_function_callable_with.hpp>
0087
0088
0089 #define BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_FUNCNAME nth
0090 #define BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_NS_BEG namespace boost { namespace container { namespace dtl {
0091 #define BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_NS_END }}}
0092 #define BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_MIN 1
0093 #define BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_MAX 1
0094 #include <boost/intrusive/detail/has_member_function_callable_with.hpp>
0095
0096
0097 #define BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_FUNCNAME reserve
0098 #define BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_NS_BEG namespace boost { namespace container { namespace dtl {
0099 #define BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_NS_END }}}
0100 #define BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_MIN 1
0101 #define BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_MAX 1
0102 #include <boost/intrusive/detail/has_member_function_callable_with.hpp>
0103
0104
0105 #define BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_FUNCNAME capacity
0106 #define BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_NS_BEG namespace boost { namespace container { namespace dtl {
0107 #define BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_NS_END }}}
0108 #define BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_MIN 0
0109 #define BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_MAX 0
0110 #include <boost/intrusive/detail/has_member_function_callable_with.hpp>
0111
0112 #if defined(BOOST_GCC) && (BOOST_GCC >= 40600)
0113 #pragma GCC diagnostic pop
0114 #endif
0115
0116
0117 #endif
0118
0119 namespace boost {
0120 namespace container {
0121 namespace dtl {
0122
0123
0124
0125
0126
0127
0128
0129 BOOST_INTRUSIVE_INSTANTIATE_DEFAULT_TYPE_TMPLT(stored_allocator_type)
0130
0131
0132
0133
0134
0135
0136 template<class SequenceContainer, class Compare>
0137 inline void flat_tree_container_inplace_merge
0138 (SequenceContainer& dest, typename SequenceContainer::iterator it, Compare comp , dtl::true_)
0139 {
0140 typedef typename SequenceContainer::value_type value_type;
0141 value_type *const braw = boost::movelib::to_raw_pointer(dest.data());
0142 value_type *const iraw = boost::movelib::iterator_to_raw_pointer(it);
0143
0144
0145 value_type *const eraw = braw + dest.size();
0146 boost::movelib::adaptive_merge
0147 (braw, iraw, eraw, comp, eraw, back_free_capacity<SequenceContainer>::get(dest));
0148 }
0149
0150 template<class SequenceContainer, class Compare>
0151 inline void flat_tree_container_inplace_merge
0152 (SequenceContainer& dest, typename SequenceContainer::iterator it, Compare comp, dtl::false_)
0153 {
0154 boost::movelib::adaptive_merge(dest.begin(), it, dest.end(), comp);
0155 }
0156
0157
0158
0159
0160
0161
0162 template<class SequenceContainer, class Compare>
0163 inline void flat_tree_container_inplace_sort_ending
0164 (SequenceContainer& dest, typename SequenceContainer::iterator it, Compare comp, dtl::true_)
0165 {
0166 typedef typename SequenceContainer::value_type value_type;
0167 value_type *const iraw = boost::movelib::iterator_to_raw_pointer(it);
0168
0169
0170 value_type* const eraw = boost::movelib::to_raw_pointer(dest.data()) + dest.size();
0171
0172
0173 boost::movelib::adaptive_sort
0174 (iraw, eraw, comp, eraw, back_free_capacity<SequenceContainer>::get(dest));
0175 }
0176
0177 template<class SequenceContainer, class Compare>
0178 inline void flat_tree_container_inplace_sort_ending
0179 (SequenceContainer& dest, typename SequenceContainer::iterator it, Compare comp , dtl::false_)
0180 {
0181 boost::movelib::adaptive_sort(it, dest.end(), comp);
0182 }
0183
0184
0185
0186
0187
0188
0189 template<class SequenceContainer, class Iterator, class Compare>
0190 inline void flat_tree_merge_equal
0191 (SequenceContainer& dest, Iterator first, Iterator last, Compare comp, dtl::true_)
0192 {
0193 dest.merge(first, last, comp);
0194 }
0195
0196 template<class SequenceContainer, class Iterator, class Compare>
0197 inline void flat_tree_merge_equal
0198 (SequenceContainer& dest, Iterator first, Iterator last, Compare comp, dtl::false_)
0199 {
0200 if(first != last) {
0201 typedef typename SequenceContainer::iterator iterator;
0202 iterator const it = dest.insert( dest.end(), first, last );
0203 dtl::bool_<is_contiguous_container<SequenceContainer>::value> contiguous_tag;
0204 (flat_tree_container_inplace_merge)(dest, it, comp, contiguous_tag);
0205 }
0206 }
0207
0208
0209
0210
0211
0212
0213 template<class SequenceContainer, class Iterator, class Compare>
0214 inline void flat_tree_merge_unique
0215 (SequenceContainer& dest, Iterator first, Iterator last, Compare comp, dtl::true_)
0216 {
0217 dest.merge_unique(first, last, comp);
0218 }
0219
0220 template<class SequenceContainer, class Iterator, class Compare>
0221 inline void flat_tree_merge_unique
0222 (SequenceContainer& dest, Iterator first, Iterator last, Compare comp, dtl::false_)
0223 {
0224 if (first != last) {
0225 typedef typename SequenceContainer::iterator iterator;
0226 typedef typename SequenceContainer::size_type size_type;
0227 typedef typename SequenceContainer::difference_type difference_type;
0228
0229 size_type const old_sz = dest.size();
0230 iterator const first_new = dest.insert(dest.cend(), first, last );
0231 iterator e = boost::movelib::inplace_set_unique_difference(first_new, dest.end(), dest.begin(), first_new, comp);
0232 dest.erase(e, dest.end());
0233 dtl::bool_<is_contiguous_container<SequenceContainer>::value> contiguous_tag;
0234 (flat_tree_container_inplace_merge)(dest, dest.begin() + difference_type(old_sz), comp, contiguous_tag);
0235 }
0236 }
0237
0238
0239
0240
0241
0242
0243 template<class SequenceContainer, class Iterator>
0244 inline typename SequenceContainer::size_type
0245 flat_tree_index_of
0246 (SequenceContainer& cont, Iterator p, dtl::true_)
0247 {
0248 return cont.index_of(p);
0249 }
0250
0251 template<class SequenceContainer, class Iterator>
0252 inline typename SequenceContainer::size_type
0253 flat_tree_index_of
0254 (SequenceContainer& cont, Iterator p, dtl::false_)
0255 {
0256 typedef typename SequenceContainer::size_type size_type;
0257 return static_cast<size_type>(p - cont.begin());
0258 }
0259
0260
0261
0262
0263
0264
0265 template<class Iterator, class SequenceContainer>
0266 inline Iterator
0267 flat_tree_nth
0268 (SequenceContainer& cont, typename SequenceContainer::size_type n, dtl::true_)
0269 {
0270 return cont.nth(n);
0271 }
0272
0273 template<class Iterator, class SequenceContainer>
0274 inline Iterator
0275 flat_tree_nth
0276 (SequenceContainer& cont, typename SequenceContainer::size_type n, dtl::false_)
0277 {
0278 return cont.begin()+ typename SequenceContainer::difference_type(n);
0279 }
0280
0281
0282
0283
0284
0285
0286 template<class SequenceContainer>
0287 inline typename SequenceContainer::stored_allocator_type &
0288 flat_tree_get_stored_allocator
0289 (SequenceContainer& cont, dtl::true_)
0290 {
0291 return cont.get_stored_allocator();
0292 }
0293
0294 template<class SequenceContainer>
0295 inline const typename SequenceContainer::stored_allocator_type &
0296 flat_tree_get_stored_allocator
0297 (const SequenceContainer& cont, dtl::true_)
0298 {
0299 return cont.get_stored_allocator();
0300 }
0301
0302 template<class SequenceContainer>
0303 inline typename SequenceContainer::allocator_type
0304 flat_tree_get_stored_allocator
0305 (SequenceContainer& cont, dtl::false_)
0306 {
0307 return cont.get_allocator();
0308 }
0309
0310
0311
0312
0313
0314
0315 template<class SequenceContainer, class Compare>
0316 void flat_tree_sort_contiguous_to_adopt
0317 (SequenceContainer &tseq, BOOST_RV_REF(SequenceContainer) seq, Compare comp)
0318 {
0319 if(tseq.capacity() >= (seq.capacity() - seq.size())) {
0320 tseq.clear();
0321 boost::movelib::adaptive_sort
0322 (boost::movelib::iterator_to_raw_pointer(seq.begin())
0323 , boost::movelib::iterator_to_raw_pointer(seq.end())
0324 , comp
0325 , boost::movelib::iterator_to_raw_pointer(tseq.begin())
0326 , tseq.capacity());
0327 }
0328 else{
0329 boost::movelib::adaptive_sort
0330 (boost::movelib::iterator_to_raw_pointer(seq.begin())
0331 , boost::movelib::iterator_to_raw_pointer(seq.end())
0332 , comp
0333 , boost::movelib::iterator_to_raw_pointer(seq.end())
0334 , seq.capacity() - seq.size());
0335 }
0336 }
0337
0338 template<class SequenceContainer, class Compare>
0339 inline void flat_tree_adopt_sequence_equal
0340 (SequenceContainer &tseq, BOOST_RV_REF(SequenceContainer) seq, Compare comp, dtl::true_)
0341 {
0342 flat_tree_sort_contiguous_to_adopt(tseq, boost::move(seq), comp);
0343 tseq = boost::move(seq);
0344 }
0345
0346 template<class SequenceContainer, class Compare>
0347 inline void flat_tree_adopt_sequence_equal
0348 (SequenceContainer &tseq, BOOST_RV_REF(SequenceContainer) seq, Compare comp, dtl::false_)
0349 {
0350 boost::movelib::adaptive_sort(seq.begin(), seq.end(), comp);
0351 tseq = boost::move(seq);
0352 }
0353
0354
0355
0356
0357
0358
0359 template<class SequenceContainer, class Compare>
0360 void flat_tree_adopt_sequence_unique
0361 (SequenceContainer &tseq, BOOST_RV_REF(SequenceContainer) seq, Compare comp, dtl::true_)
0362 {
0363 boost::movelib::pdqsort
0364 ( boost::movelib::iterator_to_raw_pointer(seq.begin())
0365 , boost::movelib::iterator_to_raw_pointer(seq.end())
0366 , comp);
0367 seq.erase(boost::movelib::unique
0368 (seq.begin(), seq.end(), boost::movelib::negate<Compare>(comp)), seq.cend());
0369 tseq = boost::move(seq);
0370 }
0371
0372 template<class SequenceContainer, class Compare>
0373 void flat_tree_adopt_sequence_unique
0374 (SequenceContainer &tseq, BOOST_RV_REF(SequenceContainer) seq, Compare comp, dtl::false_)
0375 {
0376 boost::movelib::pdqsort(seq.begin(), seq.end(), comp);
0377 seq.erase(boost::movelib::unique
0378 (seq.begin(), seq.end(), boost::movelib::negate<Compare>(comp)), seq.cend());
0379 tseq = boost::move(seq);
0380 }
0381
0382
0383
0384
0385
0386
0387 template<class SequenceContainer>
0388 inline void
0389 flat_tree_reserve(SequenceContainer &tseq, typename SequenceContainer::size_type cap, dtl::true_)
0390 {
0391 tseq.reserve(cap);
0392 }
0393
0394 template<class SequenceContainer>
0395 inline void
0396 flat_tree_reserve(SequenceContainer &, typename SequenceContainer::size_type, dtl::false_)
0397 {
0398 }
0399
0400
0401
0402
0403
0404
0405 template<class SequenceContainer>
0406 inline typename SequenceContainer::size_type
0407 flat_tree_capacity(const SequenceContainer &tseq, dtl::true_)
0408 {
0409 return tseq.capacity();
0410 }
0411
0412 template<class SequenceContainer>
0413 inline typename SequenceContainer::size_type
0414 flat_tree_capacity(const SequenceContainer &tseq, dtl::false_)
0415 {
0416 return tseq.size();
0417 }
0418
0419
0420
0421
0422
0423
0424
0425 template<class Compare, class Value, class KeyOfValue>
0426 class flat_tree_value_compare
0427 : private Compare
0428 {
0429 typedef Value first_argument_type;
0430 typedef Value second_argument_type;
0431 typedef bool return_type;
0432 public:
0433 inline flat_tree_value_compare()
0434 : Compare()
0435 {}
0436
0437 inline flat_tree_value_compare(const Compare &pred)
0438 : Compare(pred)
0439 {}
0440
0441 inline bool operator()(const Value& lhs, const Value& rhs) const
0442 {
0443 KeyOfValue key_extract;
0444 return Compare::operator()(key_extract(lhs), key_extract(rhs));
0445 }
0446
0447 inline const Compare &get_comp() const
0448 { return *this; }
0449
0450 inline Compare &get_comp()
0451 { return *this; }
0452 };
0453
0454
0455
0456
0457
0458
0459
0460 template < class Value, class AllocatorOrContainer
0461 , bool = boost::container::dtl::is_container<AllocatorOrContainer>::value
0462 >
0463 struct select_container_type
0464 {
0465 typedef AllocatorOrContainer type;
0466 };
0467
0468 template <class Value, class AllocatorOrContainer>
0469 struct select_container_type<Value, AllocatorOrContainer, false>
0470 {
0471 typedef boost::container::vector<Value, typename real_allocator<Value, AllocatorOrContainer>::type> type;
0472 };
0473
0474
0475
0476
0477
0478
0479
0480 template <class Value, class KeyOfValue,
0481 class Compare, class AllocatorOrContainer>
0482 class flat_tree
0483 {
0484 public:
0485 typedef typename select_container_type<Value, AllocatorOrContainer>::type container_type;
0486 typedef container_type sequence_type;
0487
0488 private:
0489 typedef typename container_type::allocator_type allocator_t;
0490 typedef allocator_traits<allocator_t> allocator_traits_type;
0491
0492 public:
0493 typedef flat_tree_value_compare<Compare, Value, KeyOfValue> value_compare;
0494
0495 private:
0496
0497 struct Data
0498
0499 : public value_compare
0500 {
0501 BOOST_COPYABLE_AND_MOVABLE(Data)
0502
0503 public:
0504 inline Data()
0505 : value_compare(), m_seq()
0506 {}
0507
0508 inline explicit Data(const allocator_t &alloc)
0509 : value_compare(), m_seq(alloc)
0510 {}
0511
0512 inline explicit Data(const Compare &comp)
0513 : value_compare(comp), m_seq()
0514 {}
0515
0516 inline Data(const Compare &comp, const allocator_t &alloc)
0517 : value_compare(comp), m_seq(alloc)
0518 {}
0519
0520 inline explicit Data(const Data &d)
0521 : value_compare(static_cast<const value_compare&>(d)), m_seq(d.m_seq)
0522 {}
0523
0524 inline Data(BOOST_RV_REF(Data) d)
0525 : value_compare(boost::move(static_cast<value_compare&>(d))), m_seq(boost::move(d.m_seq))
0526 {}
0527
0528 inline Data(const Data &d, const allocator_t &a)
0529 : value_compare(static_cast<const value_compare&>(d)), m_seq(d.m_seq, a)
0530 {}
0531
0532 inline Data(BOOST_RV_REF(Data) d, const allocator_t &a)
0533 : value_compare(boost::move(static_cast<value_compare&>(d))), m_seq(boost::move(d.m_seq), a)
0534 {}
0535
0536 Data& operator=(BOOST_COPY_ASSIGN_REF(Data) d)
0537 {
0538 this->value_compare::operator=(d);
0539 m_seq = d.m_seq;
0540 return *this;
0541 }
0542
0543 Data& operator=(BOOST_RV_REF(Data) d)
0544 {
0545 this->value_compare::operator=(boost::move(static_cast<value_compare &>(d)));
0546 m_seq = boost::move(d.m_seq);
0547 return *this;
0548 }
0549
0550 void swap(Data &d)
0551 {
0552 value_compare& mycomp = *this, & othercomp = d;
0553 boost::adl_move_swap(mycomp, othercomp);
0554 this->m_seq.swap(d.m_seq);
0555 }
0556
0557 container_type m_seq;
0558 };
0559
0560 Data m_data;
0561 BOOST_COPYABLE_AND_MOVABLE(flat_tree)
0562
0563 public:
0564
0565 typedef typename container_type::value_type value_type;
0566 typedef typename container_type::pointer pointer;
0567 typedef typename container_type::const_pointer const_pointer;
0568 typedef typename container_type::reference reference;
0569 typedef typename container_type::const_reference const_reference;
0570 typedef typename KeyOfValue::type key_type;
0571 typedef Compare key_compare;
0572 typedef typename container_type::allocator_type allocator_type;
0573 typedef typename container_type::size_type size_type;
0574 typedef typename container_type::difference_type difference_type;
0575 typedef typename container_type::iterator iterator;
0576 typedef typename container_type::const_iterator const_iterator;
0577 typedef typename container_type::reverse_iterator reverse_iterator;
0578 typedef typename container_type::const_reverse_iterator const_reverse_iterator;
0579
0580
0581 typedef BOOST_INTRUSIVE_OBTAIN_TYPE_WITH_DEFAULT
0582 (boost::container::dtl::, container_type
0583 ,stored_allocator_type, allocator_type) stored_allocator_type;
0584
0585 BOOST_STATIC_CONSTEXPR bool has_stored_allocator_type =
0586 BOOST_INTRUSIVE_HAS_TYPE(boost::container::dtl::, container_type, stored_allocator_type);
0587
0588 private:
0589 typedef allocator_traits<stored_allocator_type> stored_allocator_traits;
0590
0591 public:
0592 typedef typename dtl::if_c
0593 <has_stored_allocator_type, const stored_allocator_type &, allocator_type>::type get_stored_allocator_const_return_t;
0594
0595 typedef typename dtl::if_c
0596 <has_stored_allocator_type, stored_allocator_type &, allocator_type>::type get_stored_allocator_noconst_return_t;
0597
0598 inline flat_tree()
0599 : m_data()
0600 { }
0601
0602 inline explicit flat_tree(const Compare& comp)
0603 : m_data(comp)
0604 { }
0605
0606 inline explicit flat_tree(const allocator_type& a)
0607 : m_data(a)
0608 { }
0609
0610 inline flat_tree(const Compare& comp, const allocator_type& a)
0611 : m_data(comp, a)
0612 { }
0613
0614 inline flat_tree(const flat_tree& x)
0615 : m_data(x.m_data)
0616 { }
0617
0618 inline flat_tree(BOOST_RV_REF(flat_tree) x)
0619 BOOST_NOEXCEPT_IF(boost::container::dtl::is_nothrow_move_constructible<Compare>::value)
0620 : m_data(boost::move(x.m_data))
0621 { }
0622
0623 inline flat_tree(const flat_tree& x, const allocator_type &a)
0624 : m_data(x.m_data, a)
0625 { }
0626
0627 inline flat_tree(BOOST_RV_REF(flat_tree) x, const allocator_type &a)
0628 : m_data(boost::move(x.m_data), a)
0629 { }
0630
0631 template <class InputIterator>
0632 inline
0633 flat_tree( ordered_range_t, InputIterator first, InputIterator last)
0634 : m_data()
0635 {
0636 this->m_data.m_seq.insert(this->m_data.m_seq.end(), first, last);
0637 BOOST_ASSERT((is_sorted)(this->m_data.m_seq.cbegin(), this->m_data.m_seq.cend(), this->priv_value_comp()));
0638 }
0639
0640 template <class InputIterator>
0641 inline
0642 flat_tree( ordered_range_t, InputIterator first, InputIterator last, const Compare& comp)
0643 : m_data(comp)
0644 {
0645 this->m_data.m_seq.insert(this->m_data.m_seq.end(), first, last);
0646 BOOST_ASSERT((is_sorted)(this->m_data.m_seq.cbegin(), this->m_data.m_seq.cend(), this->priv_value_comp()));
0647 }
0648
0649 template <class InputIterator>
0650 inline
0651 flat_tree( ordered_range_t, InputIterator first, InputIterator last, const Compare& comp, const allocator_type& a)
0652 : m_data(comp, a)
0653 {
0654 this->m_data.m_seq.insert(this->m_data.m_seq.end(), first, last);
0655 BOOST_ASSERT((is_sorted)(this->m_data.m_seq.cbegin(), this->m_data.m_seq.cend(), this->priv_value_comp()));
0656 }
0657
0658 template <class InputIterator>
0659 inline
0660 flat_tree( ordered_unique_range_t, InputIterator first, InputIterator last)
0661 : m_data()
0662 {
0663 this->m_data.m_seq.insert(this->m_data.m_seq.end(), first, last);
0664 BOOST_ASSERT((is_sorted_and_unique)(this->m_data.m_seq.cbegin(), this->m_data.m_seq.cend(), this->priv_value_comp()));
0665 }
0666
0667 template <class InputIterator>
0668 inline
0669 flat_tree( ordered_unique_range_t, InputIterator first, InputIterator last, const Compare& comp)
0670 : m_data(comp)
0671 {
0672 this->m_data.m_seq.insert(this->m_data.m_seq.end(), first, last);
0673 BOOST_ASSERT((is_sorted_and_unique)(this->m_data.m_seq.cbegin(), this->m_data.m_seq.cend(), this->priv_value_comp()));
0674 }
0675
0676 template <class InputIterator>
0677 inline
0678 flat_tree( ordered_unique_range_t, InputIterator first, InputIterator last, const Compare& comp, const allocator_type& a)
0679 : m_data(comp, a)
0680 {
0681 this->m_data.m_seq.insert(this->m_data.m_seq.end(), first, last);
0682 BOOST_ASSERT((is_sorted_and_unique)(this->m_data.m_seq.cbegin(), this->m_data.m_seq.cend(), this->priv_value_comp()));
0683 }
0684
0685 template <class InputIterator>
0686 inline
0687 flat_tree( bool unique_insertion, InputIterator first, InputIterator last)
0688 : m_data()
0689 {
0690 this->priv_range_insertion_construct(unique_insertion, first, last);
0691 }
0692
0693 template <class InputIterator>
0694 inline
0695 flat_tree( bool unique_insertion, InputIterator first, InputIterator last
0696 , const Compare& comp)
0697 : m_data(comp)
0698 {
0699 this->priv_range_insertion_construct(unique_insertion, first, last);
0700 }
0701
0702 template <class InputIterator>
0703 inline
0704 flat_tree( bool unique_insertion, InputIterator first, InputIterator last
0705 , const allocator_type& a)
0706 : m_data(a)
0707 {
0708 this->priv_range_insertion_construct(unique_insertion, first, last);
0709 }
0710
0711 template <class InputIterator>
0712 inline
0713 flat_tree( bool unique_insertion, InputIterator first, InputIterator last
0714 , const Compare& comp, const allocator_type& a)
0715 : m_data(comp, a)
0716 {
0717 this->priv_range_insertion_construct(unique_insertion, first, last);
0718 }
0719
0720 inline ~flat_tree()
0721 {}
0722
0723 inline flat_tree& operator=(BOOST_COPY_ASSIGN_REF(flat_tree) x)
0724 { m_data = x.m_data; return *this; }
0725
0726 inline flat_tree& operator=(BOOST_RV_REF(flat_tree) x)
0727 BOOST_NOEXCEPT_IF( (allocator_traits_type::propagate_on_container_move_assignment::value ||
0728 allocator_traits_type::is_always_equal::value) &&
0729 boost::container::dtl::is_nothrow_move_assignable<Compare>::value)
0730 { m_data = boost::move(x.m_data); return *this; }
0731
0732 inline const value_compare &priv_value_comp() const
0733 { return static_cast<const value_compare &>(this->m_data); }
0734
0735 inline value_compare &priv_value_comp()
0736 { return static_cast<value_compare &>(this->m_data); }
0737
0738 inline const key_compare &priv_key_comp() const
0739 { return this->priv_value_comp().get_comp(); }
0740
0741 inline key_compare &priv_key_comp()
0742 { return this->priv_value_comp().get_comp(); }
0743
0744 struct insert_commit_data
0745 {
0746 const_iterator position;
0747 };
0748
0749 public:
0750
0751 BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline
0752 Compare key_comp() const
0753 { return this->m_data.get_comp(); }
0754
0755 BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline
0756 value_compare value_comp() const
0757 { return this->m_data; }
0758
0759 BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline
0760 allocator_type get_allocator() const
0761 { return this->m_data.m_seq.get_allocator(); }
0762
0763 BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline
0764 get_stored_allocator_const_return_t get_stored_allocator() const
0765 {
0766 return flat_tree_get_stored_allocator(this->m_data.m_seq, dtl::bool_<has_stored_allocator_type>());
0767 }
0768
0769 BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline
0770 get_stored_allocator_noconst_return_t get_stored_allocator()
0771 {
0772 return flat_tree_get_stored_allocator(this->m_data.m_seq, dtl::bool_<has_stored_allocator_type>());
0773 }
0774
0775 BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline
0776 iterator begin()
0777 { return this->m_data.m_seq.begin(); }
0778
0779 BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline
0780 const_iterator begin() const
0781 { return this->cbegin(); }
0782
0783 BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline
0784 const_iterator cbegin() const
0785 { return this->m_data.m_seq.begin(); }
0786
0787 BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline
0788 iterator end()
0789 { return this->m_data.m_seq.end(); }
0790
0791 BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline
0792 const_iterator end() const
0793 { return this->cend(); }
0794
0795 BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline
0796 const_iterator cend() const
0797 { return this->m_data.m_seq.end(); }
0798
0799 BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline
0800 reverse_iterator rbegin()
0801 { return reverse_iterator(this->end()); }
0802
0803 BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline
0804 const_reverse_iterator rbegin() const
0805 { return this->crbegin(); }
0806
0807 BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline
0808 const_reverse_iterator crbegin() const
0809 { return const_reverse_iterator(this->cend()); }
0810
0811 BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline
0812 reverse_iterator rend()
0813 { return reverse_iterator(this->begin()); }
0814
0815 BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline
0816 const_reverse_iterator rend() const
0817 { return this->crend(); }
0818
0819 BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline
0820 const_reverse_iterator crend() const
0821 { return const_reverse_iterator(this->cbegin()); }
0822
0823 BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline
0824 bool empty() const
0825 { return this->m_data.m_seq.empty(); }
0826
0827 BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline
0828 size_type size() const
0829 { return this->m_data.m_seq.size(); }
0830
0831 BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline
0832 size_type max_size() const
0833 { return this->m_data.m_seq.max_size(); }
0834
0835 inline void swap(flat_tree& other)
0836 BOOST_NOEXCEPT_IF( allocator_traits_type::is_always_equal::value
0837 && boost::container::dtl::is_nothrow_swappable<Compare>::value )
0838 { this->m_data.swap(other.m_data); }
0839
0840 public:
0841
0842 std::pair<iterator,bool> insert_unique(const value_type& val)
0843 {
0844 std::pair<iterator,bool> ret;
0845 insert_commit_data data;
0846 ret.second = this->priv_insert_unique_prepare(KeyOfValue()(val), data);
0847 ret.first = ret.second ? this->priv_insert_commit(data, val)
0848 : this->begin() + (data.position - this->cbegin());
0849
0850 return ret;
0851 }
0852
0853 std::pair<iterator,bool> insert_unique(BOOST_RV_REF(value_type) val)
0854 {
0855 std::pair<iterator,bool> ret;
0856 insert_commit_data data;
0857 ret.second = this->priv_insert_unique_prepare(KeyOfValue()(val), data);
0858 ret.first = ret.second ? this->priv_insert_commit(data, boost::move(val))
0859 : this->begin() + (data.position - this->cbegin());
0860
0861 return ret;
0862 }
0863
0864 iterator insert_equal(const value_type& val)
0865 {
0866 iterator i = this->upper_bound(KeyOfValue()(val));
0867 i = this->m_data.m_seq.insert(i, val);
0868 return i;
0869 }
0870
0871 iterator insert_equal(BOOST_RV_REF(value_type) mval)
0872 {
0873 iterator i = this->upper_bound(KeyOfValue()(mval));
0874 i = this->m_data.m_seq.insert(i, boost::move(mval));
0875 return i;
0876 }
0877
0878 iterator insert_unique(const_iterator hint, const value_type& val)
0879 {
0880 BOOST_ASSERT(this->priv_in_range_or_end(hint));
0881 insert_commit_data data;
0882 return this->priv_insert_unique_prepare(hint, KeyOfValue()(val), data)
0883 ? this->priv_insert_commit(data, val)
0884 : this->begin() + (data.position - this->cbegin());
0885
0886 }
0887
0888 iterator insert_unique(const_iterator hint, BOOST_RV_REF(value_type) val)
0889 {
0890 BOOST_ASSERT(this->priv_in_range_or_end(hint));
0891 insert_commit_data data;
0892 return this->priv_insert_unique_prepare(hint, KeyOfValue()(val), data)
0893 ? this->priv_insert_commit(data, boost::move(val))
0894 : this->begin() + (data.position - this->cbegin());
0895
0896 }
0897
0898 iterator insert_equal(const_iterator hint, const value_type& val)
0899 {
0900 BOOST_ASSERT(this->priv_in_range_or_end(hint));
0901 insert_commit_data data;
0902 this->priv_insert_equal_prepare(hint, val, data);
0903 return this->priv_insert_commit(data, val);
0904 }
0905
0906 iterator insert_equal(const_iterator hint, BOOST_RV_REF(value_type) mval)
0907 {
0908 BOOST_ASSERT(this->priv_in_range_or_end(hint));
0909 insert_commit_data data;
0910 this->priv_insert_equal_prepare(hint, mval, data);
0911 return this->priv_insert_commit(data, boost::move(mval));
0912 }
0913
0914 template <class InIt>
0915 void insert_unique(InIt first, InIt last)
0916 {
0917 dtl::bool_<is_contiguous_container<container_type>::value> contiguous_tag;
0918 container_type &seq = this->m_data.m_seq;
0919 value_compare &val_cmp = this->priv_value_comp();
0920
0921
0922 typename container_type::iterator const it = seq.insert(seq.cend(), first, last);
0923
0924
0925 boost::movelib::pdqsort(it, seq.end(), val_cmp);
0926
0927
0928 typename container_type::iterator const e = boost::movelib::inplace_set_unique_difference
0929 (it, seq.end(), seq.begin(), it, val_cmp);
0930
0931 seq.erase(e, seq.cend());
0932
0933 if (it != e)
0934 {
0935
0936 (flat_tree_container_inplace_merge)(seq, it, this->priv_value_comp(), contiguous_tag);
0937 }
0938 }
0939
0940 template <class InIt>
0941 void insert_equal(InIt first, InIt last)
0942 {
0943 if (first != last) {
0944 dtl::bool_<is_contiguous_container<container_type>::value> contiguous_tag;
0945 container_type &seq = this->m_data.m_seq;
0946 typename container_type::iterator const it = seq.insert(seq.cend(), first, last);
0947 (flat_tree_container_inplace_sort_ending)(seq, it, this->priv_value_comp(), contiguous_tag);
0948 (flat_tree_container_inplace_merge) (seq, it, this->priv_value_comp(), contiguous_tag);
0949 }
0950 }
0951
0952
0953
0954 template <class InIt>
0955 void insert_equal(ordered_range_t, InIt first, InIt last)
0956 {
0957 BOOST_ASSERT((is_sorted)(first, last, this->priv_value_comp()));
0958 const bool value = boost::container::dtl::
0959 has_member_function_callable_with_merge_unique<container_type, InIt, InIt, value_compare>::value;
0960 (flat_tree_merge_equal)(this->m_data.m_seq, first, last, this->priv_value_comp(), dtl::bool_<value>());
0961 }
0962
0963 template <class InIt>
0964 void insert_unique(ordered_unique_range_t, InIt first, InIt last)
0965 {
0966 BOOST_ASSERT((is_sorted_and_unique)(this->m_data.m_seq.cbegin(), this->m_data.m_seq.cend(), this->priv_value_comp()));
0967 const bool value = boost::container::dtl::
0968 has_member_function_callable_with_merge_unique<container_type, InIt, InIt, value_compare>::value;
0969 (flat_tree_merge_unique)(this->m_data.m_seq, first, last, this->priv_value_comp(), dtl::bool_<value>());
0970 }
0971
0972 #if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
0973
0974 template <class... Args>
0975 std::pair<iterator, bool> emplace_unique(BOOST_FWD_REF(Args)... args)
0976 {
0977 typename dtl::aligned_storage<sizeof(value_type), dtl::alignment_of<value_type>::value>::type v;
0978 get_stored_allocator_noconst_return_t a = this->get_stored_allocator();
0979 stored_allocator_traits::construct(a, (value_type *)(&v), ::boost::forward<Args>(args)... );
0980 value_type *pval = move_detail::launder_cast<value_type *>(&v);
0981 value_destructor<stored_allocator_type, value_type> d(a, *pval);
0982 return this->insert_unique(::boost::move(*pval));
0983 }
0984
0985 template <class... Args>
0986 iterator emplace_hint_unique(const_iterator hint, BOOST_FWD_REF(Args)... args)
0987 {
0988
0989 typename dtl::aligned_storage<sizeof(value_type), dtl::alignment_of<value_type>::value>::type v;
0990 get_stored_allocator_noconst_return_t a = this->get_stored_allocator();
0991 stored_allocator_traits::construct(a, (value_type*)(&v), ::boost::forward<Args>(args)... );
0992 value_type *pval = move_detail::launder_cast<value_type *>(&v);
0993 value_destructor<stored_allocator_type, value_type> d(a, *pval);
0994 return this->insert_unique(hint, ::boost::move(*pval));
0995 }
0996
0997 template <class... Args>
0998 iterator emplace_equal(BOOST_FWD_REF(Args)... args)
0999 {
1000 typename dtl::aligned_storage<sizeof(value_type), dtl::alignment_of<value_type>::value>::type v;
1001 get_stored_allocator_noconst_return_t a = this->get_stored_allocator();
1002 stored_allocator_traits::construct(a, (value_type*)(&v), ::boost::forward<Args>(args)... );
1003 value_type *pval = move_detail::launder_cast<value_type *>(&v);
1004 value_destructor<stored_allocator_type, value_type> d(a, *pval);
1005 return this->insert_equal(::boost::move(*pval));
1006 }
1007
1008 template <class... Args>
1009 iterator emplace_hint_equal(const_iterator hint, BOOST_FWD_REF(Args)... args)
1010 {
1011
1012 typename dtl::aligned_storage<sizeof(value_type), dtl::alignment_of<value_type>::value>::type v;
1013 get_stored_allocator_noconst_return_t a = this->get_stored_allocator();
1014 stored_allocator_traits::construct(a, (value_type*)(&v), ::boost::forward<Args>(args)... );
1015 value_type *pval = move_detail::launder_cast<value_type *>(&v);
1016 value_destructor<stored_allocator_type, value_type> d(a, *pval);
1017 return this->insert_equal(hint, ::boost::move(*pval));
1018 }
1019
1020 template <class KeyType, class... Args>
1021 inline std::pair<iterator, bool> try_emplace
1022 (const_iterator hint, BOOST_FWD_REF(KeyType) key, BOOST_FWD_REF(Args)... args)
1023 {
1024 std::pair<iterator,bool> ret;
1025 insert_commit_data data;
1026 const key_type & k = key;
1027 ret.second = hint == const_iterator()
1028 ? this->priv_insert_unique_prepare(k, data)
1029 : this->priv_insert_unique_prepare(hint, k, data);
1030
1031 if(!ret.second){
1032 ret.first = this->nth(size_type(data.position - this->cbegin()));
1033 }
1034 else{
1035 ret.first = this->m_data.m_seq.emplace(data.position, try_emplace_t(), ::boost::forward<KeyType>(key), ::boost::forward<Args>(args)...);
1036 }
1037 return ret;
1038 }
1039
1040 #else
1041
1042 #define BOOST_CONTAINER_FLAT_TREE_EMPLACE_CODE(N) \
1043 BOOST_MOVE_TMPL_LT##N BOOST_MOVE_CLASS##N BOOST_MOVE_GT##N \
1044 std::pair<iterator, bool> emplace_unique(BOOST_MOVE_UREF##N)\
1045 {\
1046 typename dtl::aligned_storage<sizeof(value_type), dtl::alignment_of<value_type>::value>::type v;\
1047 get_stored_allocator_noconst_return_t a = this->get_stored_allocator();\
1048 stored_allocator_traits::construct(a, (value_type *)(&v) BOOST_MOVE_I##N BOOST_MOVE_FWD##N);\
1049 value_type *pval = move_detail::launder_cast<value_type *>(&v);\
1050 value_destructor<stored_allocator_type, value_type> d(a, *pval);\
1051 return this->insert_unique(::boost::move(*pval));\
1052 }\
1053 \
1054 BOOST_MOVE_TMPL_LT##N BOOST_MOVE_CLASS##N BOOST_MOVE_GT##N \
1055 iterator emplace_hint_unique(const_iterator hint BOOST_MOVE_I##N BOOST_MOVE_UREF##N)\
1056 {\
1057 typename dtl::aligned_storage<sizeof(value_type), dtl::alignment_of<value_type>::value>::type v;\
1058 get_stored_allocator_noconst_return_t a = this->get_stored_allocator();\
1059 stored_allocator_traits::construct(a, (value_type *)(&v) BOOST_MOVE_I##N BOOST_MOVE_FWD##N);\
1060 value_type *pval = move_detail::launder_cast<value_type *>(&v);\
1061 value_destructor<stored_allocator_type, value_type> d(a, *pval);\
1062 return this->insert_unique(hint, ::boost::move(*pval));\
1063 }\
1064 \
1065 BOOST_MOVE_TMPL_LT##N BOOST_MOVE_CLASS##N BOOST_MOVE_GT##N \
1066 iterator emplace_equal(BOOST_MOVE_UREF##N)\
1067 {\
1068 typename dtl::aligned_storage<sizeof(value_type), dtl::alignment_of<value_type>::value>::type v;\
1069 get_stored_allocator_noconst_return_t a = this->get_stored_allocator();\
1070 stored_allocator_traits::construct(a, (value_type *)(&v) BOOST_MOVE_I##N BOOST_MOVE_FWD##N);\
1071 value_type *pval = move_detail::launder_cast<value_type *>(&v);\
1072 value_destructor<stored_allocator_type, value_type> d(a, *pval);\
1073 return this->insert_equal(::boost::move(*pval));\
1074 }\
1075 \
1076 BOOST_MOVE_TMPL_LT##N BOOST_MOVE_CLASS##N BOOST_MOVE_GT##N \
1077 iterator emplace_hint_equal(const_iterator hint BOOST_MOVE_I##N BOOST_MOVE_UREF##N)\
1078 {\
1079 typename dtl::aligned_storage <sizeof(value_type), dtl::alignment_of<value_type>::value>::type v;\
1080 get_stored_allocator_noconst_return_t a = this->get_stored_allocator();\
1081 stored_allocator_traits::construct(a, (value_type *)(&v) BOOST_MOVE_I##N BOOST_MOVE_FWD##N);\
1082 value_type *pval = move_detail::launder_cast<value_type *>(&v);\
1083 value_destructor<stored_allocator_type, value_type> d(a, *pval);\
1084 return this->insert_equal(hint, ::boost::move(*pval));\
1085 }\
1086 template <class KeyType BOOST_MOVE_I##N BOOST_MOVE_CLASS##N>\
1087 inline std::pair<iterator, bool>\
1088 try_emplace(const_iterator hint, BOOST_FWD_REF(KeyType) key BOOST_MOVE_I##N BOOST_MOVE_UREF##N)\
1089 {\
1090 std::pair<iterator,bool> ret;\
1091 insert_commit_data data;\
1092 const key_type & k = key;\
1093 ret.second = hint == const_iterator()\
1094 ? this->priv_insert_unique_prepare(k, data)\
1095 : this->priv_insert_unique_prepare(hint, k, data);\
1096 \
1097 if(!ret.second){\
1098 ret.first = this->nth(size_type(data.position - this->cbegin()));\
1099 }\
1100 else{\
1101 ret.first = this->m_data.m_seq.emplace(data.position, try_emplace_t(), ::boost::forward<KeyType>(key) BOOST_MOVE_I##N BOOST_MOVE_FWD##N);\
1102 }\
1103 return ret;\
1104 }\
1105
1106 BOOST_MOVE_ITERATE_0TO7(BOOST_CONTAINER_FLAT_TREE_EMPLACE_CODE)
1107 #undef BOOST_CONTAINER_FLAT_TREE_EMPLACE_CODE
1108
1109 #endif
1110
1111 template<class KeyType, class M>
1112 std::pair<iterator, bool> insert_or_assign(const_iterator hint, BOOST_FWD_REF(KeyType) key, BOOST_FWD_REF(M) obj)
1113 {
1114 const key_type& k = key;
1115 std::pair<iterator,bool> ret;
1116 insert_commit_data data;
1117 ret.second = hint == const_iterator()
1118 ? this->priv_insert_unique_prepare(k, data)
1119 : this->priv_insert_unique_prepare(hint, k, data);
1120 if(!ret.second){
1121 ret.first = this->nth(size_type(data.position - this->cbegin()));
1122 ret.first->second = boost::forward<M>(obj);
1123 }
1124 else{
1125 ret.first = this->m_data.m_seq.emplace(data.position, boost::forward<KeyType>(key), boost::forward<M>(obj));
1126 }
1127 return ret;
1128 }
1129
1130 size_type erase(const key_type& k)
1131 {
1132 std::pair<iterator,iterator > itp = this->equal_range(k);
1133 size_type ret = static_cast<size_type>(itp.second-itp.first);
1134 if (ret){
1135 this->m_data.m_seq.erase(itp.first, itp.second);
1136 }
1137 return ret;
1138 }
1139
1140 size_type erase_unique(const key_type& k)
1141 {
1142 const_iterator i = static_cast<const flat_tree &>(*this).find(k);
1143 size_type ret = static_cast<size_type>(i != this->cend());
1144 if (ret)
1145 this->erase(i);
1146 return ret;
1147 }
1148
1149 template <class K>
1150 inline typename dtl::enable_if_c<
1151 dtl::is_transparent<key_compare>::value &&
1152 !dtl::is_convertible<K, iterator>::value &&
1153 !dtl::is_convertible<K, const_iterator>::value
1154 , size_type>::type
1155 erase(const K& k)
1156 {
1157 std::pair<iterator, iterator > itp = this->equal_range(k);
1158 size_type ret = static_cast<size_type>(itp.second - itp.first);
1159 if (ret) {
1160 this->m_data.m_seq.erase(itp.first, itp.second);
1161 }
1162 return ret;
1163 }
1164
1165 template <class K>
1166 inline typename dtl::enable_if_c<
1167 dtl::is_transparent<key_compare>::value &&
1168 !dtl::is_convertible<K, iterator>::value &&
1169 !dtl::is_convertible<K, const_iterator>::value
1170 , size_type>::type
1171 erase_unique(const K& k)
1172 {
1173 const_iterator i = static_cast<const flat_tree&>(*this).find(k);
1174 size_type ret = static_cast<size_type>(i != this->cend());
1175 if (ret)
1176 this->erase(i);
1177 return ret;
1178 }
1179
1180 inline iterator erase(const_iterator position)
1181 { return this->m_data.m_seq.erase(position); }
1182
1183 inline iterator erase(const_iterator first, const_iterator last)
1184 { return this->m_data.m_seq.erase(first, last); }
1185
1186 inline void clear()
1187 { this->m_data.m_seq.clear(); }
1188
1189
1190
1191
1192
1193
1194
1195 inline void shrink_to_fit()
1196 { this->m_data.m_seq.shrink_to_fit(); }
1197
1198 inline iterator nth(size_type n) BOOST_NOEXCEPT_OR_NOTHROW
1199 {
1200 const bool value = boost::container::dtl::
1201 has_member_function_callable_with_nth<container_type, size_type>::value;
1202 return flat_tree_nth<iterator>(this->m_data.m_seq, n, dtl::bool_<value>());
1203 }
1204
1205 BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline
1206 const_iterator nth(size_type n) const BOOST_NOEXCEPT_OR_NOTHROW
1207 {
1208 const bool value = boost::container::dtl::
1209 has_member_function_callable_with_nth<container_type, size_type>::value;
1210 return flat_tree_nth<const_iterator>(this->m_data.m_seq, n, dtl::bool_<value>());
1211 }
1212
1213 BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline
1214 size_type index_of(iterator p) BOOST_NOEXCEPT_OR_NOTHROW
1215 {
1216 const bool value = boost::container::dtl::
1217 has_member_function_callable_with_index_of<container_type, iterator>::value;
1218 return flat_tree_index_of(this->m_data.m_seq, p, dtl::bool_<value>());
1219 }
1220
1221 BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline
1222 size_type index_of(const_iterator p) const BOOST_NOEXCEPT_OR_NOTHROW
1223 {
1224 const bool value = boost::container::dtl::
1225 has_member_function_callable_with_index_of<container_type, const_iterator>::value;
1226 return flat_tree_index_of(this->m_data.m_seq, p, dtl::bool_<value>());
1227 }
1228
1229
1230 BOOST_CONTAINER_ATTRIBUTE_NODISCARD
1231 iterator find(const key_type& k)
1232 {
1233 iterator i = this->lower_bound(k);
1234 iterator end_it = this->end();
1235 if (i != end_it && this->m_data.get_comp()(k, KeyOfValue()(*i))){
1236 i = end_it;
1237 }
1238 return i;
1239 }
1240
1241 BOOST_CONTAINER_ATTRIBUTE_NODISCARD
1242 const_iterator find(const key_type& k) const
1243 {
1244 const_iterator i = this->lower_bound(k);
1245
1246 const_iterator end_it = this->cend();
1247 if (i != end_it && this->m_data.get_comp()(k, KeyOfValue()(*i))){
1248 i = end_it;
1249 }
1250 return i;
1251 }
1252
1253 template<class K>
1254 BOOST_CONTAINER_ATTRIBUTE_NODISCARD
1255 typename dtl::enable_if_transparent<key_compare, K, iterator>::type
1256 find(const K& k)
1257 {
1258 iterator i = this->lower_bound(k);
1259 iterator end_it = this->end();
1260 if (i != end_it && this->m_data.get_comp()(k, KeyOfValue()(*i))){
1261 i = end_it;
1262 }
1263 return i;
1264 }
1265
1266 template<class K>
1267 BOOST_CONTAINER_ATTRIBUTE_NODISCARD
1268 typename dtl::enable_if_transparent<key_compare, K, const_iterator>::type
1269 find(const K& k) const
1270 {
1271 const_iterator i = this->lower_bound(k);
1272
1273 const_iterator end_it = this->cend();
1274 if (i != end_it && this->m_data.get_comp()(k, KeyOfValue()(*i))){
1275 i = end_it;
1276 }
1277 return i;
1278 }
1279
1280 BOOST_CONTAINER_ATTRIBUTE_NODISCARD
1281 size_type count(const key_type& k) const
1282 {
1283 std::pair<const_iterator, const_iterator> p = this->equal_range(k);
1284 size_type n = size_type(p.second - p.first);
1285 return n;
1286 }
1287
1288 template<class K>
1289 BOOST_CONTAINER_ATTRIBUTE_NODISCARD
1290 typename dtl::enable_if_transparent<key_compare, K, size_type>::type
1291 count(const K& k) const
1292 {
1293 std::pair<const_iterator, const_iterator> p = this->equal_range(k);
1294 size_type n = size_type(p.second - p.first);
1295 return n;
1296 }
1297
1298 BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline bool contains(const key_type& x) const
1299 { return this->find(x) != this->cend(); }
1300
1301 template<typename K>
1302 BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline
1303 typename dtl::enable_if_transparent<key_compare, K, bool>::type
1304 contains(const K& x) const
1305 { return this->find(x) != this->cend(); }
1306
1307 template<class C2>
1308 inline void merge_unique(flat_tree<Value, KeyOfValue, C2, AllocatorOrContainer>& source)
1309 {
1310 this->insert_unique( boost::make_move_iterator(source.begin())
1311 , boost::make_move_iterator(source.end()));
1312 }
1313
1314 template<class C2>
1315 inline void merge_equal(flat_tree<Value, KeyOfValue, C2, AllocatorOrContainer>& source)
1316 {
1317 this->insert_equal( boost::make_move_iterator(source.begin())
1318 , boost::make_move_iterator(source.end()));
1319 }
1320
1321 inline void merge_unique(flat_tree& source)
1322 {
1323 const bool value = boost::container::dtl::
1324 has_member_function_callable_with_merge_unique<container_type, iterator, iterator, value_compare>::value;
1325 (flat_tree_merge_unique)
1326 ( this->m_data.m_seq
1327 , boost::make_move_iterator(source.m_data.m_seq.begin())
1328 , boost::make_move_iterator(source.m_data.m_seq.end())
1329 , this->priv_value_comp()
1330 , dtl::bool_<value>());
1331 }
1332
1333 inline void merge_equal(flat_tree& source)
1334 {
1335 const bool value = boost::container::dtl::
1336 has_member_function_callable_with_merge<container_type, iterator, iterator, value_compare>::value;
1337 (flat_tree_merge_equal)
1338 ( this->m_data.m_seq
1339 , boost::make_move_iterator(source.m_data.m_seq.begin())
1340 , boost::make_move_iterator(source.m_data.m_seq.end())
1341 , this->priv_value_comp()
1342 , dtl::bool_<value>());
1343 }
1344
1345 BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline
1346 iterator lower_bound(const key_type& k)
1347 { return this->priv_lower_bound(this->begin(), this->end(), k); }
1348
1349 BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline
1350 const_iterator lower_bound(const key_type& k) const
1351 { return this->priv_lower_bound(this->cbegin(), this->cend(), k); }
1352
1353 template<class K>
1354 BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline
1355 typename dtl::enable_if_transparent<key_compare, K, iterator>::type
1356 lower_bound(const K& k)
1357 { return this->priv_lower_bound(this->begin(), this->end(), k); }
1358
1359 template<class K>
1360 BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline
1361 typename dtl::enable_if_transparent<key_compare, K, const_iterator>::type
1362 lower_bound(const K& k) const
1363 { return this->priv_lower_bound(this->cbegin(), this->cend(), k); }
1364
1365 BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline
1366 iterator upper_bound(const key_type& k)
1367 { return this->priv_upper_bound(this->begin(), this->end(), k); }
1368
1369 BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline
1370 const_iterator upper_bound(const key_type& k) const
1371 { return this->priv_upper_bound(this->cbegin(), this->cend(), k); }
1372
1373 template<class K>
1374 BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline
1375 typename dtl::enable_if_transparent<key_compare, K,iterator>::type
1376 upper_bound(const K& k)
1377 { return this->priv_upper_bound(this->begin(), this->end(), k); }
1378
1379 template<class K>
1380 BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline
1381 typename dtl::enable_if_transparent<key_compare, K,const_iterator>::type
1382 upper_bound(const K& k) const
1383 { return this->priv_upper_bound(this->cbegin(), this->cend(), k); }
1384
1385 BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline
1386 std::pair<iterator,iterator> equal_range(const key_type& k)
1387 { return this->priv_equal_range(this->begin(), this->end(), k); }
1388
1389 BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline
1390 std::pair<const_iterator, const_iterator> equal_range(const key_type& k) const
1391 { return this->priv_equal_range(this->cbegin(), this->cend(), k); }
1392
1393 template<class K>
1394 BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline
1395 typename dtl::enable_if_transparent<key_compare, K, std::pair<iterator,iterator> >::type
1396 equal_range(const K& k)
1397 { return this->priv_equal_range(this->begin(), this->end(), k); }
1398
1399 template<class K>
1400 BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline
1401 typename dtl::enable_if_transparent<key_compare, K,std::pair<const_iterator,const_iterator> >::type
1402 equal_range(const K& k) const
1403 { return this->priv_equal_range(this->cbegin(), this->cend(), k); }
1404
1405
1406 BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline
1407 std::pair<iterator, iterator> lower_bound_range(const key_type& k)
1408 { return this->priv_lower_bound_range(this->begin(), this->end(), k); }
1409
1410 BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline
1411 std::pair<const_iterator, const_iterator> lower_bound_range(const key_type& k) const
1412 { return this->priv_lower_bound_range(this->cbegin(), this->cend(), k); }
1413
1414 template<class K>
1415 BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline
1416 typename dtl::enable_if_transparent<key_compare, K,std::pair<iterator,iterator> >::type
1417 lower_bound_range(const K& k)
1418 { return this->priv_lower_bound_range(this->begin(), this->end(), k); }
1419
1420 template<class K>
1421 BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline
1422 typename dtl::enable_if_transparent<key_compare, K,std::pair<const_iterator,const_iterator> >::type
1423 lower_bound_range(const K& k) const
1424 { return this->priv_lower_bound_range(this->cbegin(), this->cend(), k); }
1425
1426 BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline
1427 size_type capacity() const
1428 {
1429 const bool value = boost::container::dtl::
1430 has_member_function_callable_with_capacity<container_type>::value;
1431 return (flat_tree_capacity)(this->m_data.m_seq, dtl::bool_<value>());
1432 }
1433
1434 inline
1435 void reserve(size_type cnt)
1436 {
1437 const bool value = boost::container::dtl::
1438 has_member_function_callable_with_reserve<container_type, size_type>::value;
1439 (flat_tree_reserve)(this->m_data.m_seq, cnt, dtl::bool_<value>());
1440 }
1441
1442 BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline
1443 container_type extract_sequence()
1444 { return boost::move(m_data.m_seq); }
1445
1446 BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline
1447 container_type &get_sequence_ref()
1448 { return m_data.m_seq; }
1449
1450 BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline
1451 const container_type &get_sequence_cref() const
1452 { return m_data.m_seq; }
1453
1454 inline void adopt_sequence_equal(BOOST_RV_REF(container_type) seq)
1455 {
1456 (flat_tree_adopt_sequence_equal)( m_data.m_seq, boost::move(seq), this->priv_value_comp()
1457 , dtl::bool_<is_contiguous_container<container_type>::value>());
1458 }
1459
1460 inline void adopt_sequence_unique(BOOST_RV_REF(container_type) seq)
1461 {
1462 (flat_tree_adopt_sequence_unique)(m_data.m_seq, boost::move(seq), this->priv_value_comp()
1463 , dtl::bool_<is_contiguous_container<container_type>::value>());
1464 }
1465
1466 void adopt_sequence_equal(ordered_range_t, BOOST_RV_REF(container_type) seq)
1467 {
1468 BOOST_ASSERT((is_sorted)(seq.cbegin(), seq.cend(), this->priv_value_comp()));
1469 m_data.m_seq = boost::move(seq);
1470 }
1471
1472 void adopt_sequence_unique(ordered_unique_range_t, BOOST_RV_REF(container_type) seq)
1473 {
1474 BOOST_ASSERT((is_sorted_and_unique)(seq.cbegin(), seq.cend(), this->priv_value_comp()));
1475 m_data.m_seq = boost::move(seq);
1476 }
1477
1478 BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline
1479 friend bool operator==(const flat_tree& x, const flat_tree& y)
1480 {
1481 return x.size() == y.size() && ::boost::container::algo_equal(x.begin(), x.end(), y.begin());
1482 }
1483
1484 BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline
1485 friend bool operator<(const flat_tree& x, const flat_tree& y)
1486 {
1487 return ::boost::container::algo_lexicographical_compare(x.begin(), x.end(), y.begin(), y.end());
1488 }
1489
1490 BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline
1491 friend bool operator!=(const flat_tree& x, const flat_tree& y)
1492 { return !(x == y); }
1493
1494 BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline
1495 friend bool operator>(const flat_tree& x, const flat_tree& y)
1496 { return y < x; }
1497
1498 BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline
1499 friend bool operator<=(const flat_tree& x, const flat_tree& y)
1500 { return !(y < x); }
1501
1502 BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline
1503 friend bool operator>=(const flat_tree& x, const flat_tree& y)
1504 { return !(x < y); }
1505
1506 inline friend void swap(flat_tree& x, flat_tree& y)
1507 BOOST_NOEXCEPT_IF(BOOST_NOEXCEPT(x.swap(y)))
1508 { x.swap(y); }
1509
1510 private:
1511
1512 template <class InputIterator>
1513 void priv_range_insertion_construct( bool unique_insertion, InputIterator first, InputIterator last)
1514 {
1515
1516
1517
1518
1519 if(unique_insertion){
1520 this->insert_unique(first, last);
1521 }
1522 else{
1523 this->insert_equal (first, last);
1524 }
1525 }
1526
1527 inline bool priv_in_range_or_end(const_iterator pos) const
1528 {
1529 return (this->begin() <= pos) && (pos <= this->end());
1530 }
1531
1532
1533 void priv_insert_equal_prepare
1534 (const_iterator pos, const value_type& val, insert_commit_data &data)
1535 {
1536
1537
1538
1539
1540
1541
1542
1543
1544
1545 const value_compare &val_cmp = this->m_data;
1546
1547 if(pos == this->cend() || !val_cmp(*pos, val)){
1548 if (pos == this->cbegin() || !val_cmp(val, pos[-1])){
1549 data.position = pos;
1550 }
1551 else{
1552 data.position =
1553 this->priv_upper_bound(this->cbegin(), pos, KeyOfValue()(val));
1554 }
1555 }
1556 else{
1557 data.position =
1558 this->priv_lower_bound(pos, this->cend(), KeyOfValue()(val));
1559 }
1560 }
1561
1562 bool priv_insert_unique_prepare
1563 (const_iterator b, const_iterator e, const key_type& k, insert_commit_data &commit_data)
1564 {
1565 const key_compare &key_cmp = this->priv_key_comp();
1566 commit_data.position = this->priv_lower_bound(b, e, k);
1567 return commit_data.position == e || key_cmp(k, KeyOfValue()(*commit_data.position));
1568 }
1569
1570 inline bool priv_insert_unique_prepare
1571 (const key_type& k, insert_commit_data &commit_data)
1572 { return this->priv_insert_unique_prepare(this->cbegin(), this->cend(), k, commit_data); }
1573
1574 bool priv_insert_unique_prepare
1575 (const_iterator pos, const key_type& k, insert_commit_data &commit_data)
1576 {
1577
1578
1579
1580
1581
1582
1583
1584
1585
1586
1587
1588 const key_compare &key_cmp = this->priv_key_comp();
1589 const const_iterator cend_it = this->cend();
1590 if(pos == cend_it || key_cmp(k, KeyOfValue()(*pos))){
1591 const const_iterator cbeg = this->cbegin();
1592 commit_data.position = pos;
1593 if(pos == cbeg){
1594 return true;
1595 }
1596 const_iterator prev(pos);
1597 --prev;
1598 if(key_cmp(KeyOfValue()(*prev), k)){
1599 return true;
1600 }
1601 else if(!key_cmp(k, KeyOfValue()(*prev))){
1602 commit_data.position = prev;
1603 return false;
1604 }
1605 else{
1606
1607 return this->priv_insert_unique_prepare(cbeg, prev, k, commit_data);
1608 }
1609 }
1610 else{
1611
1612
1613 return this->priv_insert_unique_prepare(pos, cend_it, k, commit_data);
1614 }
1615 }
1616
1617 template<class Convertible>
1618 inline iterator priv_insert_commit
1619 (insert_commit_data &commit_data, BOOST_FWD_REF(Convertible) convertible)
1620 {
1621 return this->m_data.m_seq.insert
1622 ( commit_data.position
1623 , boost::forward<Convertible>(convertible));
1624 }
1625
1626 template <class RanIt, class K>
1627 RanIt priv_lower_bound(RanIt first, const RanIt last,
1628 const K & key) const
1629 {
1630 const Compare &key_cmp = this->m_data.get_comp();
1631 KeyOfValue key_extract;
1632 size_type len = static_cast<size_type>(last - first);
1633 RanIt middle;
1634
1635 while (len) {
1636 size_type step = len >> 1;
1637 middle = first;
1638 middle += difference_type(step);
1639
1640 if (key_cmp(key_extract(*middle), key)) {
1641 first = ++middle;
1642 len -= step + 1;
1643 }
1644 else{
1645 len = step;
1646 }
1647 }
1648 return first;
1649 }
1650
1651 template <class RanIt, class K>
1652 RanIt priv_upper_bound
1653 (RanIt first, const RanIt last,const K & key) const
1654 {
1655 const Compare &key_cmp = this->m_data.get_comp();
1656 KeyOfValue key_extract;
1657 size_type len = static_cast<size_type>(last - first);
1658 RanIt middle;
1659
1660 while (len) {
1661 size_type step = len >> 1;
1662 middle = first;
1663 middle += difference_type(step);
1664
1665 if (key_cmp(key, key_extract(*middle))) {
1666 len = step;
1667 }
1668 else{
1669 first = ++middle;
1670 len -= step + 1;
1671 }
1672 }
1673 return first;
1674 }
1675
1676 template <class RanIt, class K>
1677 std::pair<RanIt, RanIt>
1678 priv_equal_range(RanIt first, RanIt last, const K& key) const
1679 {
1680 const Compare &key_cmp = this->m_data.get_comp();
1681 KeyOfValue key_extract;
1682 size_type len = static_cast<size_type>(last - first);
1683 RanIt middle;
1684
1685 while (len) {
1686 size_type step = len >> 1;
1687 middle = first;
1688 middle += difference_type(step);
1689
1690 if (key_cmp(key_extract(*middle), key)){
1691 first = ++middle;
1692 len -= step + 1;
1693 }
1694 else if (key_cmp(key, key_extract(*middle))){
1695 len = step;
1696 }
1697 else {
1698
1699 last = first;
1700 last += difference_type(len);
1701 RanIt const first_ret = this->priv_lower_bound(first, middle, key);
1702 return std::pair<RanIt, RanIt>
1703 ( first_ret, this->priv_upper_bound(++middle, last, key));
1704 }
1705 }
1706 return std::pair<RanIt, RanIt>(first, first);
1707 }
1708
1709 template<class RanIt, class K>
1710 std::pair<RanIt, RanIt> priv_lower_bound_range(RanIt first, RanIt last, const K& k) const
1711 {
1712 const Compare &key_cmp = this->m_data.get_comp();
1713 KeyOfValue key_extract;
1714 RanIt lb(this->priv_lower_bound(first, last, k)), ub(lb);
1715 if(lb != last && !key_cmp(k, key_extract(*lb))){
1716 ++ub;
1717 }
1718 return std::pair<RanIt, RanIt>(lb, ub);
1719 }
1720 };
1721
1722 }
1723
1724 }
1725
1726
1727
1728 template <class T, class KeyOfValue,
1729 class Compare, class AllocatorOrContainer>
1730 struct has_trivial_destructor_after_move<boost::container::dtl::flat_tree<T, KeyOfValue, Compare, AllocatorOrContainer> >
1731 {
1732 typedef boost::container::dtl::flat_tree<T, KeyOfValue, Compare, AllocatorOrContainer> flat_tree;
1733 typedef typename flat_tree::container_type container_type;
1734 typedef typename flat_tree::key_compare key_compare;
1735 BOOST_STATIC_CONSTEXPR bool value = ::boost::has_trivial_destructor_after_move<container_type>::value &&
1736 ::boost::has_trivial_destructor_after_move<key_compare>::value;
1737 };
1738
1739 }
1740
1741 #include <boost/container/detail/config_end.hpp>
1742
1743 #endif