File indexing completed on 2025-07-05 08:28:51
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011 #ifndef BOOST_CONTAINER_CONTAINER_VECTOR_HPP
0012 #define BOOST_CONTAINER_CONTAINER_VECTOR_HPP
0013
0014 #ifndef BOOST_CONFIG_HPP
0015 # include <boost/config.hpp>
0016 #endif
0017
0018 #if defined(BOOST_HAS_PRAGMA_ONCE)
0019 # pragma once
0020 #endif
0021
0022 #include <boost/container/detail/config_begin.hpp>
0023 #include <boost/container/detail/workaround.hpp>
0024
0025
0026 #include <boost/container/container_fwd.hpp>
0027 #include <boost/container/allocator_traits.hpp>
0028 #include <boost/container/new_allocator.hpp> //new_allocator
0029 #include <boost/container/throw_exception.hpp>
0030 #include <boost/container/options.hpp>
0031
0032 #include <boost/container/detail/advanced_insert_int.hpp>
0033 #include <boost/container/detail/algorithm.hpp> //equal()
0034 #include <boost/container/detail/alloc_helpers.hpp>
0035 #include <boost/container/detail/allocation_type.hpp>
0036 #include <boost/container/detail/copy_move_algo.hpp>
0037 #include <boost/container/detail/destroyers.hpp>
0038 #include <boost/container/detail/iterator.hpp>
0039 #include <boost/container/detail/iterators.hpp>
0040 #include <boost/move/detail/iterator_to_raw_pointer.hpp>
0041 #include <boost/container/detail/mpl.hpp>
0042 #include <boost/container/detail/next_capacity.hpp>
0043 #include <boost/container/detail/value_functors.hpp>
0044 #include <boost/move/detail/to_raw_pointer.hpp>
0045 #include <boost/container/detail/type_traits.hpp>
0046 #include <boost/container/detail/version_type.hpp>
0047
0048 #include <boost/intrusive/pointer_traits.hpp>
0049
0050 #include <boost/move/adl_move_swap.hpp>
0051 #include <boost/move/iterator.hpp>
0052 #include <boost/move/traits.hpp>
0053 #include <boost/move/utility_core.hpp>
0054 #include <boost/move/detail/launder.hpp>
0055
0056 #if defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
0057 #include <boost/move/detail/fwd_macros.hpp>
0058 #endif
0059 #include <boost/move/detail/move_helpers.hpp>
0060
0061 #include <boost/move/algo/adaptive_merge.hpp>
0062 #include <boost/move/algo/unique.hpp>
0063 #include <boost/move/algo/predicate.hpp>
0064 #include <boost/move/algo/detail/set_difference.hpp>
0065
0066 #include <boost/assert.hpp>
0067 #include <boost/cstdint.hpp>
0068
0069
0070 #if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
0071 #include <initializer_list> //for std::initializer_list
0072 #endif
0073
0074 namespace boost {
0075 namespace container {
0076
0077 #ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
0078
0079
0080 template <class Pointer, bool IsConst>
0081 class vec_iterator
0082 {
0083 public:
0084 typedef std::random_access_iterator_tag iterator_category;
0085 #ifdef BOOST_MOVE_CONTIGUOUS_ITERATOR_TAG
0086 typedef std::contiguous_iterator_tag iterator_concept;
0087 #endif
0088 typedef typename boost::intrusive::pointer_traits<Pointer>::element_type value_type;
0089
0090
0091
0092
0093
0094 #ifndef BOOST_GNU_STDLIB
0095
0096 typedef typename boost::intrusive::pointer_traits<Pointer>::element_type element_type;
0097 #endif
0098 typedef typename boost::intrusive::pointer_traits<Pointer>::difference_type difference_type;
0099 typedef typename boost::intrusive::pointer_traits<Pointer>::size_type size_type;
0100 typedef typename dtl::if_c
0101 < IsConst
0102 , typename boost::intrusive::pointer_traits<Pointer>::template
0103 rebind_pointer<const value_type>::type
0104 , Pointer
0105 >::type pointer;
0106 typedef typename boost::intrusive::pointer_traits<pointer> ptr_traits;
0107 typedef typename ptr_traits::reference reference;
0108
0109 #ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
0110 private:
0111 Pointer m_ptr;
0112
0113 class nat
0114 {
0115 public:
0116 Pointer get_ptr() const
0117 { return Pointer(); }
0118 };
0119 typedef typename dtl::if_c< IsConst
0120 , vec_iterator<Pointer, false>
0121 , nat>::type nonconst_iterator;
0122
0123 public:
0124 inline
0125 const Pointer &get_ptr() const BOOST_NOEXCEPT_OR_NOTHROW
0126 { return m_ptr; }
0127
0128 inline
0129 Pointer &get_ptr() BOOST_NOEXCEPT_OR_NOTHROW
0130 { return m_ptr; }
0131
0132 inline explicit vec_iterator(Pointer ptr) BOOST_NOEXCEPT_OR_NOTHROW
0133 : m_ptr(ptr)
0134 {}
0135 #endif
0136
0137 public:
0138
0139
0140 inline vec_iterator() BOOST_NOEXCEPT_OR_NOTHROW
0141 : m_ptr()
0142 {}
0143
0144 inline vec_iterator(const vec_iterator& other) BOOST_NOEXCEPT_OR_NOTHROW
0145 : m_ptr(other.get_ptr())
0146 {}
0147
0148 inline vec_iterator(const nonconst_iterator &other) BOOST_NOEXCEPT_OR_NOTHROW
0149 : m_ptr(other.get_ptr())
0150 {}
0151
0152 inline vec_iterator & operator=(const vec_iterator& other) BOOST_NOEXCEPT_OR_NOTHROW
0153 { m_ptr = other.get_ptr(); return *this; }
0154
0155
0156 BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline
0157 reference operator*() const BOOST_NOEXCEPT_OR_NOTHROW
0158 { BOOST_ASSERT(!!m_ptr); return *m_ptr; }
0159
0160 BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline
0161 pointer operator->() const BOOST_NOEXCEPT_OR_NOTHROW
0162 { return m_ptr; }
0163
0164 BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline
0165 reference operator[](difference_type off) const BOOST_NOEXCEPT_OR_NOTHROW
0166 { BOOST_ASSERT(!!m_ptr); return m_ptr[off]; }
0167
0168
0169 inline vec_iterator& operator++() BOOST_NOEXCEPT_OR_NOTHROW
0170 { BOOST_ASSERT(!!m_ptr); ++m_ptr; return *this; }
0171
0172 inline vec_iterator operator++(int) BOOST_NOEXCEPT_OR_NOTHROW
0173 { BOOST_ASSERT(!!m_ptr); return vec_iterator(m_ptr++); }
0174
0175 inline vec_iterator& operator--() BOOST_NOEXCEPT_OR_NOTHROW
0176 { BOOST_ASSERT(!!m_ptr); --m_ptr; return *this; }
0177
0178 inline vec_iterator operator--(int) BOOST_NOEXCEPT_OR_NOTHROW
0179 { BOOST_ASSERT(!!m_ptr); return vec_iterator(m_ptr--); }
0180
0181
0182 inline vec_iterator& operator+=(difference_type off) BOOST_NOEXCEPT_OR_NOTHROW
0183 { BOOST_ASSERT(m_ptr || !off); m_ptr += off; return *this; }
0184
0185 inline vec_iterator& operator-=(difference_type off) BOOST_NOEXCEPT_OR_NOTHROW
0186 { BOOST_ASSERT(m_ptr || !off); m_ptr -= off; return *this; }
0187
0188 BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline
0189 friend vec_iterator operator+(const vec_iterator &x, difference_type off) BOOST_NOEXCEPT_OR_NOTHROW
0190 { BOOST_ASSERT(x.m_ptr || !off); return vec_iterator(x.m_ptr+off); }
0191
0192 BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline
0193 friend vec_iterator operator+(difference_type off, vec_iterator right) BOOST_NOEXCEPT_OR_NOTHROW
0194 { BOOST_ASSERT(right.m_ptr || !off); right.m_ptr += off; return right; }
0195
0196 BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline
0197 friend vec_iterator operator-(vec_iterator left, difference_type off) BOOST_NOEXCEPT_OR_NOTHROW
0198 { BOOST_ASSERT(left.m_ptr || !off); left.m_ptr -= off; return left; }
0199
0200
0201 BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline
0202 friend difference_type operator-(const vec_iterator &left, const vec_iterator& right) BOOST_NOEXCEPT_OR_NOTHROW
0203 { return left.m_ptr - right.m_ptr; }
0204
0205
0206 BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline
0207 friend bool operator== (const vec_iterator& l, const vec_iterator& r) BOOST_NOEXCEPT_OR_NOTHROW
0208 { return l.m_ptr == r.m_ptr; }
0209
0210 BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline
0211 friend bool operator!= (const vec_iterator& l, const vec_iterator& r) BOOST_NOEXCEPT_OR_NOTHROW
0212 { return l.m_ptr != r.m_ptr; }
0213
0214 BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline
0215 friend bool operator< (const vec_iterator& l, const vec_iterator& r) BOOST_NOEXCEPT_OR_NOTHROW
0216 { return l.m_ptr < r.m_ptr; }
0217
0218 BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline
0219 friend bool operator<= (const vec_iterator& l, const vec_iterator& r) BOOST_NOEXCEPT_OR_NOTHROW
0220 { return l.m_ptr <= r.m_ptr; }
0221
0222 BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline
0223 friend bool operator> (const vec_iterator& l, const vec_iterator& r) BOOST_NOEXCEPT_OR_NOTHROW
0224 { return l.m_ptr > r.m_ptr; }
0225
0226 BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline
0227 friend bool operator>= (const vec_iterator& l, const vec_iterator& r) BOOST_NOEXCEPT_OR_NOTHROW
0228 { return l.m_ptr >= r.m_ptr; }
0229 };
0230
0231 template<class BiDirPosConstIt, class BiDirValueIt>
0232 struct vector_insert_ordered_cursor
0233 {
0234 typedef typename iterator_traits<BiDirPosConstIt>::value_type size_type;
0235 typedef typename iterator_traits<BiDirValueIt>::reference reference;
0236
0237 inline vector_insert_ordered_cursor(BiDirPosConstIt posit, BiDirValueIt valueit)
0238 : last_position_it(posit), last_value_it(valueit)
0239 {}
0240
0241 void operator --()
0242 {
0243 --last_value_it;
0244 --last_position_it;
0245 while(this->get_pos() == size_type(-1)){
0246 --last_value_it;
0247 --last_position_it;
0248 }
0249 }
0250
0251 inline size_type get_pos() const
0252 { return *last_position_it; }
0253
0254 inline reference get_val()
0255 { return *last_value_it; }
0256
0257 BiDirPosConstIt last_position_it;
0258 BiDirValueIt last_value_it;
0259 };
0260
0261 template<class Pointer, bool IsConst>
0262 inline const Pointer &vector_iterator_get_ptr(const vec_iterator<Pointer, IsConst> &it) BOOST_NOEXCEPT_OR_NOTHROW
0263 { return it.get_ptr(); }
0264
0265 template<class Pointer, bool IsConst>
0266 inline Pointer &get_ptr(vec_iterator<Pointer, IsConst> &it) BOOST_NOEXCEPT_OR_NOTHROW
0267 { return it.get_ptr(); }
0268
0269 struct initial_capacity_t {};
0270
0271 struct vector_uninitialized_size_t {};
0272 BOOST_CONTAINER_CONSTANT_VAR vector_uninitialized_size_t vector_uninitialized_size = vector_uninitialized_size_t();
0273
0274 struct maybe_initial_capacity_t {};
0275
0276 template <class T>
0277 struct vector_value_traits_base
0278 {
0279 BOOST_STATIC_CONSTEXPR bool trivial_dctr = dtl::is_trivially_destructible<T>::value;
0280 BOOST_STATIC_CONSTEXPR bool trivial_dctr_after_move = has_trivial_destructor_after_move<T>::value;
0281 };
0282
0283 template <class Allocator>
0284 struct vector_value_traits
0285 : public vector_value_traits_base<typename Allocator::value_type>
0286 {
0287 typedef vector_value_traits_base<typename Allocator::value_type> base_t;
0288
0289
0290 typedef typename dtl::if_c
0291 <base_t::trivial_dctr
0292 ,dtl::null_scoped_destructor_n<Allocator>
0293 ,dtl::scoped_destructor_n<Allocator>
0294 >::type ArrayDestructor;
0295
0296 typedef dtl::scoped_array_deallocator<Allocator> ArrayDeallocator;
0297 };
0298
0299
0300 template < class Allocator
0301 , class StoredSizeType
0302 , class AllocatorVersion = typename dtl::version<Allocator>::type
0303 >
0304 struct vector_alloc_holder
0305 : public Allocator
0306 {
0307 private:
0308 BOOST_MOVABLE_BUT_NOT_COPYABLE(vector_alloc_holder)
0309
0310 public:
0311 typedef Allocator allocator_type;
0312 typedef StoredSizeType stored_size_type;
0313 typedef boost::container::allocator_traits<allocator_type> allocator_traits_type;
0314 typedef typename allocator_traits_type::pointer pointer;
0315 typedef typename allocator_traits_type::size_type size_type;
0316 typedef typename allocator_traits_type::value_type value_type;
0317
0318
0319 private:
0320
0321 template<class SizeType>
0322 void do_initial_capacity(SizeType initial_capacity)
0323 {
0324 if (BOOST_UNLIKELY(initial_capacity > size_type(-1))) {
0325 boost::container::throw_length_error("get_next_capacity, allocator's max size reached");
0326 }
0327 else if (initial_capacity) {
0328 pointer reuse = pointer();
0329 size_type final_cap = static_cast<size_type>(initial_capacity);
0330 m_start = this->allocation_command(allocate_new, final_cap, final_cap, reuse);
0331 this->set_stored_capacity(final_cap);
0332 }
0333 }
0334
0335 template<class SizeType>
0336 void do_maybe_initial_capacity(pointer p, SizeType initial_capacity)
0337 {
0338 if (BOOST_UNLIKELY(initial_capacity > size_type(-1))) {
0339 boost::container::throw_length_error("get_next_capacity, allocator's max size reached");
0340 }
0341 else if (p) {
0342 m_start = p;
0343 }
0344 else {
0345 BOOST_ASSERT(initial_capacity > 0);
0346 pointer reuse = pointer();
0347 size_type final_cap = static_cast<size_type>(initial_capacity);
0348 m_start = this->allocation_command(allocate_new, final_cap, final_cap, reuse);
0349 this->set_stored_capacity(final_cap);
0350 }
0351 }
0352
0353 public:
0354
0355 template <bool PropagateAllocator>
0356 inline static bool is_propagable_from(const allocator_type &from_alloc, pointer p, const allocator_type &to_alloc)
0357 {
0358 (void)p; (void)to_alloc; (void)from_alloc;
0359 const bool all_storage_propagable = !allocator_traits_type::is_partially_propagable::value ||
0360 !allocator_traits_type::storage_is_unpropagable(from_alloc, p);
0361 return all_storage_propagable &&
0362 (PropagateAllocator || allocator_traits_type::is_always_equal::value || allocator_traits_type::equal(from_alloc, to_alloc));
0363 }
0364
0365 template <bool PropagateAllocator>
0366 inline static bool are_swap_propagable(const allocator_type &l_a, pointer l_p, const allocator_type &r_a, pointer r_p)
0367 {
0368 (void)l_p; (void)r_p; (void)l_a; (void)r_a;
0369 const bool all_storage_propagable = !allocator_traits_type::is_partially_propagable::value ||
0370 !(allocator_traits_type::storage_is_unpropagable(l_a, l_p) || allocator_traits_type::storage_is_unpropagable(r_a, r_p));
0371 return all_storage_propagable && (PropagateAllocator || allocator_traits_type::is_always_equal::value || allocator_traits_type::equal(l_a, r_a));
0372 }
0373
0374
0375 vector_alloc_holder()
0376 BOOST_NOEXCEPT_IF(dtl::is_nothrow_default_constructible<allocator_type>::value)
0377 : allocator_type(), m_start(), m_size(), m_capacity()
0378 {}
0379
0380
0381 template<class AllocConvertible>
0382 explicit vector_alloc_holder(BOOST_FWD_REF(AllocConvertible) a) BOOST_NOEXCEPT_OR_NOTHROW
0383 : allocator_type(boost::forward<AllocConvertible>(a)), m_start(), m_size(), m_capacity()
0384 {}
0385
0386
0387 template<class AllocConvertible, class SizeType>
0388 vector_alloc_holder(vector_uninitialized_size_t, BOOST_FWD_REF(AllocConvertible) a, SizeType initial_size)
0389 : allocator_type(boost::forward<AllocConvertible>(a))
0390 , m_start()
0391
0392 , m_size(static_cast<stored_size_type>(initial_size))
0393 , m_capacity()
0394 { this->do_initial_capacity(initial_size); }
0395
0396 template<class SizeType>
0397 vector_alloc_holder(vector_uninitialized_size_t, SizeType initial_size)
0398 : allocator_type()
0399 , m_start()
0400
0401 , m_size(static_cast<stored_size_type>(initial_size))
0402 , m_capacity()
0403 { this->do_initial_capacity(initial_size); }
0404
0405 vector_alloc_holder(initial_capacity_t, pointer p, size_type n)
0406 BOOST_NOEXCEPT_IF(dtl::is_nothrow_default_constructible<allocator_type>::value)
0407 : allocator_type()
0408 , m_start(p)
0409 , m_size()
0410
0411 , m_capacity(static_cast<stored_size_type>(n))
0412 {}
0413
0414 template<class AllocFwd>
0415 vector_alloc_holder(initial_capacity_t, pointer p, size_type n, BOOST_FWD_REF(AllocFwd) a)
0416 : allocator_type(::boost::forward<AllocFwd>(a))
0417 , m_start(p)
0418 , m_size()
0419 , m_capacity(n)
0420 {}
0421
0422 template<class AllocConvertible, class SizeType>
0423 vector_alloc_holder(maybe_initial_capacity_t, pointer p, SizeType initial_capacity, BOOST_FWD_REF(AllocConvertible) a)
0424 : allocator_type(boost::forward<AllocConvertible>(a))
0425
0426
0427 , m_size()
0428 , m_capacity(static_cast<stored_size_type>(initial_capacity))
0429 { this->do_maybe_initial_capacity(p, initial_capacity); }
0430
0431 template<class SizeType>
0432 vector_alloc_holder(maybe_initial_capacity_t, pointer p, SizeType initial_capacity)
0433 : allocator_type()
0434
0435
0436 , m_size()
0437 , m_capacity(static_cast<stored_size_type>(initial_capacity))
0438 { this->do_maybe_initial_capacity(p, initial_capacity); }
0439
0440 vector_alloc_holder(BOOST_RV_REF(vector_alloc_holder) holder) BOOST_NOEXCEPT_OR_NOTHROW
0441 : allocator_type(BOOST_MOVE_BASE(allocator_type, holder))
0442 , m_start(holder.m_start)
0443 , m_size(holder.m_size)
0444 , m_capacity(holder.m_capacity)
0445 {
0446 holder.m_start = pointer();
0447 holder.m_size = holder.m_capacity = 0;
0448 }
0449
0450 inline ~vector_alloc_holder() BOOST_NOEXCEPT_OR_NOTHROW
0451 {
0452 if(this->m_capacity){
0453 this->deallocate(this->m_start, this->m_capacity);
0454 }
0455 }
0456
0457 inline void set_stored_size(size_type s) BOOST_NOEXCEPT_OR_NOTHROW
0458 { this->m_size = static_cast<stored_size_type>(s); }
0459
0460 inline void dec_stored_size(size_type s) BOOST_NOEXCEPT_OR_NOTHROW
0461 { this->m_size = static_cast<stored_size_type>(this->m_size - s); }
0462
0463 inline void inc_stored_size(size_type s) BOOST_NOEXCEPT_OR_NOTHROW
0464 { this->m_size = static_cast<stored_size_type>(this->m_size + s); }
0465
0466 inline void set_stored_capacity(size_type c) BOOST_NOEXCEPT_OR_NOTHROW
0467 { this->m_capacity = static_cast<stored_size_type>(c); }
0468
0469 inline pointer allocation_command(boost::container::allocation_type command,
0470 size_type limit_size, size_type &prefer_in_recvd_out_size, pointer &reuse)
0471 {
0472 typedef typename dtl::version<allocator_type>::type alloc_version;
0473 return this->priv_allocation_command(alloc_version(), command, limit_size, prefer_in_recvd_out_size, reuse);
0474 }
0475
0476 inline pointer allocate(size_type n)
0477 {
0478 const size_type max_alloc = allocator_traits_type::max_size(this->alloc());
0479 const size_type max = max_alloc <= stored_size_type(-1) ? max_alloc : stored_size_type(-1);
0480 if (BOOST_UNLIKELY(max < n) )
0481 boost::container::throw_length_error("get_next_capacity, allocator's max size reached");
0482
0483 return allocator_traits_type::allocate(this->alloc(), n);
0484 }
0485
0486 inline void deallocate(const pointer &p, size_type n)
0487 {
0488 allocator_traits_type::deallocate(this->alloc(), p, n);
0489 }
0490
0491 bool try_expand_fwd(size_type at_least)
0492 {
0493
0494 const size_type new_cap = size_type(this->capacity() + at_least);
0495 size_type real_cap = new_cap;
0496 pointer reuse = this->start();
0497 bool const success = !!this->allocation_command(expand_fwd, new_cap, real_cap, reuse);
0498
0499 if(success){
0500 #ifdef BOOST_CONTAINER_VECTOR_ALLOC_STATS
0501 ++this->num_expand_fwd;
0502 #endif
0503 this->capacity(real_cap);
0504 }
0505 return success;
0506 }
0507
0508 template<class GrowthFactorType>
0509 size_type next_capacity(size_type additional_objects) const
0510 {
0511 BOOST_ASSERT(additional_objects > size_type(this->m_capacity - this->m_size));
0512 size_type max = allocator_traits_type::max_size(this->alloc());
0513 (clamp_by_stored_size_type<size_type>)(max, stored_size_type());
0514 const size_type remaining_cap = size_type(max - size_type(this->m_capacity));
0515 const size_type min_additional_cap = size_type(additional_objects - size_type(this->m_capacity - this->m_size));
0516
0517 if ( remaining_cap < min_additional_cap )
0518 boost::container::throw_length_error("get_next_capacity, allocator's max size reached");
0519
0520 return GrowthFactorType()( size_type(this->m_capacity), min_additional_cap, max);
0521 }
0522
0523 pointer m_start;
0524 stored_size_type m_size;
0525 stored_size_type m_capacity;
0526
0527 void swap_resources(vector_alloc_holder &x) BOOST_NOEXCEPT_OR_NOTHROW
0528 {
0529 boost::adl_move_swap(this->m_start, x.m_start);
0530 boost::adl_move_swap(this->m_size, x.m_size);
0531 boost::adl_move_swap(this->m_capacity, x.m_capacity);
0532 }
0533
0534 void steal_resources(vector_alloc_holder &x) BOOST_NOEXCEPT_OR_NOTHROW
0535 {
0536 this->m_start = x.m_start;
0537 this->m_size = x.m_size;
0538 this->m_capacity = x.m_capacity;
0539 x.m_start = pointer();
0540 x.m_size = x.m_capacity = 0;
0541 }
0542
0543 inline allocator_type &alloc() BOOST_NOEXCEPT_OR_NOTHROW
0544 { return *this; }
0545
0546 inline const allocator_type &alloc() const BOOST_NOEXCEPT_OR_NOTHROW
0547 { return *this; }
0548
0549 inline pointer start() const BOOST_NOEXCEPT_OR_NOTHROW
0550 { return m_start; }
0551 inline size_type capacity() const BOOST_NOEXCEPT_OR_NOTHROW
0552 { return m_capacity; }
0553 inline void start(const pointer &p) BOOST_NOEXCEPT_OR_NOTHROW
0554 { m_start = p; }
0555 inline void capacity(const size_type &c) BOOST_NOEXCEPT_OR_NOTHROW
0556 { BOOST_ASSERT( c <= stored_size_type(-1)); this->set_stored_capacity(c); }
0557
0558 static inline void on_capacity_overflow()
0559 { }
0560
0561 private:
0562 void priv_first_allocation(size_type cap)
0563 {
0564 if(cap){
0565 pointer reuse = pointer();
0566 m_start = this->allocation_command(allocate_new, cap, cap, reuse);
0567 m_capacity = cap;
0568 #ifdef BOOST_CONTAINER_VECTOR_ALLOC_STATS
0569 ++this->num_alloc;
0570 #endif
0571 }
0572 }
0573
0574 pointer priv_allocation_command(version_1, boost::container::allocation_type command,
0575 size_type limit_size,
0576 size_type &prefer_in_recvd_out_size,
0577 pointer &reuse)
0578 {
0579 (void)command;
0580 BOOST_ASSERT( (command & allocate_new));
0581 BOOST_ASSERT(!(command & nothrow_allocation));
0582
0583 if (BOOST_UNLIKELY(limit_size > stored_size_type(-1))){
0584 boost::container::throw_length_error("get_next_capacity, allocator's max size reached");
0585 }
0586 (clamp_by_stored_size_type<size_type>)(prefer_in_recvd_out_size, stored_size_type());
0587 pointer const p = this->allocate(prefer_in_recvd_out_size);
0588 reuse = pointer();
0589 return p;
0590 }
0591
0592 pointer priv_allocation_command(version_2, boost::container::allocation_type command,
0593 size_type limit_size,
0594 size_type &prefer_in_recvd_out_size,
0595 pointer &reuse)
0596 {
0597
0598 if (BOOST_UNLIKELY(limit_size > stored_size_type(-1))){
0599 boost::container::throw_length_error("get_next_capacity, allocator's max size reached");
0600 }
0601 (clamp_by_stored_size_type<size_type>)(prefer_in_recvd_out_size, stored_size_type());
0602
0603 pointer p = this->alloc().allocation_command(command, limit_size, prefer_in_recvd_out_size, reuse);
0604
0605 (clamp_by_stored_size_type<size_type>)(prefer_in_recvd_out_size, stored_size_type());
0606 return p;
0607 }
0608 };
0609
0610
0611 template <class Allocator, class StoredSizeType>
0612 struct vector_alloc_holder<Allocator, StoredSizeType, version_0>
0613 : public Allocator
0614 {
0615 private:
0616 BOOST_MOVABLE_BUT_NOT_COPYABLE(vector_alloc_holder)
0617
0618 public:
0619 typedef Allocator allocator_type;
0620 typedef boost::container::
0621 allocator_traits<allocator_type> allocator_traits_type;
0622 typedef typename allocator_traits_type::pointer pointer;
0623 typedef typename allocator_traits_type::size_type size_type;
0624 typedef typename allocator_traits_type::value_type value_type;
0625 typedef StoredSizeType stored_size_type;
0626
0627 template <class OtherAllocator, class OtherStoredSizeType, class OtherAllocatorVersion>
0628 friend struct vector_alloc_holder;
0629
0630
0631 vector_alloc_holder()
0632 BOOST_NOEXCEPT_IF(dtl::is_nothrow_default_constructible<allocator_type>::value)
0633 : allocator_type(), m_size()
0634 {}
0635
0636
0637 template<class AllocConvertible>
0638 explicit vector_alloc_holder(BOOST_FWD_REF(AllocConvertible) a) BOOST_NOEXCEPT_OR_NOTHROW
0639 : allocator_type(boost::forward<AllocConvertible>(a)), m_size()
0640 {}
0641
0642
0643 template<class AllocConvertible>
0644 vector_alloc_holder(vector_uninitialized_size_t, BOOST_FWD_REF(AllocConvertible) a, size_type initial_size)
0645 : allocator_type(boost::forward<AllocConvertible>(a))
0646 , m_size(initial_size)
0647 {
0648
0649 this->priv_first_allocation(initial_size);
0650 }
0651
0652
0653 vector_alloc_holder(vector_uninitialized_size_t, size_type initial_size)
0654 : allocator_type()
0655 , m_size(initial_size)
0656 {
0657
0658 this->priv_first_allocation(initial_size);
0659 }
0660
0661 vector_alloc_holder(BOOST_RV_REF(vector_alloc_holder) holder)
0662 : allocator_type(BOOST_MOVE_BASE(allocator_type, holder))
0663 , m_size(holder.m_size)
0664 {
0665 ::boost::container::uninitialized_move_alloc_n
0666 (this->alloc(), boost::movelib::to_raw_pointer(holder.start()), m_size, boost::movelib::to_raw_pointer(this->start()));
0667 ::boost::container::destroy_alloc_n
0668 (this->alloc(), boost::movelib::to_raw_pointer(holder.start()), m_size);
0669 holder.m_size = 0;
0670 }
0671
0672 template<class OtherAllocator, class OtherStoredSizeType, class OtherAllocatorVersion>
0673 vector_alloc_holder(BOOST_RV_REF_BEG vector_alloc_holder<OtherAllocator, OtherStoredSizeType, OtherAllocatorVersion> BOOST_RV_REF_END holder)
0674 : allocator_type()
0675 , m_size(holder.m_size)
0676 {
0677
0678 const size_type n = holder.m_size;
0679 this->priv_first_allocation(n);
0680 ::boost::container::uninitialized_move_alloc_n
0681 (this->alloc(), boost::movelib::to_raw_pointer(holder.start()), n, boost::movelib::to_raw_pointer(this->start()));
0682 }
0683
0684 static inline void on_capacity_overflow()
0685 { allocator_type::on_capacity_overflow(); }
0686
0687 inline void set_stored_size(size_type s) BOOST_NOEXCEPT_OR_NOTHROW
0688 { this->m_size = static_cast<stored_size_type>(s); }
0689
0690 inline void dec_stored_size(size_type s) BOOST_NOEXCEPT_OR_NOTHROW
0691 { this->m_size = static_cast<stored_size_type>(this->m_size - s); }
0692
0693 inline void inc_stored_size(size_type s) BOOST_NOEXCEPT_OR_NOTHROW
0694 { this->m_size = static_cast<stored_size_type>(this->m_size + s); }
0695
0696 inline void priv_first_allocation(size_type cap)
0697 {
0698 if(cap > allocator_type::internal_capacity){
0699 on_capacity_overflow();
0700 }
0701 }
0702
0703 inline void deep_swap(vector_alloc_holder &x)
0704 { this->priv_deep_swap(x); }
0705
0706 template<class OtherAllocator, class OtherStoredSizeType, class OtherAllocatorVersion>
0707 void deep_swap(vector_alloc_holder<OtherAllocator, OtherStoredSizeType, OtherAllocatorVersion> &x)
0708 {
0709 typedef typename real_allocator<value_type, OtherAllocator>::type other_allocator_type;
0710 if(this->m_size > other_allocator_type::internal_capacity || x.m_size > allocator_type::internal_capacity){
0711 on_capacity_overflow();
0712 }
0713 this->priv_deep_swap(x);
0714 }
0715
0716 inline void swap_resources(vector_alloc_holder &) BOOST_NOEXCEPT_OR_NOTHROW
0717 {
0718 on_capacity_overflow();
0719 }
0720
0721 inline void steal_resources(vector_alloc_holder &)
0722 {
0723 on_capacity_overflow();
0724 }
0725
0726 inline allocator_type &alloc() BOOST_NOEXCEPT_OR_NOTHROW
0727 { return *this; }
0728
0729 inline const allocator_type &alloc() const BOOST_NOEXCEPT_OR_NOTHROW
0730 { return *this; }
0731
0732 inline bool try_expand_fwd(size_type at_least)
0733 { return !at_least; }
0734
0735 inline pointer start() const BOOST_NOEXCEPT_OR_NOTHROW
0736 { return allocator_type::internal_storage(); }
0737
0738 inline size_type capacity() const BOOST_NOEXCEPT_OR_NOTHROW
0739 { return allocator_type::internal_capacity; }
0740
0741 stored_size_type m_size;
0742
0743 private:
0744
0745 template<class OtherAllocator, class OtherStoredSizeType, class OtherAllocatorVersion>
0746 void priv_deep_swap(vector_alloc_holder<OtherAllocator, OtherStoredSizeType, OtherAllocatorVersion> &x)
0747 {
0748 const size_type MaxTmpStorage = sizeof(value_type)*allocator_type::internal_capacity;
0749 value_type *const first_this = boost::movelib::to_raw_pointer(this->start());
0750 value_type *const first_x = boost::movelib::to_raw_pointer(x.start());
0751
0752 if(this->m_size < x.m_size){
0753 boost::container::deep_swap_alloc_n<MaxTmpStorage>(this->alloc(), first_this, this->m_size, first_x, x.m_size);
0754 }
0755 else{
0756 boost::container::deep_swap_alloc_n<MaxTmpStorage>(this->alloc(), first_x, x.m_size, first_this, this->m_size);
0757 }
0758 boost::adl_move_swap(this->m_size, x.m_size);
0759 }
0760 };
0761
0762 struct growth_factor_60;
0763 struct growth_factor_100;
0764
0765 template<class Options, class AllocatorSizeType>
0766 struct get_vector_opt
0767 {
0768 typedef vector_opt< typename default_if_void<typename Options::growth_factor_type, growth_factor_60>::type
0769 , typename default_if_void<typename Options::stored_size_type, AllocatorSizeType>::type
0770 > type;
0771 };
0772
0773 template<class AllocatorSizeType>
0774 struct get_vector_opt<void, AllocatorSizeType>
0775 {
0776 typedef vector_opt<growth_factor_60, AllocatorSizeType> type;
0777 };
0778
0779 #endif
0780
0781
0782
0783
0784
0785
0786
0787
0788
0789
0790 template <class T, class A BOOST_CONTAINER_DOCONLY(= void), class Options BOOST_CONTAINER_DOCONLY(= void) >
0791 class vector
0792 {
0793 public:
0794
0795
0796
0797
0798
0799 typedef T value_type;
0800 typedef BOOST_CONTAINER_IMPDEF
0801 (typename real_allocator<T BOOST_MOVE_I A>::type) allocator_type;
0802 typedef ::boost::container::allocator_traits<allocator_type> allocator_traits_t;
0803 typedef typename allocator_traits<allocator_type>::pointer pointer;
0804 typedef typename allocator_traits<allocator_type>::const_pointer const_pointer;
0805 typedef typename allocator_traits<allocator_type>::reference reference;
0806 typedef typename allocator_traits<allocator_type>::const_reference const_reference;
0807 typedef typename allocator_traits<allocator_type>::size_type size_type;
0808 typedef typename allocator_traits<allocator_type>::difference_type difference_type;
0809 typedef allocator_type stored_allocator_type;
0810 typedef BOOST_CONTAINER_IMPDEF(vec_iterator<pointer BOOST_MOVE_I false>) iterator;
0811 typedef BOOST_CONTAINER_IMPDEF(vec_iterator<pointer BOOST_MOVE_I true >) const_iterator;
0812 typedef BOOST_CONTAINER_IMPDEF(boost::container::reverse_iterator<iterator>) reverse_iterator;
0813 typedef BOOST_CONTAINER_IMPDEF(boost::container::reverse_iterator<const_iterator>) const_reverse_iterator;
0814
0815 private:
0816
0817 #ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
0818 typedef typename boost::container::
0819 allocator_traits<allocator_type>::size_type alloc_size_type;
0820 typedef typename get_vector_opt<Options, alloc_size_type>::type options_type;
0821 typedef typename options_type::growth_factor_type growth_factor_type;
0822 typedef typename options_type::stored_size_type stored_size_type;
0823 typedef value_less<T> value_less_t;
0824
0825
0826 BOOST_CONTAINER_STATIC_ASSERT( (sizeof(stored_size_type) < sizeof(alloc_size_type) ||
0827 dtl::is_same<stored_size_type, alloc_size_type>::value) );
0828
0829 typedef typename dtl::version<allocator_type>::type alloc_version;
0830 typedef boost::container::vector_alloc_holder
0831 <allocator_type, stored_size_type> alloc_holder_t;
0832
0833 alloc_holder_t m_holder;
0834
0835 typedef allocator_traits<allocator_type> allocator_traits_type;
0836 template <class U, class UA, class UOptions>
0837 friend class vector;
0838
0839
0840 protected:
0841 template <bool PropagateAllocator>
0842 inline static bool is_propagable_from(const allocator_type &from_alloc, pointer p, const allocator_type &to_alloc)
0843 { return alloc_holder_t::template is_propagable_from<PropagateAllocator>(from_alloc, p, to_alloc); }
0844
0845 template <bool PropagateAllocator>
0846 inline static bool are_swap_propagable( const allocator_type &l_a, pointer l_p
0847 , const allocator_type &r_a, pointer r_p)
0848 { return alloc_holder_t::template are_swap_propagable<PropagateAllocator>(l_a, l_p, r_a, r_p); }
0849
0850 #endif
0851 #ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
0852 private:
0853 BOOST_COPYABLE_AND_MOVABLE(vector)
0854 typedef vector_value_traits<allocator_type> value_traits;
0855 typedef constant_iterator<T> cvalue_iterator;
0856
0857 protected:
0858
0859 inline void steal_resources(vector &x)
0860 { return this->m_holder.steal_resources(x.m_holder); }
0861
0862 inline void protected_set_size(size_type n)
0863 { this->m_holder.m_size = static_cast<stored_size_type>(n); }
0864
0865 template<class AllocFwd>
0866 inline vector(initial_capacity_t, pointer initial_memory, size_type cap, BOOST_FWD_REF(AllocFwd) a)
0867 : m_holder(initial_capacity_t(), initial_memory, cap, ::boost::forward<AllocFwd>(a))
0868 {}
0869
0870 template<class AllocFwd>
0871 inline vector(initial_capacity_t, pointer initial_memory, size_type cap, BOOST_FWD_REF(AllocFwd) a, vector &x)
0872 : m_holder(initial_capacity_t(), initial_memory, cap, ::boost::forward<AllocFwd>(a))
0873 {
0874 allocator_type &this_al = this->get_stored_allocator();
0875 if (this->template is_propagable_from<true>(x.get_stored_allocator(), x.data(), this_al)) {
0876 this->steal_resources(x);
0877 }
0878 else {
0879 const size_type sz = x.size();
0880 ::boost::container::uninitialized_move_alloc_n_source
0881 ( this_al, x.priv_raw_begin(), sz
0882
0883 , boost::move_detail::launder(this->priv_raw_begin()));
0884 this->protected_set_size(sz);
0885 x.clear();
0886 }
0887 }
0888
0889 inline vector(initial_capacity_t, pointer initial_memory, size_type cap)
0890 : m_holder(initial_capacity_t(), initial_memory, cap)
0891 {}
0892
0893 template<class SizeType, class AllocFwd>
0894 inline vector(maybe_initial_capacity_t, pointer p, SizeType initial_capacity, BOOST_FWD_REF(AllocFwd) a)
0895 : m_holder(maybe_initial_capacity_t(), p, initial_capacity, ::boost::forward<AllocFwd>(a))
0896 {
0897 #ifdef BOOST_CONTAINER_VECTOR_ALLOC_STATS
0898 this->num_alloc += size_type(p != pointer());
0899 #endif
0900 }
0901
0902 template<class SizeType>
0903 inline vector(maybe_initial_capacity_t, pointer p, SizeType initial_capacity)
0904 : m_holder(maybe_initial_capacity_t(), p, initial_capacity)
0905 {
0906 #ifdef BOOST_CONTAINER_VECTOR_ALLOC_STATS
0907 this->num_alloc += size_type(p != pointer());
0908 #endif
0909 }
0910
0911 template <class U>
0912 void protected_init_n(const size_type new_size, const U& u)
0913 {
0914 BOOST_ASSERT(this->empty());
0915 this->priv_resize_proxy(u).uninitialized_copy_n_and_update(this->m_holder.alloc(), this->priv_raw_begin(), new_size);
0916 this->m_holder.set_stored_size(new_size);
0917 }
0918
0919 #endif
0920
0921 public:
0922
0923
0924
0925
0926
0927
0928
0929
0930
0931
0932
0933 vector() BOOST_NOEXCEPT_IF(dtl::is_nothrow_default_constructible<allocator_type>::value)
0934 : m_holder()
0935 {}
0936
0937
0938
0939
0940
0941
0942 explicit vector(const allocator_type& a) BOOST_NOEXCEPT_OR_NOTHROW
0943 : m_holder(a)
0944 {}
0945
0946
0947
0948
0949
0950
0951
0952 explicit vector(size_type n)
0953 : m_holder(vector_uninitialized_size, n)
0954 {
0955 #ifdef BOOST_CONTAINER_VECTOR_ALLOC_STATS
0956 this->num_alloc += n != 0;
0957 #endif
0958 boost::container::uninitialized_value_init_alloc_n
0959 (this->m_holder.alloc(), n, this->priv_raw_begin());
0960 }
0961
0962
0963
0964
0965
0966
0967
0968
0969 explicit vector(size_type n, const allocator_type &a)
0970 : m_holder(vector_uninitialized_size, a, n)
0971 {
0972 #ifdef BOOST_CONTAINER_VECTOR_ALLOC_STATS
0973 this->num_alloc += n != 0;
0974 #endif
0975 boost::container::uninitialized_value_init_alloc_n
0976 (this->m_holder.alloc(), n, this->priv_raw_begin());
0977 }
0978
0979
0980
0981
0982
0983
0984
0985
0986
0987
0988 vector(size_type n, default_init_t)
0989 : m_holder(vector_uninitialized_size, n)
0990 {
0991 #ifdef BOOST_CONTAINER_VECTOR_ALLOC_STATS
0992 this->num_alloc += n != 0;
0993 #endif
0994 boost::container::uninitialized_default_init_alloc_n
0995 (this->m_holder.alloc(), n, this->priv_raw_begin());
0996 }
0997
0998
0999
1000
1001
1002
1003
1004
1005
1006
1007 vector(size_type n, default_init_t, const allocator_type &a)
1008 : m_holder(vector_uninitialized_size, a, n)
1009 {
1010 #ifdef BOOST_CONTAINER_VECTOR_ALLOC_STATS
1011 this->num_alloc += n != 0;
1012 #endif
1013 boost::container::uninitialized_default_init_alloc_n
1014 (this->m_holder.alloc(), n, this->priv_raw_begin());
1015 }
1016
1017
1018
1019
1020
1021
1022
1023
1024 vector(size_type n, const T& value)
1025 : m_holder(vector_uninitialized_size, n)
1026 {
1027 #ifdef BOOST_CONTAINER_VECTOR_ALLOC_STATS
1028 this->num_alloc += n != 0;
1029 #endif
1030 boost::container::uninitialized_fill_alloc_n
1031 (this->m_holder.alloc(), value, n, this->priv_raw_begin());
1032 }
1033
1034
1035
1036
1037
1038
1039
1040
1041 vector(size_type n, const T& value, const allocator_type& a)
1042 : m_holder(vector_uninitialized_size, a, n)
1043 {
1044 #ifdef BOOST_CONTAINER_VECTOR_ALLOC_STATS
1045 this->num_alloc += n != 0;
1046 #endif
1047 boost::container::uninitialized_fill_alloc_n
1048 (this->m_holder.alloc(), value, n, this->priv_raw_begin());
1049 }
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064 template <class InIt>
1065 vector(InIt first, InIt last
1066 BOOST_CONTAINER_DOCIGN(BOOST_MOVE_I typename dtl::disable_if_c
1067 < dtl::is_convertible<InIt BOOST_MOVE_I size_type>::value
1068 BOOST_MOVE_I dtl::nat >::type * = 0)
1069 )
1070 : m_holder()
1071 { this->assign(first, last); }
1072
1073
1074
1075
1076
1077
1078
1079
1080 template <class InIt>
1081 vector(InIt first, InIt last, const allocator_type& a
1082 BOOST_CONTAINER_DOCIGN(BOOST_MOVE_I typename dtl::disable_if_c
1083 < dtl::is_convertible<InIt BOOST_MOVE_I size_type>::value
1084 BOOST_MOVE_I dtl::nat >::type * = 0)
1085 )
1086 : m_holder(a)
1087 { this->assign(first, last); }
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097 vector(const vector &x)
1098 : m_holder( vector_uninitialized_size
1099 , allocator_traits_type::select_on_container_copy_construction(x.m_holder.alloc())
1100 , x.size())
1101 {
1102 #ifdef BOOST_CONTAINER_VECTOR_ALLOC_STATS
1103 this->num_alloc += x.size() != 0;
1104 #endif
1105 ::boost::container::uninitialized_copy_alloc_n
1106 ( this->m_holder.alloc(), x.priv_raw_begin()
1107 , x.size(), this->priv_raw_begin());
1108 }
1109
1110
1111
1112
1113
1114
1115 vector(BOOST_RV_REF(vector) x) BOOST_NOEXCEPT_OR_NOTHROW
1116 : m_holder(boost::move(x.m_holder))
1117 { BOOST_CONTAINER_STATIC_ASSERT((!allocator_traits_type::is_partially_propagable::value)); }
1118
1119 #if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
1120
1121
1122
1123
1124
1125
1126 vector(std::initializer_list<value_type> il, const allocator_type& a = allocator_type())
1127 : m_holder(vector_uninitialized_size, a, il.size())
1128 {
1129 #ifdef BOOST_CONTAINER_VECTOR_ALLOC_STATS
1130 this->num_alloc += il.size() != 0;
1131 #endif
1132 ::boost::container::uninitialized_copy_alloc_n_source
1133 ( this->m_holder.alloc(), il.begin()
1134 , static_cast<size_type>(il.size()), this->priv_raw_begin());
1135 }
1136 #endif
1137
1138 #if !defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
1139
1140
1141
1142
1143
1144
1145
1146
1147 template<class OtherA>
1148 vector(BOOST_RV_REF_BEG vector<T, OtherA, Options> BOOST_RV_REF_END x
1149 , typename dtl::enable_if_c
1150 < dtl::is_version<typename real_allocator<T, OtherA>::type, 0>::value>::type * = 0
1151 )
1152 : m_holder(boost::move(x.m_holder))
1153 {}
1154
1155 #endif
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165 vector(const vector &x, const allocator_type &a)
1166 : m_holder(vector_uninitialized_size, a, x.size())
1167 {
1168 #ifdef BOOST_CONTAINER_VECTOR_ALLOC_STATS
1169 this->num_alloc += x.size() != 0;
1170 #endif
1171 ::boost::container::uninitialized_copy_alloc_n_source
1172 ( this->m_holder.alloc(), x.priv_raw_begin()
1173 , x.size(), this->priv_raw_begin());
1174 }
1175
1176
1177
1178
1179
1180
1181
1182
1183 vector(BOOST_RV_REF(vector) x, const allocator_type &a)
1184 : m_holder( vector_uninitialized_size, a
1185
1186 , is_propagable_from<false>(x.get_stored_allocator(), x.m_holder.start(), a) ? 0 : x.size()
1187 )
1188 {
1189
1190 if(is_propagable_from<false>(x.get_stored_allocator(), x.m_holder.start(), a)){
1191 this->m_holder.steal_resources(x.m_holder);
1192 }
1193 else{
1194 const size_type n = x.size();
1195 #ifdef BOOST_CONTAINER_VECTOR_ALLOC_STATS
1196 this->num_alloc += n != 0;
1197 #endif
1198 ::boost::container::uninitialized_move_alloc_n_source
1199 ( this->m_holder.alloc(), x.priv_raw_begin()
1200 , n, this->priv_raw_begin());
1201 }
1202 }
1203
1204
1205
1206
1207
1208
1209
1210 ~vector() BOOST_NOEXCEPT_OR_NOTHROW
1211 {
1212 boost::container::destroy_alloc_n
1213 (this->get_stored_allocator(), this->priv_raw_begin(), this->m_holder.m_size);
1214
1215 }
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225 inline vector& operator=(BOOST_COPY_ASSIGN_REF(vector) x)
1226 {
1227 if (BOOST_LIKELY(&x != this)){
1228 this->priv_copy_assign(x);
1229 }
1230 return *this;
1231 }
1232
1233 #if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
1234
1235
1236
1237 inline vector& operator=(std::initializer_list<value_type> il)
1238 {
1239 this->assign(il.begin(), il.end());
1240 return *this;
1241 }
1242 #endif
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255 inline vector& operator=(BOOST_RV_REF(vector) x)
1256 BOOST_NOEXCEPT_IF(allocator_traits_type::propagate_on_container_move_assignment::value
1257 || allocator_traits_type::is_always_equal::value)
1258 {
1259 if (BOOST_LIKELY(&x != this)){
1260 this->priv_move_assign(boost::move(x));
1261 }
1262 return *this;
1263 }
1264
1265 #if !defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277 template<class OtherA>
1278 inline typename dtl::enable_if_and
1279 < vector&
1280 , dtl::is_version<typename real_allocator<T, OtherA>::type, 0>
1281 , dtl::is_different<typename real_allocator<T, OtherA>::type, allocator_type>
1282 >::type
1283 operator=(BOOST_RV_REF_BEG vector<value_type, OtherA, Options> BOOST_RV_REF_END x)
1284 {
1285 this->priv_move_assign(boost::move(x));
1286 return *this;
1287 }
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299 template<class OtherA>
1300 inline typename dtl::enable_if_and
1301 < vector&
1302 , dtl::is_version<typename real_allocator<T, OtherA>::type, 0>
1303 , dtl::is_different<typename real_allocator<T, OtherA>::type, allocator_type>
1304 >::type
1305 operator=(const vector<value_type, OtherA, Options> &x)
1306 {
1307 this->priv_copy_assign(x);
1308 return *this;
1309 }
1310
1311 #endif
1312
1313
1314
1315
1316
1317
1318
1319 template <class InIt>
1320 void assign(InIt first, InIt last
1321
1322 BOOST_CONTAINER_DOCIGN(BOOST_MOVE_I typename dtl::disable_if_or
1323 < void
1324 BOOST_MOVE_I dtl::is_convertible<InIt BOOST_MOVE_I size_type>
1325 BOOST_MOVE_I dtl::and_
1326 < dtl::is_different<alloc_version BOOST_MOVE_I version_0>
1327 BOOST_MOVE_I dtl::is_not_input_iterator<InIt>
1328 >
1329 >::type * = 0)
1330 )
1331 {
1332
1333 iterator cur = this->begin();
1334 const iterator end_it = this->end();
1335 for ( ; first != last && cur != end_it; ++cur, ++first){
1336 *cur = *first;
1337 }
1338
1339 if (first == last){
1340
1341 T* const end_pos = this->priv_raw_end();
1342 const size_type n = static_cast<size_type>(end_pos - boost::movelib::iterator_to_raw_pointer(cur));
1343 this->priv_destroy_last_n(n);
1344 }
1345 else{
1346
1347 this->insert(this->cend(), first, last);
1348 }
1349 }
1350
1351 #if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
1352
1353
1354
1355
1356
1357 inline void assign(std::initializer_list<T> il)
1358 {
1359 this->assign(il.begin(), il.end());
1360 }
1361 #endif
1362
1363
1364
1365
1366
1367
1368
1369 template <class FwdIt>
1370 void assign(FwdIt first, FwdIt last
1371
1372 BOOST_CONTAINER_DOCIGN(BOOST_MOVE_I typename dtl::disable_if_or
1373 < void
1374 BOOST_MOVE_I dtl::is_same<alloc_version BOOST_MOVE_I version_0>
1375 BOOST_MOVE_I dtl::is_convertible<FwdIt BOOST_MOVE_I size_type>
1376 BOOST_MOVE_I dtl::is_input_iterator<FwdIt>
1377 >::type * = 0)
1378 )
1379 {
1380 typedef typename iter_size<FwdIt>::type it_size_type;
1381
1382
1383 const it_size_type sz = boost::container::iterator_udistance(first, last);
1384 if (BOOST_UNLIKELY(sz > size_type(-1))){
1385 boost::container::throw_length_error("vector::assign, FwdIt's max length reached");
1386 }
1387
1388 const size_type input_sz = static_cast<size_type>(sz);
1389 const size_type old_capacity = this->capacity();
1390 if(input_sz > old_capacity){
1391 size_type real_cap = 0;
1392 pointer reuse(this->m_holder.start());
1393 pointer const ret(this->m_holder.allocation_command(allocate_new|expand_fwd, input_sz, real_cap = input_sz, reuse));
1394 if(!reuse){
1395 #ifdef BOOST_CONTAINER_VECTOR_ALLOC_STATS
1396 ++this->num_alloc;
1397 #endif
1398 pointer const old_p = this->m_holder.start();
1399 if(old_p){
1400 this->priv_destroy_all();
1401 this->m_holder.deallocate(old_p, old_capacity);
1402 }
1403 this->m_holder.start(ret);
1404 this->m_holder.capacity(real_cap);
1405 this->m_holder.m_size = 0;
1406 this->priv_uninitialized_construct_at_end(first, last);
1407 return;
1408 }
1409 else{
1410 #ifdef BOOST_CONTAINER_VECTOR_ALLOC_STATS
1411 ++this->num_expand_fwd;
1412 #endif
1413 this->m_holder.capacity(real_cap);
1414
1415 }
1416 }
1417
1418 boost::container::copy_assign_range_alloc_n(this->m_holder.alloc(), first, input_sz, this->priv_raw_begin(), this->size());
1419 m_holder.set_stored_size(input_sz);
1420 }
1421
1422
1423
1424
1425
1426
1427
1428 inline void assign(size_type n, const value_type& val)
1429 { this->assign(cvalue_iterator(val, n), cvalue_iterator()); }
1430
1431
1432
1433
1434
1435
1436 BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline allocator_type get_allocator() const BOOST_NOEXCEPT_OR_NOTHROW
1437 { return this->m_holder.alloc(); }
1438
1439
1440
1441
1442
1443
1444
1445
1446 BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline
1447 stored_allocator_type &get_stored_allocator() BOOST_NOEXCEPT_OR_NOTHROW
1448 { return this->m_holder.alloc(); }
1449
1450
1451
1452
1453
1454
1455
1456
1457 BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline
1458 const stored_allocator_type &get_stored_allocator() const BOOST_NOEXCEPT_OR_NOTHROW
1459 { return this->m_holder.alloc(); }
1460
1461
1462
1463
1464
1465
1466
1467
1468
1469
1470
1471
1472 BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline iterator begin() BOOST_NOEXCEPT_OR_NOTHROW
1473 { return iterator(this->m_holder.start()); }
1474
1475
1476
1477
1478
1479
1480 BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline const_iterator begin() const BOOST_NOEXCEPT_OR_NOTHROW
1481 { return const_iterator(this->m_holder.start()); }
1482
1483
1484
1485
1486
1487
1488 BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline iterator end() BOOST_NOEXCEPT_OR_NOTHROW
1489 {
1490 iterator it (this->m_holder.start());
1491 it += difference_type(this->m_holder.m_size);
1492 return it;
1493 }
1494
1495
1496
1497
1498
1499
1500 BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline const_iterator end() const BOOST_NOEXCEPT_OR_NOTHROW
1501 { return this->cend(); }
1502
1503
1504
1505
1506
1507
1508
1509 BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline reverse_iterator rbegin() BOOST_NOEXCEPT_OR_NOTHROW
1510 { return reverse_iterator(this->end()); }
1511
1512
1513
1514
1515
1516
1517
1518 BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline const_reverse_iterator rbegin() const BOOST_NOEXCEPT_OR_NOTHROW
1519 { return this->crbegin(); }
1520
1521
1522
1523
1524
1525
1526
1527 BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline reverse_iterator rend() BOOST_NOEXCEPT_OR_NOTHROW
1528 { return reverse_iterator(this->begin()); }
1529
1530
1531
1532
1533
1534
1535
1536 BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline const_reverse_iterator rend() const BOOST_NOEXCEPT_OR_NOTHROW
1537 { return this->crend(); }
1538
1539
1540
1541
1542
1543
1544 BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline const_iterator cbegin() const BOOST_NOEXCEPT_OR_NOTHROW
1545 { return const_iterator(this->m_holder.start()); }
1546
1547
1548
1549
1550
1551
1552 BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline const_iterator cend() const BOOST_NOEXCEPT_OR_NOTHROW
1553 {
1554 const_iterator it (this->m_holder.start());
1555 it += difference_type(this->m_holder.m_size);
1556 return it;
1557 }
1558
1559
1560
1561
1562
1563
1564
1565 BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline const_reverse_iterator crbegin() const BOOST_NOEXCEPT_OR_NOTHROW
1566 { return const_reverse_iterator(this->end());}
1567
1568
1569
1570
1571
1572
1573
1574 BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline const_reverse_iterator crend() const BOOST_NOEXCEPT_OR_NOTHROW
1575 { return const_reverse_iterator(this->begin()); }
1576
1577
1578
1579
1580
1581
1582
1583
1584
1585
1586
1587
1588 BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline bool empty() const BOOST_NOEXCEPT_OR_NOTHROW
1589 { return !this->m_holder.m_size; }
1590
1591
1592
1593
1594
1595
1596 BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline size_type size() const BOOST_NOEXCEPT_OR_NOTHROW
1597 { return this->m_holder.m_size; }
1598
1599
1600
1601
1602
1603
1604 BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline size_type max_size() const BOOST_NOEXCEPT_OR_NOTHROW
1605 { return allocator_traits_type::max_size(this->m_holder.alloc()); }
1606
1607
1608
1609
1610
1611
1612
1613 inline void resize(size_type new_size)
1614 { this->priv_resize(new_size, value_init, alloc_version()); }
1615
1616
1617
1618
1619
1620
1621
1622
1623
1624 inline void resize(size_type new_size, default_init_t)
1625 { this->priv_resize(new_size, default_init, alloc_version()); }
1626
1627
1628
1629
1630
1631
1632
1633 inline void resize(size_type new_size, const T& x)
1634 { this->priv_resize(new_size, x, alloc_version()); }
1635
1636
1637
1638
1639
1640
1641
1642 BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline size_type capacity() const BOOST_NOEXCEPT_OR_NOTHROW
1643 { return this->m_holder.capacity(); }
1644
1645
1646
1647
1648
1649
1650
1651 inline void reserve(size_type new_cap)
1652 {
1653 if (this->capacity() < new_cap){
1654 this->priv_move_to_new_buffer(new_cap, alloc_version());
1655 }
1656 }
1657
1658
1659
1660
1661
1662
1663
1664 inline void shrink_to_fit()
1665 { this->priv_shrink_to_fit(alloc_version()); }
1666
1667
1668
1669
1670
1671
1672
1673
1674
1675
1676
1677
1678
1679
1680
1681 BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline reference front() BOOST_NOEXCEPT_OR_NOTHROW
1682 {
1683 BOOST_ASSERT(!this->empty());
1684 return *this->m_holder.start();
1685 }
1686
1687
1688
1689
1690
1691
1692
1693
1694
1695 BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline const_reference front() const BOOST_NOEXCEPT_OR_NOTHROW
1696 {
1697 BOOST_ASSERT(!this->empty());
1698 return *this->m_holder.start();
1699 }
1700
1701
1702
1703
1704
1705
1706
1707
1708
1709 BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline reference back() BOOST_NOEXCEPT_OR_NOTHROW
1710 {
1711 BOOST_ASSERT(!this->empty());
1712 return this->m_holder.start()[difference_type(this->m_holder.m_size - 1u)];
1713 }
1714
1715
1716
1717
1718
1719
1720
1721
1722
1723 BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline const_reference back() const BOOST_NOEXCEPT_OR_NOTHROW
1724 {
1725 BOOST_ASSERT(!this->empty());
1726 return this->m_holder.start()[this->m_holder.m_size - 1];
1727 }
1728
1729
1730
1731
1732
1733
1734
1735
1736
1737 BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline reference operator[](size_type n) BOOST_NOEXCEPT_OR_NOTHROW
1738 {
1739 BOOST_ASSERT(this->m_holder.m_size > n);
1740 return this->m_holder.start()[difference_type(n)];
1741 }
1742
1743
1744
1745
1746
1747
1748
1749
1750
1751 BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline
1752 const_reference operator[](size_type n) const BOOST_NOEXCEPT_OR_NOTHROW
1753 {
1754 BOOST_ASSERT(this->m_holder.m_size > n);
1755 return this->m_holder.start()[n];
1756 }
1757
1758
1759
1760
1761
1762
1763
1764
1765
1766
1767
1768
1769 BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline
1770 iterator nth(size_type n) BOOST_NOEXCEPT_OR_NOTHROW
1771 {
1772 BOOST_ASSERT(this->m_holder.m_size >= n);
1773 return iterator(this->m_holder.start()+difference_type(n));
1774 }
1775
1776
1777
1778
1779
1780
1781
1782
1783
1784
1785
1786
1787 BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline
1788 const_iterator nth(size_type n) const BOOST_NOEXCEPT_OR_NOTHROW
1789 {
1790 BOOST_ASSERT(this->m_holder.m_size >= n);
1791 return const_iterator(this->m_holder.start()+difference_type(n));
1792 }
1793
1794
1795
1796
1797
1798
1799
1800
1801
1802
1803
1804 BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline
1805 size_type index_of(iterator p) BOOST_NOEXCEPT_OR_NOTHROW
1806 {
1807
1808 return this->priv_index_of(vector_iterator_get_ptr(p));
1809 }
1810
1811
1812
1813
1814
1815
1816
1817
1818
1819
1820
1821 BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline
1822 size_type index_of(const_iterator p) const BOOST_NOEXCEPT_OR_NOTHROW
1823 {
1824
1825 return this->priv_index_of(vector_iterator_get_ptr(p));
1826 }
1827
1828
1829
1830
1831
1832
1833
1834
1835
1836 BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline reference at(size_type n)
1837 {
1838 this->priv_throw_if_out_of_range(n);
1839 return this->m_holder.start()[difference_type(n)];
1840 }
1841
1842
1843
1844
1845
1846
1847
1848
1849
1850 BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline const_reference at(size_type n) const
1851 {
1852 this->priv_throw_if_out_of_range(n);
1853 return this->m_holder.start()[n];
1854 }
1855
1856
1857
1858
1859
1860
1861
1862
1863
1864
1865
1866
1867
1868 BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline T* data() BOOST_NOEXCEPT_OR_NOTHROW
1869 { return this->priv_raw_begin(); }
1870
1871
1872
1873
1874
1875
1876
1877 BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline const T * data() const BOOST_NOEXCEPT_OR_NOTHROW
1878 { return this->priv_raw_begin(); }
1879
1880
1881
1882
1883
1884
1885
1886 #if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) || defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
1887
1888
1889
1890
1891
1892
1893
1894
1895
1896 template<class ...Args>
1897 inline reference emplace_back(BOOST_FWD_REF(Args)...args)
1898 {
1899 T* const p = this->priv_raw_end();
1900 if (BOOST_LIKELY(this->room_enough())){
1901
1902 allocator_traits_type::construct(this->m_holder.alloc(), p, ::boost::forward<Args>(args)...);
1903 ++this->m_holder.m_size;
1904 return *p;
1905 }
1906 else{
1907 typedef dtl::insert_emplace_proxy<allocator_type, Args...> proxy_t;
1908 return *this->priv_insert_forward_range_no_capacity
1909 (p, 1, proxy_t(::boost::forward<Args>(args)...), alloc_version());
1910 }
1911 }
1912
1913
1914
1915
1916
1917
1918
1919
1920
1921 template<class ...Args>
1922 inline bool stable_emplace_back(BOOST_FWD_REF(Args)...args)
1923 {
1924 const bool is_room_enough = this->room_enough() || (alloc_version::value == 2 && this->m_holder.try_expand_fwd(1u));
1925 if (BOOST_LIKELY(is_room_enough)){
1926
1927 allocator_traits_type::construct(this->m_holder.alloc(), this->priv_raw_end(), ::boost::forward<Args>(args)...);
1928 ++this->m_holder.m_size;
1929 }
1930 return is_room_enough;
1931 }
1932
1933
1934
1935
1936
1937
1938
1939
1940
1941
1942
1943 template<class ...Args>
1944 inline iterator emplace(const_iterator position, BOOST_FWD_REF(Args) ...args)
1945 {
1946 BOOST_ASSERT(this->priv_in_range_or_end(position));
1947
1948 typedef dtl::insert_emplace_proxy<allocator_type, Args...> proxy_t;
1949 return this->priv_insert_forward_range( vector_iterator_get_ptr(position), 1
1950 , proxy_t(::boost::forward<Args>(args)...));
1951 }
1952
1953 #else
1954
1955 #define BOOST_CONTAINER_VECTOR_EMPLACE_CODE(N) \
1956 BOOST_MOVE_TMPL_LT##N BOOST_MOVE_CLASS##N BOOST_MOVE_GT##N \
1957 inline reference emplace_back(BOOST_MOVE_UREF##N)\
1958 {\
1959 T* const p = this->priv_raw_end();\
1960 if (BOOST_LIKELY(this->room_enough())){\
1961 allocator_traits_type::construct (this->m_holder.alloc()\
1962 , this->priv_raw_end() BOOST_MOVE_I##N BOOST_MOVE_FWD##N);\
1963 ++this->m_holder.m_size;\
1964 return *p;\
1965 }\
1966 else{\
1967 typedef dtl::insert_emplace_proxy_arg##N<allocator_type BOOST_MOVE_I##N BOOST_MOVE_TARG##N> proxy_t;\
1968 return *this->priv_insert_forward_range_no_capacity\
1969 ( p, 1, proxy_t(BOOST_MOVE_FWD##N), alloc_version());\
1970 }\
1971 }\
1972 \
1973 BOOST_MOVE_TMPL_LT##N BOOST_MOVE_CLASS##N BOOST_MOVE_GT##N \
1974 inline bool stable_emplace_back(BOOST_MOVE_UREF##N)\
1975 {\
1976 const bool is_room_enough = this->room_enough() || (alloc_version::value == 2 && this->m_holder.try_expand_fwd(1u));\
1977 if (BOOST_LIKELY(is_room_enough)){\
1978 allocator_traits_type::construct (this->m_holder.alloc()\
1979 , this->priv_raw_end() BOOST_MOVE_I##N BOOST_MOVE_FWD##N);\
1980 ++this->m_holder.m_size;\
1981 }\
1982 return is_room_enough;\
1983 }\
1984 \
1985 BOOST_MOVE_TMPL_LT##N BOOST_MOVE_CLASS##N BOOST_MOVE_GT##N \
1986 inline iterator emplace(const_iterator pos BOOST_MOVE_I##N BOOST_MOVE_UREF##N)\
1987 {\
1988 BOOST_ASSERT(this->priv_in_range_or_end(pos));\
1989 typedef dtl::insert_emplace_proxy_arg##N<allocator_type BOOST_MOVE_I##N BOOST_MOVE_TARG##N> proxy_t;\
1990 return this->priv_insert_forward_range(vector_iterator_get_ptr(pos), 1, proxy_t(BOOST_MOVE_FWD##N));\
1991 }\
1992
1993 BOOST_MOVE_ITERATE_0TO9(BOOST_CONTAINER_VECTOR_EMPLACE_CODE)
1994 #undef BOOST_CONTAINER_VECTOR_EMPLACE_CODE
1995
1996 #endif
1997
1998 #if defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
1999
2000
2001
2002
2003
2004
2005 void push_back(const T &x);
2006
2007
2008
2009
2010
2011
2012
2013
2014 void push_back(T &&x);
2015 #else
2016 BOOST_MOVE_CONVERSION_AWARE_CATCH(push_back, T, void, priv_push_back)
2017 #endif
2018
2019 #if defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
2020
2021
2022
2023
2024
2025
2026
2027
2028 iterator insert(const_iterator position, const T &x);
2029
2030
2031
2032
2033
2034
2035
2036
2037
2038 iterator insert(const_iterator position, T &&x);
2039 #else
2040 BOOST_MOVE_CONVERSION_AWARE_CATCH_1ARG(insert, T, iterator, priv_insert, const_iterator, const_iterator)
2041 #endif
2042
2043
2044
2045
2046
2047
2048
2049
2050
2051
2052 inline iterator insert(const_iterator p, size_type n, const T& x)
2053 {
2054 BOOST_ASSERT(this->priv_in_range_or_end(p));
2055 dtl::insert_n_copies_proxy<allocator_type> proxy(x);
2056 return this->priv_insert_forward_range(vector_iterator_get_ptr(p), n, proxy);
2057 }
2058
2059
2060
2061
2062
2063
2064
2065
2066
2067
2068
2069 template <class InIt>
2070 iterator insert(const_iterator pos, InIt first, InIt last
2071 #if !defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
2072 , typename dtl::disable_if_or
2073 < void
2074 , dtl::is_convertible<InIt, size_type>
2075 , dtl::is_not_input_iterator<InIt>
2076 >::type * = 0
2077 #endif
2078 )
2079 {
2080 BOOST_ASSERT(this->priv_in_range_or_end(pos));
2081 const size_type n_pos = size_type(pos - this->cbegin());
2082 iterator it(vector_iterator_get_ptr(pos));
2083 for(;first != last; ++first){
2084 it = this->emplace(it, *first);
2085 ++it;
2086 }
2087 return iterator(this->m_holder.start() + difference_type(n_pos));
2088 }
2089
2090 #if !defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
2091 template <class FwdIt>
2092 inline iterator insert(const_iterator pos, FwdIt first, FwdIt last
2093 , typename dtl::disable_if_or
2094 < void
2095 , dtl::is_convertible<FwdIt, size_type>
2096 , dtl::is_input_iterator<FwdIt>
2097 >::type * = 0
2098 )
2099 {
2100 typedef typename iter_size<FwdIt>::type it_size_type;
2101 BOOST_ASSERT(this->priv_in_range_or_end(pos));
2102 const it_size_type sz = boost::container::iterator_udistance(first, last);
2103 if (BOOST_UNLIKELY(sz > size_type(-1))){
2104 boost::container::throw_length_error("vector::insert, FwdIt's max length reached");
2105 }
2106
2107 dtl::insert_range_proxy<allocator_type, FwdIt> proxy(first);
2108 return this->priv_insert_forward_range(vector_iterator_get_ptr(pos), static_cast<size_type>(sz), proxy);
2109 }
2110 #endif
2111
2112
2113
2114
2115
2116
2117
2118
2119
2120
2121
2122
2123
2124
2125
2126
2127 #if !defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
2128 template <class InIt>
2129 inline iterator insert(const_iterator pos, size_type num, InIt first, InIt last)
2130 {
2131 BOOST_ASSERT(this->priv_in_range_or_end(pos));
2132 BOOST_ASSERT(dtl::is_input_iterator<InIt>::value ||
2133 num == boost::container::iterator_udistance(first, last));
2134 (void)last;
2135 dtl::insert_range_proxy<allocator_type, InIt> proxy(first);
2136 return this->priv_insert_forward_range(vector_iterator_get_ptr(pos), num, proxy);
2137 }
2138 #endif
2139
2140 #if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
2141
2142
2143
2144
2145
2146
2147
2148 inline iterator insert(const_iterator position, std::initializer_list<value_type> il)
2149 {
2150
2151 return this->insert(position, il.begin(), il.end());
2152 }
2153 #endif
2154
2155
2156
2157
2158
2159
2160 inline void pop_back() BOOST_NOEXCEPT_OR_NOTHROW
2161 {
2162 BOOST_ASSERT(!this->empty());
2163
2164 allocator_traits_type::destroy(this->get_stored_allocator(), this->priv_raw_end() - 1);
2165 --this->m_holder.m_size;
2166 }
2167
2168
2169
2170
2171
2172
2173
2174 iterator erase(const_iterator position)
2175 {
2176 BOOST_ASSERT(this->priv_in_range(position));
2177 const pointer p = vector_iterator_get_ptr(position);
2178 T *const pos_ptr = boost::movelib::to_raw_pointer(p);
2179 T *const end_ptr = this->priv_raw_end();
2180
2181
2182 (void)::boost::container::move(pos_ptr + 1, end_ptr, pos_ptr);
2183
2184 T *const last_ptr = end_ptr-1;
2185 if(!value_traits::trivial_dctr_after_move || pos_ptr == last_ptr){
2186 allocator_traits_type::destroy(this->get_stored_allocator(), last_ptr);
2187 }
2188 --this->m_holder.m_size;
2189 return iterator(p);
2190 }
2191
2192
2193
2194
2195
2196
2197
2198 iterator erase(const_iterator first, const_iterator last)
2199 {
2200 BOOST_ASSERT(this->priv_in_range_or_end(first));
2201 BOOST_ASSERT(this->priv_in_range_or_end(last));
2202 BOOST_ASSERT(first <= last);
2203 if(first != last){
2204 T* const old_end_ptr = this->priv_raw_end();
2205 T* const first_ptr = boost::movelib::to_raw_pointer(vector_iterator_get_ptr(first));
2206 T* const last_ptr = boost::movelib::to_raw_pointer(vector_iterator_get_ptr(last));
2207 T* const new_last_ptr = boost::movelib::to_raw_pointer(boost::container::move(last_ptr, old_end_ptr, first_ptr));
2208 const size_type n = static_cast<size_type>(old_end_ptr - new_last_ptr);
2209 if(!value_traits::trivial_dctr_after_move || old_end_ptr == last_ptr){
2210 boost::container::destroy_alloc_n(this->get_stored_allocator(), new_last_ptr, n);
2211 }
2212 this->m_holder.dec_stored_size(n);
2213 }
2214 return iterator(vector_iterator_get_ptr(first));
2215 }
2216
2217
2218
2219
2220
2221
2222 inline void swap(vector& x)
2223 BOOST_NOEXCEPT_IF( ((allocator_traits_type::propagate_on_container_swap::value
2224 || allocator_traits_type::is_always_equal::value) &&
2225 !dtl::is_version<allocator_type, 0>::value))
2226 {
2227 this->priv_swap(x, dtl::bool_<dtl::is_version<allocator_type, 0>::value>());
2228 }
2229
2230 #ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
2231
2232
2233
2234
2235
2236
2237
2238
2239 template<class OtherA>
2240 inline void swap(vector<T, OtherA, Options> & x
2241 , typename dtl::enable_if_and
2242 < void
2243 , dtl::is_version<typename real_allocator<T, OtherA>::type, 0>
2244 , dtl::is_different<typename real_allocator<T, OtherA>::type, allocator_type>
2245 >::type * = 0
2246 )
2247 { this->m_holder.deep_swap(x.m_holder); }
2248
2249 #endif
2250
2251
2252
2253
2254
2255
2256 inline void clear() BOOST_NOEXCEPT_OR_NOTHROW
2257 { this->priv_destroy_all(); }
2258
2259
2260
2261
2262 BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline friend bool operator==(const vector& x, const vector& y)
2263 { return x.size() == y.size() && ::boost::container::algo_equal(x.begin(), x.end(), y.begin()); }
2264
2265
2266
2267
2268 BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline friend bool operator!=(const vector& x, const vector& y)
2269 { return !(x == y); }
2270
2271
2272
2273
2274 BOOST_CONTAINER_ATTRIBUTE_NODISCARD friend bool operator<(const vector& x, const vector& y)
2275 { return boost::container::algo_lexicographical_compare(x.begin(), x.end(), y.begin(), y.end()); }
2276
2277
2278
2279
2280 BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline friend bool operator>(const vector& x, const vector& y)
2281 { return y < x; }
2282
2283
2284
2285
2286 BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline friend bool operator<=(const vector& x, const vector& y)
2287 { return !(y < x); }
2288
2289
2290
2291
2292 BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline friend bool operator>=(const vector& x, const vector& y)
2293 { return !(x < y); }
2294
2295
2296
2297
2298 inline friend void swap(vector& x, vector& y)
2299 BOOST_NOEXCEPT_IF(BOOST_NOEXCEPT(x.swap(y)))
2300 { x.swap(y); }
2301
2302 #ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
2303
2304
2305
2306
2307
2308
2309
2310
2311
2312 bool stable_reserve(size_type new_cap)
2313 {
2314 const size_type cp = this->capacity();
2315 return cp >= new_cap || (alloc_version::value == 2 && this->m_holder.try_expand_fwd(size_type(new_cap - cp)));
2316 }
2317
2318
2319 template<class BiDirPosConstIt, class BiDirValueIt>
2320 inline void insert_ordered_at(const size_type element_count, BiDirPosConstIt last_position_it, BiDirValueIt last_value_it)
2321 {
2322 typedef vector_insert_ordered_cursor<BiDirPosConstIt, BiDirValueIt> inserter_t;
2323 return this->priv_insert_ordered_at(element_count, inserter_t(last_position_it, last_value_it));
2324 }
2325
2326 template<class InputIt>
2327 inline void merge(InputIt first, InputIt last)
2328 { this->merge(first, last, value_less_t()); }
2329
2330 template<class InputIt, class Compare>
2331 inline void merge(InputIt first, InputIt last, Compare comp)
2332 {
2333 size_type const s = this->size();
2334 size_type const c = this->capacity();
2335 size_type n = 0;
2336 size_type const free_cap = c - s;
2337
2338 if(!dtl::is_input_iterator<InputIt>::value &&
2339 free_cap < (n = boost::container::iterator_udistance(first, last))){
2340 this->priv_merge_in_new_buffer(first, n, comp, alloc_version());
2341 }
2342 else{
2343 this->insert(this->cend(), first, last);
2344 T *const raw_beg = this->priv_raw_begin();
2345 T *const raw_end = this->priv_raw_end();
2346 T *const raw_pos = raw_beg + s;
2347 boost::movelib::adaptive_merge(raw_beg, raw_pos, raw_end, comp, raw_end, free_cap - n);
2348 }
2349 }
2350
2351 template<class InputIt>
2352 inline void merge_unique(InputIt first, InputIt last)
2353 { this->merge_unique(first, last, value_less_t()); }
2354
2355 template<class InputIt, class Compare>
2356 inline void merge_unique(InputIt first, InputIt last, Compare comp)
2357 {
2358 size_type const old_size = this->size();
2359 this->priv_set_difference_back(first, last, comp);
2360 T *const raw_beg = this->priv_raw_begin();
2361 T *const raw_end = this->priv_raw_end();
2362 T *raw_pos = raw_beg + old_size;
2363 boost::movelib::adaptive_merge(raw_beg, raw_pos, raw_end, comp, raw_end, this->capacity() - this->size());
2364 }
2365
2366 private:
2367 template<class PositionValue>
2368 void priv_insert_ordered_at(const size_type element_count, PositionValue position_value)
2369 {
2370 const size_type old_size_pos = this->size();
2371 this->reserve(old_size_pos + element_count);
2372 T* const begin_ptr = this->priv_raw_begin();
2373 size_type insertions_left = element_count;
2374 size_type prev_pos = old_size_pos;
2375 size_type old_hole_size = element_count;
2376
2377
2378
2379 typename value_traits::ArrayDestructor past_hole_values_destroyer
2380 (begin_ptr + old_size_pos + element_count, this->m_holder.alloc(), size_type(0u));
2381
2382
2383 while(insertions_left){
2384 --position_value;
2385 size_type const pos = position_value.get_pos();
2386 BOOST_ASSERT(pos != size_type(-1) && pos <= old_size_pos && pos <= prev_pos);
2387
2388
2389
2390 size_type new_hole_size = (pos != prev_pos)
2391 ? priv_insert_ordered_at_shift_range(pos, prev_pos, this->size(), insertions_left)
2392 : old_hole_size
2393 ;
2394 if(new_hole_size){
2395
2396 past_hole_values_destroyer.increment_size_backwards(prev_pos - pos);
2397
2398 allocator_traits_type::construct(this->m_holder.alloc(), begin_ptr + pos + insertions_left - 1, position_value.get_val());
2399 if(--new_hole_size){
2400
2401 past_hole_values_destroyer.increment_size_backwards(size_type(1u));
2402 }
2403 else{
2404
2405 past_hole_values_destroyer.release();
2406 this->m_holder.inc_stored_size(element_count);
2407 }
2408 }
2409 else{
2410 if(old_hole_size){
2411
2412 past_hole_values_destroyer.release();
2413 this->m_holder.inc_stored_size(element_count);
2414 }
2415
2416 begin_ptr[pos + insertions_left - 1] = position_value.get_val();
2417 }
2418 --insertions_left;
2419 old_hole_size = new_hole_size;
2420 prev_pos = pos;
2421 }
2422 }
2423
2424 template<class InputIt, class Compare>
2425 void priv_set_difference_back(InputIt first1, InputIt last1, Compare comp)
2426 {
2427 T * old_first2 = this->priv_raw_begin();
2428 T * first2 = old_first2;
2429 T * last2 = this->priv_raw_end();
2430
2431 while (first1 != last1) {
2432 if (first2 == last2){
2433 this->insert(this->cend(), first1, last1);
2434 return;
2435 }
2436
2437 if (comp(*first1, *first2)) {
2438 this->emplace_back(*first1);
2439 T * const raw_begin = this->priv_raw_begin();
2440 if(old_first2 != raw_begin)
2441 {
2442
2443 first2 = raw_begin + (first2 - old_first2);
2444 last2 = raw_begin + (last2 - old_first2);
2445 old_first2 = raw_begin;
2446 }
2447 ++first1;
2448 }
2449 else {
2450 if (!comp(*first2, *first1)) {
2451 ++first1;
2452 }
2453 ++first2;
2454 }
2455 }
2456 }
2457
2458 template<class FwdIt, class Compare>
2459 inline void priv_merge_in_new_buffer(FwdIt, size_type, Compare, version_0)
2460 {
2461 alloc_holder_t::on_capacity_overflow();
2462 }
2463
2464 template<class FwdIt, class Compare, class Version>
2465 void priv_merge_in_new_buffer(FwdIt first, size_type n, Compare comp, Version)
2466 {
2467 size_type const new_size = this->size() + n;
2468 size_type new_cap = new_size;
2469 pointer p = pointer();
2470 pointer const new_storage = this->m_holder.allocation_command(allocate_new, new_size, new_cap, p);
2471
2472 BOOST_ASSERT((new_cap >= this->size() ) && (new_cap - this->size()) >= n);
2473 allocator_type &a = this->m_holder.alloc();
2474 typename value_traits::ArrayDeallocator new_buffer_deallocator(new_storage, a, new_cap);
2475 typename value_traits::ArrayDestructor new_values_destroyer(new_storage, a, 0u);
2476 T* pbeg = this->priv_raw_begin();
2477 size_type const old_size = this->size();
2478 T* const pend = pbeg + old_size;
2479 T* d_first = boost::movelib::to_raw_pointer(new_storage);
2480 size_type added = n;
2481
2482 while(1){
2483 if(!n) {
2484 ::boost::container::uninitialized_move_alloc(this->m_holder.alloc(), pbeg, pend, d_first);
2485 break;
2486 }
2487 else if(pbeg == pend) {
2488 ::boost::container::uninitialized_move_alloc_n(this->m_holder.alloc(), first, n, d_first);
2489 break;
2490 }
2491
2492 else if(comp(*first, *pbeg)) {
2493 allocator_traits_type::construct( this->m_holder.alloc(), d_first, *first );
2494 new_values_destroyer.increment_size(1u);
2495 ++first;
2496 --n;
2497 ++d_first;
2498 }
2499 else{
2500 allocator_traits_type::construct( this->m_holder.alloc(), d_first, boost::move(*pbeg) );
2501 new_values_destroyer.increment_size(1u);
2502 ++pbeg;
2503 ++d_first;
2504 }
2505 }
2506
2507
2508 pointer const old_p = this->m_holder.start();
2509 size_type const old_cap = this->m_holder.capacity();
2510 boost::container::destroy_alloc_n(a, boost::movelib::to_raw_pointer(old_p), old_size);
2511 if (old_cap > 0) {
2512 this->m_holder.deallocate(old_p, old_cap);
2513 }
2514 m_holder.set_stored_size(old_size + added);
2515 this->m_holder.start(new_storage);
2516 this->m_holder.capacity(new_cap);
2517 new_buffer_deallocator.release();
2518 new_values_destroyer.release();
2519 }
2520
2521 inline bool room_enough() const
2522 { return this->m_holder.m_size != this->m_holder.capacity(); }
2523
2524 inline pointer back_ptr() const
2525 { return this->m_holder.start() + difference_type(this->m_holder.m_size); }
2526
2527 inline size_type priv_index_of(pointer p) const
2528 {
2529 BOOST_ASSERT(this->m_holder.start() <= p);
2530 BOOST_ASSERT(p <= (this->m_holder.start()+difference_type(this->size())));
2531 return static_cast<size_type>(p - this->m_holder.start());
2532 }
2533
2534 template<class OtherA>
2535 void priv_move_assign(BOOST_RV_REF_BEG vector<T, OtherA, Options> BOOST_RV_REF_END x
2536 , typename dtl::enable_if_c
2537 < dtl::is_version<typename real_allocator<T, OtherA>::type, 0>::value >::type * = 0)
2538 {
2539 if(!dtl::is_same<typename real_allocator<T, OtherA>::type, allocator_type>::value &&
2540 this->capacity() < x.size()){
2541 alloc_holder_t::on_capacity_overflow();
2542 }
2543 T* const this_start = this->priv_raw_begin();
2544 T* const other_start = x.priv_raw_begin();
2545 const size_type this_sz = m_holder.m_size;
2546 const size_type other_sz = static_cast<size_type>(x.m_holder.m_size);
2547 boost::container::move_assign_range_alloc_n(this->m_holder.alloc(), other_start, other_sz, this_start, this_sz);
2548 m_holder.set_stored_size(other_sz);
2549
2550
2551 x.clear();
2552 }
2553
2554 template<class OtherA>
2555 void priv_move_assign_steal_or_assign(BOOST_RV_REF_BEG vector<T, OtherA, Options> BOOST_RV_REF_END x, dtl::true_type )
2556 {
2557 this->clear();
2558 if (BOOST_LIKELY(!!this->m_holder.m_start))
2559 this->m_holder.deallocate(this->m_holder.m_start, this->m_holder.m_capacity);
2560 this->m_holder.steal_resources(x.m_holder);
2561 }
2562
2563 template<class OtherA>
2564 void priv_move_assign_steal_or_assign(BOOST_RV_REF_BEG vector<T, OtherA, Options> BOOST_RV_REF_END x, dtl::false_type )
2565 {
2566 const bool propagate_alloc = allocator_traits_type::propagate_on_container_move_assignment::value;
2567 allocator_type& this_alloc = this->m_holder.alloc();
2568 allocator_type& x_alloc = x.m_holder.alloc();
2569
2570
2571
2572 const bool is_buffer_propagable_from_x = is_propagable_from<propagate_alloc>(x_alloc, x.m_holder.start(), this_alloc);
2573
2574 if (is_buffer_propagable_from_x) {
2575 this->priv_move_assign_steal_or_assign(boost::move(x), dtl::true_type());
2576 }
2577
2578
2579 else {
2580 this->assign( boost::make_move_iterator(boost::movelib::iterator_to_raw_pointer(x.begin()))
2581 , boost::make_move_iterator(boost::movelib::iterator_to_raw_pointer(x.end())) );
2582 x.clear();
2583 }
2584 }
2585
2586 template<class OtherA>
2587 void priv_move_assign(BOOST_RV_REF_BEG vector<T, OtherA, Options> BOOST_RV_REF_END x
2588 , typename dtl::disable_if_or
2589 < void
2590 , dtl::is_version<typename real_allocator<T, OtherA>::type, 0>
2591 , dtl::is_different<typename real_allocator<T, OtherA>::type, allocator_type>
2592 >::type * = 0)
2593 {
2594
2595
2596 BOOST_ASSERT(this != &x || x.size() == 0);
2597 const bool alloc_is_always_equal = allocator_traits_type::is_always_equal::value;
2598 const bool propagate_alloc = allocator_traits_type::propagate_on_container_move_assignment::value;
2599 const bool partially_propagable_alloc = allocator_traits_type::is_partially_propagable::value;
2600 const bool data_can_be_always_be_stolen = alloc_is_always_equal || (propagate_alloc && !partially_propagable_alloc);
2601
2602 this->priv_move_assign_steal_or_assign(boost::move(x), dtl::bool_<data_can_be_always_be_stolen>());
2603
2604
2605 allocator_type& this_alloc = this->m_holder.alloc();
2606 allocator_type& x_alloc = x.m_holder.alloc();
2607 dtl::move_alloc(this_alloc, x_alloc, dtl::bool_<propagate_alloc>());
2608 }
2609
2610 template<class OtherA>
2611 void priv_copy_assign(const vector<T, OtherA, Options> &x
2612 , typename dtl::enable_if_c
2613 < dtl::is_version<typename real_allocator<T, OtherA>::type, 0>::value >::type * = 0)
2614 {
2615 if(!dtl::is_same<typename real_allocator<T, OtherA>::type, allocator_type>::value &&
2616 this->capacity() < x.size()){
2617 alloc_holder_t::on_capacity_overflow();
2618 }
2619 T* const this_start = this->priv_raw_begin();
2620 T* const other_start = x.priv_raw_begin();
2621 const size_type this_sz = m_holder.m_size;
2622 const size_type other_sz = static_cast<size_type>(x.m_holder.m_size);
2623 boost::container::copy_assign_range_alloc_n(this->m_holder.alloc(), other_start, other_sz, this_start, this_sz);
2624 m_holder.set_stored_size(other_sz);
2625 }
2626
2627 template<class OtherA>
2628 typename dtl::disable_if_or
2629 < void
2630 , dtl::is_version<typename real_allocator<T, OtherA>::type, 0>
2631 , dtl::is_different<typename real_allocator<T, OtherA>::type, allocator_type>
2632 >::type
2633 priv_copy_assign(const vector<T, OtherA, Options> &x)
2634 {
2635 allocator_type &this_alloc = this->m_holder.alloc();
2636 const allocator_type &x_alloc = x.m_holder.alloc();
2637 dtl::bool_<allocator_traits_type::
2638 propagate_on_container_copy_assignment::value> flag;
2639 if(flag && this_alloc != x_alloc){
2640 this->clear();
2641 this->shrink_to_fit();
2642 }
2643 dtl::assign_alloc(this_alloc, x_alloc, flag);
2644 this->assign( x.priv_raw_begin(), x.priv_raw_end() );
2645 }
2646
2647 template<class Vector>
2648 inline void priv_swap(Vector &x, dtl::true_type)
2649 { this->m_holder.deep_swap(x.m_holder); }
2650
2651 template<class Vector>
2652 void priv_swap(Vector &x, dtl::false_type)
2653 {
2654 BOOST_ASSERT(allocator_traits_type::propagate_on_container_swap::value ||
2655 allocator_traits_type::is_always_equal::value ||
2656 this->get_stored_allocator() == x.get_stored_allocator());
2657
2658 if (BOOST_UNLIKELY(&x == this)) {
2659 return;
2660 }
2661
2662
2663 this->m_holder.swap_resources(x.m_holder);
2664
2665 dtl::bool_<allocator_traits_type::propagate_on_container_swap::value> flag;
2666 dtl::swap_alloc(this->m_holder.alloc(), x.m_holder.alloc(), flag);
2667 }
2668
2669 protected:
2670 template<class Vector>
2671 void prot_swap_small(Vector &x, std::size_t internal_capacity)
2672 {
2673 if (BOOST_UNLIKELY(&x == this)){
2674 return;
2675 }
2676
2677 const bool propagate_alloc = allocator_traits_type::propagate_on_container_swap::value;
2678 if(are_swap_propagable<propagate_alloc>
2679 ( this->get_stored_allocator(), this->m_holder.start(), x.get_stored_allocator(), x.m_holder.start())){
2680 this->priv_swap(x, dtl::false_());
2681 return;
2682 }
2683
2684 allocator_type &th_al = this->get_stored_allocator();
2685 allocator_type &ot_al = x.get_stored_allocator();
2686
2687 const bool is_this_data_propagable = is_propagable_from<propagate_alloc>(th_al, this->data(), ot_al);
2688 const bool is_that_data_propagable = is_propagable_from<propagate_alloc>(ot_al, x.data(), th_al);
2689
2690 if(internal_capacity && (is_this_data_propagable || is_that_data_propagable)) {
2691
2692 vector& extmem = is_this_data_propagable ? *this : x;
2693 vector& intmem = is_this_data_propagable ? x : *this;
2694
2695
2696 pointer const orig_extdata = extmem.data();
2697 const size_type orig_extmem_size = extmem.size();
2698 const size_type orig_extmem_cap = extmem.capacity();
2699
2700
2701 extmem.m_holder.m_start = extmem.get_stored_allocator().internal_storage();
2702 extmem.m_holder.set_stored_size(0u);
2703 extmem.m_holder.set_stored_capacity(internal_capacity);
2704
2705 {
2706
2707 typename value_traits::ArrayDeallocator new_buffer_deallocator(orig_extdata, extmem.get_stored_allocator(), orig_extmem_cap);
2708 typename value_traits::ArrayDestructor new_values_destroyer(orig_extdata, extmem.get_stored_allocator(), orig_extmem_size);
2709
2710
2711 BOOST_ASSERT(extmem.capacity() >= intmem.size());
2712 ::boost::container::uninitialized_move_alloc_n
2713 (intmem.get_stored_allocator(), this->priv_raw_begin(), intmem.size(), extmem.priv_raw_begin());
2714
2715
2716 extmem.m_holder.set_stored_size(intmem.size());
2717
2718 new_buffer_deallocator.release();
2719 new_values_destroyer.release();
2720 }
2721
2722
2723 boost::container::destroy_alloc_n
2724 ( intmem.get_stored_allocator(), this->priv_raw_begin()
2725 , intmem.size());
2726
2727
2728 intmem.m_holder.m_start = orig_extdata;
2729 intmem.m_holder.set_stored_size(orig_extmem_size);
2730 intmem.m_holder.set_stored_capacity(orig_extmem_cap);
2731
2732
2733 dtl::swap_alloc(this->m_holder.alloc(), x.m_holder.alloc(), dtl::bool_<propagate_alloc>());
2734 }
2735 else {
2736 bool const t_smaller = this->size() < x.size();
2737 vector &sml = t_smaller ? *this : x;
2738 vector &big = t_smaller ? x : *this;
2739
2740
2741 size_type const common_elements = sml.size();
2742 for(size_type i = 0; i != common_elements; ++i){
2743 boost::adl_move_swap(sml[i], big[i]);
2744 }
2745
2746
2747 dtl::swap_alloc(this->m_holder.alloc(), x.m_holder.alloc(), dtl::bool_<propagate_alloc>());
2748
2749
2750 T *const raw_big_nth = boost::movelib::iterator_to_raw_pointer(big.nth(common_elements));
2751 sml.insert(sml.cend()
2752 , boost::make_move_iterator(raw_big_nth)
2753 , boost::make_move_iterator(boost::movelib::iterator_to_raw_pointer(big.end())));
2754
2755
2756 boost::container::destroy_alloc_n
2757 ( sml.get_stored_allocator(), raw_big_nth
2758 , std::size_t(big.m_holder.m_size - common_elements));
2759 big.m_holder.set_stored_size(common_elements);
2760 }
2761 }
2762 private:
2763 inline void priv_move_to_new_buffer(size_type, version_0)
2764 { alloc_holder_t::on_capacity_overflow(); }
2765
2766 inline dtl::insert_range_proxy<allocator_type, boost::move_iterator<T*> > priv_dummy_empty_proxy()
2767 {
2768 return dtl::insert_range_proxy<allocator_type, boost::move_iterator<T*> >
2769 (::boost::make_move_iterator((T *)0));
2770 }
2771
2772 inline void priv_move_to_new_buffer(size_type new_cap, version_1)
2773 {
2774
2775
2776 pointer const p = this->m_holder.allocate(new_cap);
2777 #ifdef BOOST_CONTAINER_VECTOR_ALLOC_STATS
2778 ++this->num_alloc;
2779 #endif
2780
2781 this->priv_insert_forward_range_new_allocation
2782 ( boost::movelib::to_raw_pointer(p), new_cap, this->priv_raw_end(), 0, this->priv_dummy_empty_proxy());
2783 }
2784
2785 void priv_move_to_new_buffer(size_type new_cap, version_2)
2786 {
2787
2788
2789 bool same_buffer_start;
2790 size_type real_cap = 0;
2791 pointer reuse(this->m_holder.start());
2792 pointer const ret(this->m_holder.allocation_command(allocate_new | expand_fwd | expand_bwd, new_cap, real_cap = new_cap, reuse));
2793
2794
2795 same_buffer_start = reuse && this->m_holder.start() == ret;
2796 if(same_buffer_start){
2797 #ifdef BOOST_CONTAINER_VECTOR_ALLOC_STATS
2798 ++this->num_expand_fwd;
2799 #endif
2800 this->m_holder.capacity(real_cap);
2801 }
2802 else{
2803 T * const new_mem = boost::movelib::to_raw_pointer(ret);
2804 T * const ins_pos = this->priv_raw_end();
2805 if(reuse){
2806 #ifdef BOOST_CONTAINER_VECTOR_ALLOC_STATS
2807 ++this->num_expand_bwd;
2808 #endif
2809 this->priv_insert_forward_range_expand_backwards
2810 ( new_mem, real_cap, ins_pos, 0, this->priv_dummy_empty_proxy());
2811 }
2812 else{
2813 #ifdef BOOST_CONTAINER_VECTOR_ALLOC_STATS
2814 ++this->num_alloc;
2815 #endif
2816 this->priv_insert_forward_range_new_allocation
2817 ( new_mem, real_cap, ins_pos, 0, this->priv_dummy_empty_proxy());
2818 }
2819 }
2820 }
2821
2822 void priv_destroy_last_n(const size_type n) BOOST_NOEXCEPT_OR_NOTHROW
2823 {
2824 BOOST_ASSERT(n <= this->m_holder.m_size);
2825 boost::container::destroy_alloc_n(this->get_stored_allocator(), this->priv_raw_end() - n, n);
2826 this->m_holder.dec_stored_size(n);
2827 }
2828
2829 template<class InpIt>
2830 void priv_uninitialized_construct_at_end(InpIt first, InpIt last)
2831 {
2832 T* const old_end_pos = this->priv_raw_end();
2833 T* const new_end_pos = boost::container::uninitialized_copy_alloc(this->m_holder.alloc(), first, last, old_end_pos);
2834 this->m_holder.inc_stored_size(static_cast<size_type>(new_end_pos - old_end_pos));
2835 }
2836
2837 void priv_destroy_all() BOOST_NOEXCEPT_OR_NOTHROW
2838 {
2839 boost::container::destroy_alloc_n
2840 (this->get_stored_allocator(), this->priv_raw_begin(), this->m_holder.m_size);
2841 this->m_holder.m_size = 0;
2842 }
2843
2844 template<class U>
2845 inline iterator priv_insert(const const_iterator &p, BOOST_FWD_REF(U) u)
2846 {
2847 return this->emplace(p, ::boost::forward<U>(u));
2848 }
2849
2850 template <class U>
2851 inline void priv_push_back(BOOST_FWD_REF(U) u)
2852 {
2853 this->emplace_back(::boost::forward<U>(u));
2854 }
2855
2856
2857 inline void priv_push_back(::boost::move_detail::nat)
2858 {}
2859
2860 inline iterator priv_insert(const_iterator, ::boost::move_detail::nat)
2861 { return iterator(); }
2862
2863 inline dtl::insert_n_copies_proxy<allocator_type> priv_resize_proxy(const T &x)
2864 { return dtl::insert_n_copies_proxy<allocator_type>(x); }
2865
2866 inline dtl::insert_default_initialized_n_proxy<allocator_type> priv_resize_proxy(default_init_t)
2867 { return dtl::insert_default_initialized_n_proxy<allocator_type>(); }
2868
2869 inline dtl::insert_value_initialized_n_proxy<allocator_type> priv_resize_proxy(value_init_t)
2870 { return dtl::insert_value_initialized_n_proxy<allocator_type>(); }
2871
2872 protected:
2873 void prot_shrink_to_fit_small(pointer const small_buffer, const size_type small_capacity)
2874 {
2875 const size_type cp = this->m_holder.capacity();
2876 if (cp && this->m_holder.m_start != small_buffer) {
2877 const size_type sz = this->size();
2878 if (!sz) {
2879 if (BOOST_LIKELY(!!this->m_holder.m_start))
2880 this->m_holder.deallocate(this->m_holder.m_start, cp);
2881 this->m_holder.m_start = small_buffer;
2882 this->m_holder.set_stored_capacity(small_capacity);
2883 }
2884 else if(sz <= small_capacity) {
2885 T *const oldbuf = boost::movelib::to_raw_pointer(this->m_holder.m_start);
2886 ::boost::container::uninitialized_move_alloc_n
2887 ( this->get_stored_allocator()
2888 , oldbuf
2889 , sz
2890 , boost::movelib::to_raw_pointer(small_buffer)
2891 );
2892 boost::container::destroy_alloc_n(this->get_stored_allocator(), oldbuf, sz);
2893
2894 if (BOOST_LIKELY(!!this->m_holder.m_start))
2895 this->m_holder.deallocate(this->m_holder.m_start, cp);
2896
2897 this->m_holder.m_start = small_buffer;
2898 this->m_holder.set_stored_capacity(small_capacity);
2899 }
2900 else if (sz < cp) {
2901 this->priv_move_to_new_buffer(sz, alloc_version());
2902 }
2903 }
2904 }
2905
2906 private:
2907 inline void priv_shrink_to_fit(version_0) BOOST_NOEXCEPT_OR_NOTHROW
2908 {}
2909
2910 void priv_shrink_to_fit(version_1)
2911 {
2912 const size_type cp = this->m_holder.capacity();
2913 if(cp){
2914 const size_type sz = this->size();
2915 if(!sz){
2916 if(BOOST_LIKELY(!!this->m_holder.m_start))
2917 this->m_holder.deallocate(this->m_holder.m_start, cp);
2918 this->m_holder.m_start = pointer();
2919 this->m_holder.m_capacity = 0;
2920 }
2921 else if(sz < cp){
2922 this->priv_move_to_new_buffer(sz, alloc_version());
2923 }
2924 }
2925 }
2926
2927 void priv_shrink_to_fit(version_2) BOOST_NOEXCEPT_OR_NOTHROW
2928 {
2929 const size_type cp = this->m_holder.capacity();
2930 if(cp){
2931 const size_type sz = this->size();
2932 if(!sz){
2933 if(BOOST_LIKELY(!!this->m_holder.m_start))
2934 this->m_holder.deallocate(this->m_holder.m_start, cp);
2935 this->m_holder.m_start = pointer();
2936 this->m_holder.m_capacity = 0;
2937 }
2938 else{
2939 size_type received_size = sz;
2940 pointer reuse(this->m_holder.start());
2941 if(this->m_holder.allocation_command
2942 (shrink_in_place | nothrow_allocation, cp, received_size, reuse)){
2943 this->m_holder.capacity(received_size);
2944 #ifdef BOOST_CONTAINER_VECTOR_ALLOC_STATS
2945 ++this->num_shrink;
2946 #endif
2947 }
2948 }
2949 }
2950 }
2951
2952 #ifdef _MSC_VER
2953 #pragma warning (push)
2954 #pragma warning(disable: 4702)
2955 #endif
2956 template <class InsertionProxy>
2957 inline iterator priv_insert_forward_range_no_capacity
2958 (T * const, const size_type, const InsertionProxy , version_0)
2959 {
2960 return alloc_holder_t::on_capacity_overflow(), iterator();
2961 }
2962 #ifdef _MSC_VER
2963 #pragma warning (pop)
2964 #endif
2965
2966 template <class InsertionProxy>
2967 BOOST_CONTAINER_NOINLINE iterator priv_insert_forward_range_no_capacity
2968 (T *const raw_pos, const size_type n, const InsertionProxy insert_range_proxy, version_1)
2969 {
2970
2971 const size_type n_pos = static_cast<size_type>(raw_pos - this->priv_raw_begin());
2972
2973 const size_type new_cap = this->m_holder.template next_capacity<growth_factor_type>(n);
2974
2975 T * const new_buf = boost::movelib::to_raw_pointer(this->m_holder.allocate(new_cap));
2976 #ifdef BOOST_CONTAINER_VECTOR_ALLOC_STATS
2977 ++this->num_alloc;
2978 #endif
2979 this->priv_insert_forward_range_new_allocation(new_buf, new_cap, raw_pos, n, insert_range_proxy);
2980 return iterator(this->m_holder.start() + difference_type(n_pos));
2981 }
2982
2983 template <class InsertionProxy>
2984 BOOST_CONTAINER_NOINLINE iterator priv_insert_forward_range_no_capacity
2985 (T *const raw_pos, const size_type n, const InsertionProxy insert_range_proxy, version_2)
2986 {
2987
2988 const size_type n_pos = size_type(raw_pos - this->priv_raw_begin());
2989
2990
2991
2992 size_type real_cap = this->m_holder.template next_capacity<growth_factor_type>(n);
2993 pointer reuse(this->m_holder.start());
2994 pointer const ret (this->m_holder.allocation_command
2995 (allocate_new | expand_fwd | expand_bwd, size_type(this->m_holder.m_size + n), real_cap, reuse));
2996
2997
2998 if(reuse){
2999
3000 if(this->m_holder.start() == ret){
3001 #ifdef BOOST_CONTAINER_VECTOR_ALLOC_STATS
3002 ++this->num_expand_fwd;
3003 #endif
3004 this->m_holder.capacity(real_cap);
3005
3006 this->priv_insert_forward_range_expand_forward
3007 (raw_pos, n, insert_range_proxy, dtl::bool_<dtl::is_single_value_proxy<InsertionProxy>::value>());
3008 }
3009
3010 else{
3011 #ifdef BOOST_CONTAINER_VECTOR_ALLOC_STATS
3012 ++this->num_expand_bwd;
3013 #endif
3014 this->priv_insert_forward_range_expand_backwards
3015 (boost::movelib::to_raw_pointer(ret), real_cap, raw_pos, n, insert_range_proxy);
3016 }
3017 }
3018
3019 else{
3020 #ifdef BOOST_CONTAINER_VECTOR_ALLOC_STATS
3021 ++this->num_alloc;
3022 #endif
3023 this->priv_insert_forward_range_new_allocation
3024 ( boost::movelib::to_raw_pointer(ret), real_cap, raw_pos, n, insert_range_proxy);
3025 }
3026
3027 return iterator(this->m_holder.start() + (difference_type)(n_pos));
3028 }
3029
3030 template <class InsertionProxy>
3031 inline iterator priv_insert_forward_range
3032 (const pointer &pos, const size_type n, const InsertionProxy insert_range_proxy)
3033 {
3034 BOOST_ASSERT(this->m_holder.capacity() >= this->m_holder.m_size);
3035 T *const p = boost::movelib::to_raw_pointer(pos);
3036
3037 if (BOOST_LIKELY(n <= (this->m_holder.capacity() - this->m_holder.m_size))){
3038
3039 this->priv_insert_forward_range_expand_forward
3040 (p, n, insert_range_proxy, dtl::bool_<dtl::is_single_value_proxy<InsertionProxy>::value>());
3041 return iterator(pos);
3042 }
3043 else{
3044 return this->priv_insert_forward_range_no_capacity(p, n, insert_range_proxy, alloc_version());
3045 }
3046 }
3047
3048 template <class U>
3049 void priv_resize(const size_type new_size, const U &u, version_0)
3050 {
3051 const size_type sz = this->m_holder.m_size;
3052 if (new_size > this->capacity()){
3053
3054 alloc_holder_t::on_capacity_overflow();
3055 }
3056 else if (new_size < sz){
3057
3058 this->priv_destroy_last_n(sz - new_size);
3059 }
3060 else{
3061 T* const old_finish = this->priv_raw_end();
3062 this->priv_resize_proxy(u).uninitialized_copy_n_and_update(this->m_holder.alloc(), old_finish, new_size - sz);
3063 this->m_holder.set_stored_size(new_size);
3064 }
3065 }
3066
3067 template <class U, class AllocVersion>
3068 void priv_resize(const size_type new_size, const U &u, AllocVersion)
3069 {
3070 const size_type sz = this->m_holder.m_size;
3071 if (new_size < sz){
3072
3073 this->priv_destroy_last_n(size_type(sz - new_size));
3074 }
3075 else {
3076 this->priv_insert_forward_range(this->back_ptr(), size_type(new_size - sz), this->priv_resize_proxy(u));
3077 }
3078 }
3079
3080
3081
3082
3083
3084
3085
3086
3087
3088
3089
3090
3091
3092
3093
3094
3095
3096
3097
3098
3099
3100
3101
3102
3103
3104
3105
3106
3107
3108
3109
3110
3111
3112
3113
3114
3115
3116
3117
3118
3119
3120
3121
3122
3123
3124
3125
3126
3127
3128
3129
3130
3131 size_type priv_insert_ordered_at_shift_range
3132 (size_type first_pos, size_type last_pos, size_type limit_pos, size_type shift_count)
3133 {
3134 BOOST_ASSERT(first_pos <= last_pos);
3135 BOOST_ASSERT(last_pos <= limit_pos);
3136
3137 T* const begin_ptr = this->priv_raw_begin();
3138 T* const first_ptr = begin_ptr + first_pos;
3139 T* const last_ptr = begin_ptr + last_pos;
3140
3141 size_type hole_size = 0;
3142
3143 if((last_pos + shift_count) <= limit_pos){
3144
3145 boost::container::move_backward(first_ptr, last_ptr, last_ptr + shift_count);
3146 }
3147
3148 else if((first_pos + shift_count) >= limit_pos){
3149
3150 ::boost::container::uninitialized_move_alloc
3151 (this->m_holder.alloc(), first_ptr, last_ptr, first_ptr + shift_count);
3152
3153
3154 hole_size = static_cast<size_type>(first_pos + shift_count - limit_pos);
3155 }
3156
3157 else{
3158
3159 T* const limit_ptr = begin_ptr + limit_pos;
3160 T* const boundary_ptr = limit_ptr - shift_count;
3161 ::boost::container::uninitialized_move_alloc(this->m_holder.alloc(), boundary_ptr, last_ptr, limit_ptr);
3162
3163 boost::container::move_backward(first_ptr, boundary_ptr, limit_ptr);
3164 }
3165 return hole_size;
3166 }
3167
3168 private:
3169 inline T *priv_raw_begin() const
3170 { return boost::movelib::to_raw_pointer(m_holder.start()); }
3171
3172 inline T* priv_raw_end() const
3173 { return this->priv_raw_begin() + this->m_holder.m_size; }
3174
3175 template <class InsertionProxy>
3176 inline void priv_insert_forward_range_expand_forward
3177 (T* const raw_pos, const size_type, InsertionProxy insert_range_proxy, dtl::true_type)
3178 {
3179 BOOST_ASSERT(this->room_enough());
3180
3181 T* const old_finish = this->priv_raw_end();
3182 allocator_type & a = this->m_holder.alloc();
3183
3184 if (old_finish == raw_pos){
3185 insert_range_proxy.uninitialized_copy_n_and_update(a, old_finish, 1);
3186 ++this->m_holder.m_size;
3187 }
3188 else{
3189
3190
3191 T * const before_old_finish = old_finish-1;
3192
3193 allocator_traits_type::construct(a, old_finish, ::boost::move(*before_old_finish));
3194 ++this->m_holder.m_size;
3195
3196 boost::container::move_backward(raw_pos, before_old_finish, old_finish);
3197
3198 insert_range_proxy.copy_n_and_update(a, raw_pos, 1);
3199 }
3200 }
3201
3202 template <class InsertionProxy>
3203 inline void priv_insert_forward_range_expand_forward
3204 (T* const raw_pos, const size_type n, InsertionProxy insert_range_proxy, dtl::false_type)
3205 {
3206
3207 boost::container::expand_forward_and_insert_alloc
3208 ( this->m_holder.alloc(), raw_pos, this->priv_raw_end(), n, insert_range_proxy);
3209 this->m_holder.inc_stored_size(n);
3210 }
3211
3212 template <class InsertionProxy>
3213 void priv_insert_forward_range_new_allocation
3214 (T* const new_start, size_type new_cap, T* const pos, const size_type n, InsertionProxy insert_range_proxy)
3215 {
3216
3217 allocator_type &a = this->m_holder.alloc();
3218 T * const raw_old_buffer = this->priv_raw_begin();
3219
3220 typename value_traits::ArrayDeallocator new_buffer_deallocator(new_start, a, new_cap);
3221 boost::container::uninitialized_move_and_insert_alloc
3222 (a, raw_old_buffer, pos, this->priv_raw_end(), new_start, n, insert_range_proxy);
3223 new_buffer_deallocator.release();
3224
3225
3226 if(raw_old_buffer){
3227 BOOST_IF_CONSTEXPR(!has_trivial_destructor_after_move<value_type>::value)
3228 boost::container::destroy_alloc_n(a, raw_old_buffer, this->m_holder.m_size);
3229 this->m_holder.deallocate(this->m_holder.start(), this->m_holder.capacity());
3230 }
3231
3232 this->m_holder.start(new_start);
3233 this->m_holder.inc_stored_size(n);
3234 this->m_holder.capacity(new_cap);
3235 }
3236
3237 template <class InsertionProxy>
3238 void priv_insert_forward_range_expand_backwards
3239 (T* const new_start, const size_type new_capacity,
3240 T* const pos, const size_type n, InsertionProxy insert_range_proxy)
3241 {
3242 T* const old_start = this->priv_raw_begin();
3243 const size_type old_size = this->m_holder.m_size;
3244 allocator_type& a = this->m_holder.alloc();
3245
3246
3247 this->m_holder.start(new_start);
3248 this->m_holder.capacity(new_capacity);
3249 this->m_holder.m_size = 0;
3250
3251 expand_backward_forward_and_insert_alloc(old_start, old_size, new_start, pos, n, insert_range_proxy, a);
3252
3253
3254 this->m_holder.m_size = stored_size_type(old_size + n);
3255 }
3256
3257 void priv_throw_if_out_of_range(size_type n) const
3258 {
3259
3260 if (n >= this->size()){
3261 throw_out_of_range("vector::at out of range");
3262 }
3263 }
3264
3265 inline bool priv_in_range(const_iterator pos) const
3266 {
3267 return (this->begin() <= pos) && (pos < this->end());
3268 }
3269
3270 inline bool priv_in_range_or_end(const_iterator pos) const
3271 {
3272 return (this->begin() <= pos) && (pos <= this->end());
3273 }
3274
3275 #ifdef BOOST_CONTAINER_VECTOR_ALLOC_STATS
3276 public:
3277 unsigned int num_expand_fwd;
3278 unsigned int num_expand_bwd;
3279 unsigned int num_shrink;
3280 unsigned int num_alloc;
3281 void reset_alloc_stats()
3282 { num_expand_fwd = num_expand_bwd = num_alloc = 0, num_shrink = 0; }
3283 #endif
3284 #endif
3285 };
3286
3287 #ifndef BOOST_CONTAINER_NO_CXX17_CTAD
3288
3289 template <typename InputIterator>
3290 vector(InputIterator, InputIterator) ->
3291 vector<typename iter_value<InputIterator>::type>;
3292
3293 template <typename InputIterator, typename Allocator>
3294 vector(InputIterator, InputIterator, Allocator const&) ->
3295 vector<typename iter_value<InputIterator>::type, Allocator>;
3296
3297 #endif
3298
3299
3300 }}
3301
3302 #ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
3303
3304 namespace boost {
3305
3306
3307
3308 template <class T, class Allocator, class Options>
3309 struct has_trivial_destructor_after_move<boost::container::vector<T, Allocator, Options> >
3310 {
3311 typedef typename boost::container::vector<T, Allocator, Options>::allocator_type allocator_type;
3312 typedef typename ::boost::container::allocator_traits<allocator_type>::pointer pointer;
3313 BOOST_STATIC_CONSTEXPR bool value = ::boost::has_trivial_destructor_after_move<allocator_type>::value &&
3314 ::boost::has_trivial_destructor_after_move<pointer>::value;
3315 };
3316
3317 }
3318
3319
3320 #ifdef BOOST_GNU_STDLIB
3321
3322 BOOST_MOVE_STD_NS_BEG
3323
3324 template <class Pointer, bool IsConst>
3325 struct pointer_traits< boost::container::vec_iterator<Pointer, IsConst> >
3326 : public boost::intrusive::pointer_traits< boost::container::vec_iterator<Pointer, IsConst> >
3327 {};
3328
3329 BOOST_MOVE_STD_NS_END
3330
3331 #endif
3332
3333 #endif
3334
3335 #include <boost/container/detail/config_end.hpp>
3336
3337 #endif