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