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