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