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