File indexing completed on 2025-07-05 08:36:06
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014 #ifndef BOOST_INTRUSIVE_LIST_HPP
0015 #define BOOST_INTRUSIVE_LIST_HPP
0016
0017 #include <boost/intrusive/detail/config_begin.hpp>
0018 #include <boost/intrusive/intrusive_fwd.hpp>
0019 #include <boost/intrusive/detail/assert.hpp>
0020 #include <boost/intrusive/list_hook.hpp>
0021 #include <boost/intrusive/circular_list_algorithms.hpp>
0022 #include <boost/intrusive/pointer_traits.hpp>
0023 #include <boost/intrusive/detail/mpl.hpp>
0024 #include <boost/intrusive/link_mode.hpp>
0025 #include <boost/intrusive/detail/get_value_traits.hpp>
0026 #include <boost/intrusive/detail/is_stateful_value_traits.hpp>
0027 #include <boost/intrusive/detail/default_header_holder.hpp>
0028 #include <boost/intrusive/detail/reverse_iterator.hpp>
0029 #include <boost/intrusive/detail/uncast.hpp>
0030 #include <boost/intrusive/detail/list_iterator.hpp>
0031 #include <boost/intrusive/detail/array_initializer.hpp>
0032 #include <boost/intrusive/detail/exception_disposer.hpp>
0033 #include <boost/intrusive/detail/equal_to_value.hpp>
0034 #include <boost/intrusive/detail/key_nodeptr_comp.hpp>
0035 #include <boost/intrusive/detail/simple_disposers.hpp>
0036 #include <boost/intrusive/detail/size_holder.hpp>
0037 #include <boost/intrusive/detail/algorithm.hpp>
0038
0039 #include <boost/move/utility_core.hpp>
0040
0041 #include <boost/intrusive/detail/value_functors.hpp>
0042 #include <cstddef> //std::size_t, etc.
0043
0044 #if defined(BOOST_HAS_PRAGMA_ONCE)
0045 # pragma once
0046 #endif
0047
0048 namespace boost {
0049 namespace intrusive {
0050
0051
0052
0053 struct default_list_hook_applier
0054 { template <class T> struct apply{ typedef typename T::default_list_hook type; }; };
0055
0056 template<>
0057 struct is_default_hook_tag<default_list_hook_applier>
0058 { static const bool value = true; };
0059
0060 struct list_defaults
0061 {
0062 typedef default_list_hook_applier proto_value_traits;
0063 static const bool constant_time_size = true;
0064 typedef std::size_t size_type;
0065 typedef void header_holder_type;
0066 };
0067
0068
0069
0070
0071
0072
0073
0074
0075
0076
0077
0078
0079
0080 #if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED)
0081 template<class T, class ...Options>
0082 #else
0083 template <class ValueTraits, class SizeType, bool ConstantTimeSize, typename HeaderHolder>
0084 #endif
0085 class list_impl
0086 {
0087
0088 public:
0089 typedef ValueTraits value_traits;
0090 typedef typename value_traits::pointer pointer;
0091 typedef typename value_traits::const_pointer const_pointer;
0092 typedef typename pointer_traits<pointer>::element_type value_type;
0093 typedef typename pointer_traits<pointer>::reference reference;
0094 typedef typename pointer_traits<const_pointer>::reference const_reference;
0095 typedef typename pointer_traits<pointer>::difference_type difference_type;
0096 typedef SizeType size_type;
0097 typedef list_iterator<value_traits, false> iterator;
0098 typedef list_iterator<value_traits, true> const_iterator;
0099 typedef boost::intrusive::reverse_iterator<iterator> reverse_iterator;
0100 typedef boost::intrusive::reverse_iterator<const_iterator> const_reverse_iterator;
0101 typedef typename value_traits::node_traits node_traits;
0102 typedef typename node_traits::node node;
0103 typedef typename node_traits::node_ptr node_ptr;
0104 typedef typename node_traits::const_node_ptr const_node_ptr;
0105 typedef circular_list_algorithms<node_traits> node_algorithms;
0106 typedef typename detail::get_header_holder_type
0107 < value_traits, HeaderHolder >::type header_holder_type;
0108
0109 static const bool constant_time_size = ConstantTimeSize;
0110 static const bool stateful_value_traits = detail::is_stateful_value_traits<value_traits>::value;
0111 static const bool has_container_from_iterator =
0112 detail::is_same< header_holder_type, detail::default_header_holder< node_traits > >::value;
0113
0114
0115
0116 private:
0117 typedef detail::size_holder<constant_time_size, size_type> size_traits;
0118
0119
0120 BOOST_MOVABLE_BUT_NOT_COPYABLE(list_impl)
0121
0122 static const bool safemode_or_autounlink = is_safe_autounlink<value_traits::link_mode>::value;
0123
0124
0125 BOOST_INTRUSIVE_STATIC_ASSERT(!(constant_time_size &&
0126 ((int)value_traits::link_mode == (int)auto_unlink)
0127 ));
0128
0129 inline node_ptr get_root_node()
0130 { return data_.root_plus_size_.m_header.get_node(); }
0131
0132 inline const_node_ptr get_root_node() const
0133 { return data_.root_plus_size_.m_header.get_node(); }
0134
0135 struct root_plus_size : public size_traits
0136 {
0137 header_holder_type m_header;
0138 };
0139
0140 struct data_t : public value_traits
0141 {
0142 typedef typename list_impl::value_traits value_traits;
0143 inline explicit data_t(const value_traits &val_traits)
0144 : value_traits(val_traits)
0145 {}
0146
0147 root_plus_size root_plus_size_;
0148 } data_;
0149
0150 inline size_traits &priv_size_traits() BOOST_NOEXCEPT
0151 { return data_.root_plus_size_; }
0152
0153 inline const size_traits &priv_size_traits() const BOOST_NOEXCEPT
0154 { return data_.root_plus_size_; }
0155
0156 inline const value_traits &priv_value_traits() const BOOST_NOEXCEPT
0157 { return data_; }
0158
0159 inline value_traits &priv_value_traits() BOOST_NOEXCEPT
0160 { return data_; }
0161
0162 typedef typename boost::intrusive::value_traits_pointers
0163 <ValueTraits>::const_value_traits_ptr const_value_traits_ptr;
0164
0165 inline const_value_traits_ptr priv_value_traits_ptr() const BOOST_NOEXCEPT
0166 { return pointer_traits<const_value_traits_ptr>::pointer_to(this->priv_value_traits()); }
0167
0168
0169
0170 public:
0171
0172
0173
0174
0175
0176
0177
0178 list_impl()
0179 : data_(value_traits())
0180 {
0181 this->priv_size_traits().set_size(size_type(0));
0182 node_algorithms::init_header(this->get_root_node());
0183 }
0184
0185
0186
0187
0188
0189
0190
0191 explicit list_impl(const value_traits &v_traits)
0192 : data_(v_traits)
0193 {
0194 this->priv_size_traits().set_size(size_type(0));
0195 node_algorithms::init_header(this->get_root_node());
0196 }
0197
0198
0199
0200
0201
0202
0203
0204
0205
0206 template<class Iterator>
0207 list_impl(Iterator b, Iterator e, const value_traits &v_traits = value_traits())
0208 : data_(v_traits)
0209 {
0210
0211 this->priv_size_traits().set_size(size_type(0));
0212 node_algorithms::init_header(this->get_root_node());
0213
0214 this->insert(this->cend(), b, e);
0215 }
0216
0217
0218
0219
0220
0221
0222
0223
0224
0225
0226 list_impl(BOOST_RV_REF(list_impl) x)
0227 : data_(::boost::move(x.priv_value_traits()))
0228 {
0229 this->priv_size_traits().set_size(size_type(0));
0230 node_algorithms::init_header(this->get_root_node());
0231
0232 this->swap(x);
0233 }
0234
0235
0236
0237 list_impl& operator=(BOOST_RV_REF(list_impl) x)
0238 { this->swap(x); return *this; }
0239
0240
0241
0242
0243
0244
0245
0246
0247
0248
0249
0250
0251 ~list_impl()
0252 {
0253 BOOST_IF_CONSTEXPR(is_safe_autounlink<ValueTraits::link_mode>::value){
0254 this->clear();
0255 node_algorithms::init(this->get_root_node());
0256 }
0257 }
0258
0259
0260
0261
0262
0263
0264
0265
0266
0267
0268
0269 void push_back(reference value) BOOST_NOEXCEPT
0270 {
0271 node_ptr to_insert = priv_value_traits().to_node_ptr(value);
0272 BOOST_INTRUSIVE_SAFE_HOOK_DEFAULT_ASSERT(!safemode_or_autounlink || node_algorithms::inited(to_insert));
0273 node_algorithms::link_before(this->get_root_node(), to_insert);
0274 this->priv_size_traits().increment();
0275 }
0276
0277
0278
0279
0280
0281
0282
0283
0284
0285
0286
0287 void push_front(reference value) BOOST_NOEXCEPT
0288 {
0289 node_ptr to_insert = priv_value_traits().to_node_ptr(value);
0290 BOOST_INTRUSIVE_SAFE_HOOK_DEFAULT_ASSERT(!safemode_or_autounlink || node_algorithms::inited(to_insert));
0291 node_algorithms::link_before(node_traits::get_next(this->get_root_node()), to_insert);
0292 this->priv_size_traits().increment();
0293 }
0294
0295
0296
0297
0298
0299
0300
0301
0302
0303 void pop_back() BOOST_NOEXCEPT
0304 { return this->pop_back_and_dispose(detail::null_disposer()); }
0305
0306
0307
0308
0309
0310
0311
0312
0313
0314
0315
0316
0317 template<class Disposer>
0318 void pop_back_and_dispose(Disposer disposer) BOOST_NOEXCEPT
0319 {
0320 node_ptr to_erase = node_traits::get_previous(this->get_root_node());
0321 node_algorithms::unlink(to_erase);
0322 this->priv_size_traits().decrement();
0323 BOOST_IF_CONSTEXPR(safemode_or_autounlink)
0324 node_algorithms::init(to_erase);
0325 disposer(priv_value_traits().to_value_ptr(to_erase));
0326 }
0327
0328
0329
0330
0331
0332
0333
0334
0335
0336 void pop_front() BOOST_NOEXCEPT
0337 { return this->pop_front_and_dispose(detail::null_disposer()); }
0338
0339
0340
0341
0342
0343
0344
0345
0346
0347
0348
0349
0350 template<class Disposer>
0351 void pop_front_and_dispose(Disposer disposer) BOOST_NOEXCEPT
0352 {
0353 node_ptr to_erase = node_traits::get_next(this->get_root_node());
0354 node_algorithms::unlink(to_erase);
0355 this->priv_size_traits().decrement();
0356 BOOST_IF_CONSTEXPR(safemode_or_autounlink)
0357 node_algorithms::init(to_erase);
0358 disposer(priv_value_traits().to_value_ptr(to_erase));
0359 }
0360
0361
0362
0363
0364
0365
0366 inline reference front() BOOST_NOEXCEPT
0367 { return *priv_value_traits().to_value_ptr(node_traits::get_next(this->get_root_node())); }
0368
0369
0370
0371
0372
0373
0374 inline const_reference front() const BOOST_NOEXCEPT
0375 { return *priv_value_traits().to_value_ptr(node_traits::get_next(this->get_root_node())); }
0376
0377
0378
0379
0380
0381
0382 inline reference back() BOOST_NOEXCEPT
0383 { return *priv_value_traits().to_value_ptr(node_traits::get_previous(this->get_root_node())); }
0384
0385
0386
0387
0388
0389
0390 inline const_reference back() const BOOST_NOEXCEPT
0391 { return *priv_value_traits().to_value_ptr(detail::uncast(node_traits::get_previous(this->get_root_node()))); }
0392
0393
0394
0395
0396
0397
0398 inline iterator begin() BOOST_NOEXCEPT
0399 { return iterator(node_traits::get_next(this->get_root_node()), this->priv_value_traits_ptr()); }
0400
0401
0402
0403
0404
0405
0406 inline const_iterator begin() const BOOST_NOEXCEPT
0407 { return this->cbegin(); }
0408
0409
0410
0411
0412
0413
0414 inline const_iterator cbegin() const BOOST_NOEXCEPT
0415 { return const_iterator(node_traits::get_next(this->get_root_node()), this->priv_value_traits_ptr()); }
0416
0417
0418
0419
0420
0421
0422 inline iterator end() BOOST_NOEXCEPT
0423 { return iterator(this->get_root_node(), this->priv_value_traits_ptr()); }
0424
0425
0426
0427
0428
0429
0430 inline const_iterator end() const BOOST_NOEXCEPT
0431 { return this->cend(); }
0432
0433
0434
0435
0436
0437
0438 inline const_iterator cend() const BOOST_NOEXCEPT
0439 { return const_iterator(detail::uncast(this->get_root_node()), this->priv_value_traits_ptr()); }
0440
0441
0442
0443
0444
0445
0446
0447 inline reverse_iterator rbegin() BOOST_NOEXCEPT
0448 { return reverse_iterator(this->end()); }
0449
0450
0451
0452
0453
0454
0455
0456 inline const_reverse_iterator rbegin() const BOOST_NOEXCEPT
0457 { return this->crbegin(); }
0458
0459
0460
0461
0462
0463
0464
0465 inline const_reverse_iterator crbegin() const BOOST_NOEXCEPT
0466 { return const_reverse_iterator(end()); }
0467
0468
0469
0470
0471
0472
0473
0474 inline reverse_iterator rend() BOOST_NOEXCEPT
0475 { return reverse_iterator(begin()); }
0476
0477
0478
0479
0480
0481
0482
0483 inline const_reverse_iterator rend() const BOOST_NOEXCEPT
0484 { return this->crend(); }
0485
0486
0487
0488
0489
0490
0491
0492 inline const_reverse_iterator crend() const BOOST_NOEXCEPT
0493 { return const_reverse_iterator(this->begin()); }
0494
0495
0496
0497
0498
0499
0500
0501
0502
0503 inline static list_impl &container_from_end_iterator(iterator end_iterator) BOOST_NOEXCEPT
0504 { return list_impl::priv_container_from_end_iterator(end_iterator); }
0505
0506
0507
0508
0509
0510
0511
0512
0513
0514 inline static const list_impl &container_from_end_iterator(const_iterator end_iterator) BOOST_NOEXCEPT
0515 { return list_impl::priv_container_from_end_iterator(end_iterator); }
0516
0517
0518
0519
0520
0521
0522
0523
0524
0525 inline size_type size() const BOOST_NOEXCEPT
0526 {
0527 BOOST_IF_CONSTEXPR(constant_time_size)
0528 return this->priv_size_traits().get_size();
0529 else
0530 return node_algorithms::count(this->get_root_node()) - 1;
0531 }
0532
0533
0534
0535
0536
0537
0538
0539
0540 inline bool empty() const BOOST_NOEXCEPT
0541 { return node_algorithms::unique(this->get_root_node()); }
0542
0543
0544
0545
0546
0547
0548
0549
0550 void swap(list_impl& other) BOOST_NOEXCEPT
0551 {
0552 node_algorithms::swap_nodes(this->get_root_node(), other.get_root_node());
0553 this->priv_size_traits().swap(other.priv_size_traits());
0554 }
0555
0556
0557
0558
0559
0560
0561
0562
0563
0564
0565 inline void shift_backwards(size_type n = 1) BOOST_NOEXCEPT
0566 { node_algorithms::move_forward(this->get_root_node(), n); }
0567
0568
0569
0570
0571
0572
0573
0574
0575
0576
0577 inline void shift_forward(size_type n = 1) BOOST_NOEXCEPT
0578 { node_algorithms::move_backwards(this->get_root_node(), n); }
0579
0580
0581
0582
0583
0584
0585
0586
0587
0588
0589
0590
0591
0592 inline iterator erase(const_iterator i) BOOST_NOEXCEPT
0593 { return this->erase_and_dispose(i, detail::null_disposer()); }
0594
0595
0596
0597
0598
0599
0600
0601
0602
0603
0604
0605
0606
0607
0608
0609
0610 inline iterator erase(const_iterator b, const_iterator e) BOOST_NOEXCEPT
0611 {
0612 BOOST_IF_CONSTEXPR(safemode_or_autounlink || constant_time_size){
0613 return this->erase_and_dispose(b, e, detail::null_disposer());
0614 }
0615 else{
0616 node_algorithms::unlink(b.pointed_node(), e.pointed_node());
0617 return e.unconst();
0618 }
0619 }
0620
0621
0622
0623
0624
0625
0626
0627
0628
0629
0630
0631
0632
0633
0634
0635
0636
0637 iterator erase(const_iterator b, const_iterator e, size_type n) BOOST_NOEXCEPT
0638 {
0639 BOOST_INTRUSIVE_INVARIANT_ASSERT(node_algorithms::distance(b.pointed_node(), e.pointed_node()) == n);
0640 (void)n;
0641 BOOST_IF_CONSTEXPR(safemode_or_autounlink){
0642 return this->erase_and_dispose(b, e, detail::null_disposer());
0643 }
0644 else{
0645 BOOST_IF_CONSTEXPR(constant_time_size){
0646 this->priv_size_traits().decrease(n);
0647 }
0648 node_algorithms::unlink(b.pointed_node(), e.pointed_node());
0649 return e.unconst();
0650 }
0651 }
0652
0653
0654
0655
0656
0657
0658
0659
0660
0661
0662
0663
0664
0665
0666
0667 template <class Disposer>
0668 iterator erase_and_dispose(const_iterator i, Disposer disposer) BOOST_NOEXCEPT
0669 {
0670 node_ptr to_erase(i.pointed_node());
0671 ++i;
0672 node_algorithms::unlink(to_erase);
0673 this->priv_size_traits().decrement();
0674 BOOST_IF_CONSTEXPR(safemode_or_autounlink)
0675 node_algorithms::init(to_erase);
0676 disposer(this->priv_value_traits().to_value_ptr(to_erase));
0677 return i.unconst();
0678 }
0679
0680 #if !defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED)
0681 template<class Disposer>
0682 iterator erase_and_dispose(iterator i, Disposer disposer) BOOST_NOEXCEPT
0683 { return this->erase_and_dispose(const_iterator(i), disposer); }
0684 #endif
0685
0686
0687
0688
0689
0690
0691
0692
0693
0694
0695
0696
0697
0698
0699
0700 template <class Disposer>
0701 iterator erase_and_dispose(const_iterator b, const_iterator e, Disposer disposer) BOOST_NOEXCEPT
0702 {
0703 node_ptr bp(b.pointed_node()), ep(e.pointed_node());
0704 node_algorithms::unlink(bp, ep);
0705 while(bp != ep){
0706 node_ptr to_erase(bp);
0707 bp = node_traits::get_next(bp);
0708 BOOST_IF_CONSTEXPR(safemode_or_autounlink)
0709 node_algorithms::init(to_erase);
0710 disposer(priv_value_traits().to_value_ptr(to_erase));
0711 this->priv_size_traits().decrement();
0712 }
0713 return e.unconst();
0714 }
0715
0716
0717
0718
0719
0720
0721
0722
0723
0724
0725 void clear() BOOST_NOEXCEPT
0726 {
0727 BOOST_IF_CONSTEXPR(safemode_or_autounlink){
0728 this->clear_and_dispose(detail::null_disposer());
0729 }
0730 else{
0731 node_algorithms::init_header(this->get_root_node());
0732 this->priv_size_traits().set_size(size_type(0));
0733 }
0734 }
0735
0736
0737
0738
0739
0740
0741
0742
0743
0744
0745
0746
0747 template <class Disposer>
0748 void clear_and_dispose(Disposer disposer) BOOST_NOEXCEPT
0749 {
0750 const_iterator it(this->begin()), itend(this->end());
0751 while(it != itend){
0752 node_ptr to_erase(it.pointed_node());
0753 ++it;
0754 BOOST_IF_CONSTEXPR(safemode_or_autounlink)
0755 node_algorithms::init(to_erase);
0756 disposer(priv_value_traits().to_value_ptr(to_erase));
0757 }
0758 node_algorithms::init_header(this->get_root_node());
0759 this->priv_size_traits().set_size(0);
0760 }
0761
0762
0763
0764
0765
0766
0767
0768
0769
0770
0771
0772
0773
0774
0775
0776 template <class Cloner, class Disposer>
0777 void clone_from(const list_impl &src, Cloner cloner, Disposer disposer)
0778 {
0779 this->clear_and_dispose(disposer);
0780 detail::exception_disposer<list_impl, Disposer>
0781 rollback(*this, disposer);
0782 const_iterator b(src.begin()), e(src.end());
0783 for(; b != e; ++b){
0784 this->push_back(*cloner(*b));
0785 }
0786 rollback.release();
0787 }
0788
0789
0790
0791
0792
0793
0794
0795
0796
0797
0798
0799
0800
0801
0802
0803 template <class Cloner, class Disposer>
0804 void clone_from(BOOST_RV_REF(list_impl) src, Cloner cloner, Disposer disposer)
0805 {
0806 this->clear_and_dispose(disposer);
0807 detail::exception_disposer<list_impl, Disposer>
0808 rollback(*this, disposer);
0809 iterator b(src.begin()), e(src.end());
0810 for(; b != e; ++b){
0811 this->push_back(*cloner(*b));
0812 }
0813 rollback.release();
0814 }
0815
0816
0817
0818
0819
0820
0821
0822
0823
0824
0825
0826
0827 iterator insert(const_iterator p, reference value) BOOST_NOEXCEPT
0828 {
0829 node_ptr to_insert = this->priv_value_traits().to_node_ptr(value);
0830 BOOST_INTRUSIVE_SAFE_HOOK_DEFAULT_ASSERT(!safemode_or_autounlink || node_algorithms::inited(to_insert));
0831 node_algorithms::link_before(p.pointed_node(), to_insert);
0832 this->priv_size_traits().increment();
0833 return iterator(to_insert, this->priv_value_traits_ptr());
0834 }
0835
0836
0837
0838
0839
0840
0841
0842
0843
0844
0845
0846
0847 template<class Iterator>
0848 void insert(const_iterator p, Iterator b, Iterator e) BOOST_NOEXCEPT
0849 {
0850 for (; b != e; ++b)
0851 this->insert(p, *b);
0852 }
0853
0854
0855
0856
0857
0858
0859
0860
0861
0862
0863
0864
0865
0866
0867
0868
0869 template<class Iterator>
0870 void assign(Iterator b, Iterator e) BOOST_NOEXCEPT
0871 {
0872 this->clear();
0873 this->insert(this->cend(), b, e);
0874 }
0875
0876
0877
0878
0879
0880
0881
0882
0883
0884
0885
0886
0887
0888
0889
0890
0891
0892 template<class Iterator, class Disposer>
0893 void dispose_and_assign(Disposer disposer, Iterator b, Iterator e) BOOST_NOEXCEPT
0894 {
0895 this->clear_and_dispose(disposer);
0896 this->insert(this->cend(), b, e);
0897 }
0898
0899
0900
0901
0902
0903
0904
0905
0906
0907
0908
0909
0910 void splice(const_iterator p, list_impl& x) BOOST_NOEXCEPT
0911 {
0912 if(!x.empty()){
0913 node_algorithms::transfer
0914 (p.pointed_node(), x.begin().pointed_node(), x.end().pointed_node());
0915 size_traits &thist = this->priv_size_traits();
0916 size_traits &xt = x.priv_size_traits();
0917 thist.increase(xt.get_size());
0918 xt.set_size(size_type(0));
0919 }
0920 }
0921
0922
0923
0924
0925
0926
0927
0928
0929
0930
0931
0932
0933
0934
0935 void splice(const_iterator p, list_impl&x, const_iterator new_ele) BOOST_NOEXCEPT
0936 {
0937 node_algorithms::transfer(p.pointed_node(), new_ele.pointed_node());
0938 x.priv_size_traits().decrement();
0939 this->priv_size_traits().increment();
0940 }
0941
0942
0943
0944
0945
0946
0947
0948
0949
0950
0951
0952
0953
0954
0955 void splice(const_iterator p, list_impl&x, const_iterator f, const_iterator e) BOOST_NOEXCEPT
0956 {
0957 BOOST_IF_CONSTEXPR(constant_time_size)
0958 this->splice(p, x, f, e, node_algorithms::distance(f.pointed_node(), e.pointed_node()));
0959 else
0960 this->splice(p, x, f, e, 1);
0961 }
0962
0963
0964
0965
0966
0967
0968
0969
0970
0971
0972
0973
0974
0975
0976 void splice(const_iterator p, list_impl&x, const_iterator f, const_iterator e, size_type n) BOOST_NOEXCEPT
0977 {
0978 if(n){
0979 BOOST_IF_CONSTEXPR(constant_time_size){
0980 BOOST_INTRUSIVE_INVARIANT_ASSERT(n == node_algorithms::distance(f.pointed_node(), e.pointed_node()));
0981 node_algorithms::transfer(p.pointed_node(), f.pointed_node(), e.pointed_node());
0982 size_traits &thist = this->priv_size_traits();
0983 size_traits &xt = x.priv_size_traits();
0984 thist.increase(n);
0985 xt.decrease(n);
0986 }
0987 else{
0988 node_algorithms::transfer(p.pointed_node(), f.pointed_node(), e.pointed_node());
0989 }
0990 }
0991 }
0992
0993
0994
0995
0996
0997
0998
0999
1000
1001
1002
1003
1004 void sort()
1005 { this->sort(value_less<value_type>()); }
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022 template<class Predicate>
1023 void sort(Predicate p)
1024 {
1025 if(node_traits::get_next(this->get_root_node())
1026 != node_traits::get_previous(this->get_root_node())){
1027 list_impl carry(this->priv_value_traits());
1028 detail::array_initializer<list_impl, 64> counter(this->priv_value_traits());
1029 int fill = 0;
1030 while(!this->empty()){
1031 carry.splice(carry.cbegin(), *this, this->cbegin());
1032 int i = 0;
1033 while(i < fill && !counter[i].empty()) {
1034 counter[i].merge(carry, p);
1035 carry.swap(counter[i++]);
1036 }
1037 carry.swap(counter[i]);
1038 if(i == fill)
1039 ++fill;
1040 }
1041 for (int i = 1; i < fill; ++i)
1042 counter[i].merge(counter[i-1], p);
1043 this->swap(counter[fill-1]);
1044 }
1045 }
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058 void merge(list_impl& x)
1059 { this->merge(x, value_less<value_type>()); }
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075 template<class Predicate>
1076 void merge(list_impl& x, Predicate p)
1077 {
1078 const_iterator e(this->cend()), ex(x.cend());
1079 const_iterator b(this->cbegin());
1080 while(!x.empty()){
1081 const_iterator ix(x.cbegin());
1082 while (b != e && !p(*ix, *b)){
1083 ++b;
1084 }
1085 if(b == e){
1086
1087 this->splice(e, x);
1088 break;
1089 }
1090 else{
1091 size_type n(0);
1092 do{
1093 ++ix; ++n;
1094 } while(ix != ex && p(*ix, *b));
1095 this->splice(b, x, x.begin(), ix, n);
1096 }
1097 }
1098 }
1099
1100
1101
1102
1103
1104
1105
1106
1107 void reverse() BOOST_NOEXCEPT
1108 { node_algorithms::reverse(this->get_root_node()); }
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119 void remove(const_reference value) BOOST_NOEXCEPT
1120 { this->remove_if(detail::equal_to_value<const_reference>(value)); }
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133 template<class Disposer>
1134 void remove_and_dispose(const_reference value, Disposer disposer) BOOST_NOEXCEPT
1135 { this->remove_and_dispose_if(detail::equal_to_value<const_reference>(value), disposer); }
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146 template<class Pred>
1147 void remove_if(Pred pred)
1148 {
1149 const node_ptr root_node = this->get_root_node();
1150 typename node_algorithms::stable_partition_info info;
1151 node_algorithms::stable_partition
1152 (node_traits::get_next(root_node), root_node, detail::key_nodeptr_comp<Pred, value_traits>(pred, &this->priv_value_traits()), info);
1153
1154
1155 this->erase( const_iterator(node_traits::get_next(root_node), this->priv_value_traits_ptr())
1156 , const_iterator(info.beg_2st_partition, this->priv_value_traits_ptr())
1157 , info.num_1st_partition);
1158 }
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172 template<class Pred, class Disposer>
1173 void remove_and_dispose_if(Pred pred, Disposer disposer)
1174 {
1175 const node_ptr root_node = this->get_root_node();
1176 typename node_algorithms::stable_partition_info info;
1177 node_algorithms::stable_partition
1178 (node_traits::get_next(root_node), root_node, detail::key_nodeptr_comp<Pred, value_traits>(pred, &this->priv_value_traits()), info);
1179
1180
1181 this->erase_and_dispose( const_iterator(node_traits::get_next(root_node), this->priv_value_traits_ptr())
1182 , const_iterator(info.beg_2st_partition, this->priv_value_traits_ptr())
1183 , disposer);
1184 }
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195 void unique()
1196 { this->unique_and_dispose(value_equal<value_type>(), detail::null_disposer()); }
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208 template<class BinaryPredicate>
1209 void unique(BinaryPredicate pred)
1210 { this->unique_and_dispose(pred, detail::null_disposer()); }
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224 template<class Disposer>
1225 void unique_and_dispose(Disposer disposer)
1226 { this->unique_and_dispose(value_equal<value_type>(), disposer); }
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240 template<class BinaryPredicate, class Disposer>
1241 void unique_and_dispose(BinaryPredicate pred, Disposer disposer)
1242 {
1243 const_iterator itend(this->cend());
1244 const_iterator cur(this->cbegin());
1245
1246 if(cur != itend){
1247 const_iterator after(cur);
1248 ++after;
1249 while(after != itend){
1250 if(pred(*cur, *after)){
1251 after = this->erase_and_dispose(after, disposer);
1252 }
1253 else{
1254 cur = after;
1255 ++after;
1256 }
1257 }
1258 }
1259 }
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272 static iterator s_iterator_to(reference value) BOOST_NOEXCEPT
1273 {
1274 BOOST_INTRUSIVE_STATIC_ASSERT((!stateful_value_traits));
1275 BOOST_INTRUSIVE_INVARIANT_ASSERT(!node_algorithms::inited(value_traits::to_node_ptr(value)));
1276 return iterator(value_traits::to_node_ptr(value), const_value_traits_ptr());
1277 }
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290 static const_iterator s_iterator_to(const_reference value) BOOST_NOEXCEPT
1291 {
1292 BOOST_INTRUSIVE_STATIC_ASSERT((!stateful_value_traits));
1293 reference r =*detail::uncast(pointer_traits<const_pointer>::pointer_to(value));
1294 BOOST_INTRUSIVE_INVARIANT_ASSERT(!node_algorithms::inited(value_traits::to_node_ptr(r)));
1295 return const_iterator(value_traits::to_node_ptr(r), const_value_traits_ptr());
1296 }
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307 iterator iterator_to(reference value) BOOST_NOEXCEPT
1308 {
1309 BOOST_INTRUSIVE_INVARIANT_ASSERT(!node_algorithms::inited(this->priv_value_traits().to_node_ptr(value)));
1310 return iterator(this->priv_value_traits().to_node_ptr(value), this->priv_value_traits_ptr());
1311 }
1312
1313
1314
1315
1316
1317
1318
1319
1320
1321
1322 const_iterator iterator_to(const_reference value) const BOOST_NOEXCEPT
1323 {
1324 reference r = *detail::uncast(pointer_traits<const_pointer>::pointer_to(value));
1325 BOOST_INTRUSIVE_INVARIANT_ASSERT(!node_algorithms::inited(this->priv_value_traits().to_node_ptr(r)));
1326 return const_iterator(this->priv_value_traits().to_node_ptr(r), this->priv_value_traits_ptr());
1327 }
1328
1329
1330
1331
1332
1333
1334
1335 void check() const
1336 {
1337 const_node_ptr header_ptr = get_root_node();
1338
1339 BOOST_INTRUSIVE_INVARIANT_ASSERT(node_traits::get_next(header_ptr));
1340 BOOST_INTRUSIVE_INVARIANT_ASSERT(node_traits::get_previous(header_ptr));
1341
1342 BOOST_INTRUSIVE_INVARIANT_ASSERT((node_traits::get_next(header_ptr) == header_ptr)
1343 == (node_traits::get_previous(header_ptr) == header_ptr));
1344 if (node_traits::get_next(header_ptr) == header_ptr)
1345 {
1346 BOOST_IF_CONSTEXPR(constant_time_size)
1347 BOOST_INTRUSIVE_INVARIANT_ASSERT(this->priv_size_traits().get_size() == 0);
1348 return;
1349 }
1350 size_t node_count = 0; (void)node_count;
1351 const_node_ptr p = header_ptr;
1352 while (true)
1353 {
1354 const_node_ptr next_p = node_traits::get_next(p);
1355 BOOST_INTRUSIVE_INVARIANT_ASSERT(next_p);
1356 BOOST_INTRUSIVE_INVARIANT_ASSERT(node_traits::get_previous(next_p) == p);
1357 p = next_p;
1358 if (p == header_ptr) break;
1359 ++node_count;
1360 }
1361 BOOST_IF_CONSTEXPR(constant_time_size)
1362 BOOST_INTRUSIVE_INVARIANT_ASSERT(this->priv_size_traits().get_size() == node_count);
1363 }
1364
1365 friend bool operator==(const list_impl &x, const list_impl &y)
1366 {
1367 if(constant_time_size && x.size() != y.size()){
1368 return false;
1369 }
1370 return ::boost::intrusive::algo_equal(x.cbegin(), x.cend(), y.cbegin(), y.cend());
1371 }
1372
1373 inline friend bool operator!=(const list_impl &x, const list_impl &y)
1374 { return !(x == y); }
1375
1376 inline friend bool operator<(const list_impl &x, const list_impl &y)
1377 { return ::boost::intrusive::algo_lexicographical_compare(x.begin(), x.end(), y.begin(), y.end()); }
1378
1379 inline friend bool operator>(const list_impl &x, const list_impl &y)
1380 { return y < x; }
1381
1382 inline friend bool operator<=(const list_impl &x, const list_impl &y)
1383 { return !(y < x); }
1384
1385 inline friend bool operator>=(const list_impl &x, const list_impl &y)
1386 { return !(x < y); }
1387
1388 inline friend void swap(list_impl &x, list_impl &y) BOOST_NOEXCEPT
1389 { x.swap(y); }
1390
1391
1392
1393 private:
1394 static list_impl &priv_container_from_end_iterator(const const_iterator &end_iterator) BOOST_NOEXCEPT
1395 {
1396 BOOST_INTRUSIVE_STATIC_ASSERT((has_container_from_iterator));
1397 node_ptr p = end_iterator.pointed_node();
1398 header_holder_type* h = header_holder_type::get_holder(p);
1399 root_plus_size* r = detail::parent_from_member
1400 < root_plus_size, header_holder_type>(h, &root_plus_size::m_header);
1401 data_t *d = detail::parent_from_member<data_t, root_plus_size>
1402 ( r, &data_t::root_plus_size_);
1403 list_impl *s = detail::parent_from_member<list_impl, data_t>(d, &list_impl::data_);
1404 return *s;
1405 }
1406
1407 };
1408
1409
1410
1411
1412 #if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) || defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES)
1413 template<class T, class ...Options>
1414 #else
1415 template<class T, class O1 = void, class O2 = void, class O3 = void, class O4 = void>
1416 #endif
1417 struct make_list
1418 {
1419
1420 typedef typename pack_options
1421 < list_defaults,
1422 #if !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES)
1423 O1, O2, O3, O4
1424 #else
1425 Options...
1426 #endif
1427 >::type packed_options;
1428
1429 typedef typename detail::get_value_traits
1430 <T, typename packed_options::proto_value_traits>::type value_traits;
1431 typedef list_impl
1432 <
1433 value_traits,
1434 typename packed_options::size_type,
1435 packed_options::constant_time_size,
1436 typename packed_options::header_holder_type
1437 > implementation_defined;
1438
1439 typedef implementation_defined type;
1440 };
1441
1442
1443 #ifndef BOOST_INTRUSIVE_DOXYGEN_INVOKED
1444
1445 #if !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES)
1446 template<class T, class O1, class O2, class O3, class O4>
1447 #else
1448 template<class T, class ...Options>
1449 #endif
1450 class list
1451 : public make_list<T,
1452 #if !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES)
1453 O1, O2, O3, O4
1454 #else
1455 Options...
1456 #endif
1457 >::type
1458 {
1459 typedef typename make_list
1460 <T,
1461 #if !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES)
1462 O1, O2, O3, O4
1463 #else
1464 Options...
1465 #endif
1466 >::type Base;
1467
1468 BOOST_INTRUSIVE_STATIC_ASSERT((detail::is_same<typename Base::value_traits::value_type, T>::value));
1469 BOOST_MOVABLE_BUT_NOT_COPYABLE(list)
1470
1471 public:
1472 typedef typename Base::value_traits value_traits;
1473 typedef typename Base::iterator iterator;
1474 typedef typename Base::const_iterator const_iterator;
1475
1476 inline list()
1477 : Base()
1478 {}
1479
1480 inline explicit list(const value_traits &v_traits)
1481 : Base(v_traits)
1482 {}
1483
1484 template<class Iterator>
1485 inline list(Iterator b, Iterator e, const value_traits &v_traits = value_traits())
1486 : Base(b, e, v_traits)
1487 {}
1488
1489 inline list(BOOST_RV_REF(list) x)
1490 : Base(BOOST_MOVE_BASE(Base, x))
1491 {}
1492
1493 inline list& operator=(BOOST_RV_REF(list) x)
1494 { return static_cast<list &>(this->Base::operator=(BOOST_MOVE_BASE(Base, x))); }
1495
1496 template <class Cloner, class Disposer>
1497 inline void clone_from(const list &src, Cloner cloner, Disposer disposer)
1498 { Base::clone_from(src, cloner, disposer); }
1499
1500 template <class Cloner, class Disposer>
1501 inline void clone_from(BOOST_RV_REF(list) src, Cloner cloner, Disposer disposer)
1502 { Base::clone_from(BOOST_MOVE_BASE(Base, src), cloner, disposer); }
1503
1504 inline static list &container_from_end_iterator(iterator end_iterator) BOOST_NOEXCEPT
1505 { return static_cast<list &>(Base::container_from_end_iterator(end_iterator)); }
1506
1507 inline static const list &container_from_end_iterator(const_iterator end_iterator) BOOST_NOEXCEPT
1508 { return static_cast<const list &>(Base::container_from_end_iterator(end_iterator)); }
1509 };
1510
1511 #endif
1512
1513 }
1514 }
1515
1516 #include <boost/intrusive/detail/config_end.hpp>
1517
1518 #endif