annotate DEPENDENCIES/generic/include/boost/container/vector.hpp @ 133:4acb5d8d80b6 tip

Don't fail environmental check if README.md exists (but .txt and no-suffix don't)
author Chris Cannam
date Tue, 30 Jul 2019 12:25:44 +0100
parents c530137014c0
children
rev   line source
Chris@16 1 //////////////////////////////////////////////////////////////////////////////
Chris@16 2 //
Chris@101 3 // (C) Copyright Ion Gaztanaga 2005-2014. Distributed under the Boost
Chris@16 4 // Software License, Version 1.0. (See accompanying file
Chris@16 5 // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
Chris@16 6 //
Chris@16 7 // See http://www.boost.org/libs/container for documentation.
Chris@16 8 //
Chris@16 9 //////////////////////////////////////////////////////////////////////////////
Chris@16 10
Chris@16 11 #ifndef BOOST_CONTAINER_CONTAINER_VECTOR_HPP
Chris@16 12 #define BOOST_CONTAINER_CONTAINER_VECTOR_HPP
Chris@16 13
Chris@101 14 #ifndef BOOST_CONFIG_HPP
Chris@101 15 # include <boost/config.hpp>
Chris@101 16 #endif
Chris@101 17
Chris@101 18 #if defined(BOOST_HAS_PRAGMA_ONCE)
Chris@16 19 # pragma once
Chris@16 20 #endif
Chris@16 21
Chris@16 22 #include <boost/container/detail/config_begin.hpp>
Chris@16 23 #include <boost/container/detail/workaround.hpp>
Chris@101 24
Chris@101 25 // container
Chris@16 26 #include <boost/container/container_fwd.hpp>
Chris@101 27 #include <boost/container/allocator_traits.hpp>
Chris@101 28 #include <boost/container/new_allocator.hpp> //new_allocator
Chris@101 29 #include <boost/container/throw_exception.hpp>
Chris@101 30 // container detail
Chris@101 31 #include <boost/container/detail/advanced_insert_int.hpp>
Chris@101 32 #include <boost/container/detail/algorithm.hpp> //equal()
Chris@101 33 #include <boost/container/detail/alloc_helpers.hpp>
Chris@101 34 #include <boost/container/detail/allocation_type.hpp>
Chris@101 35 #include <boost/container/detail/copy_move_algo.hpp>
Chris@101 36 #include <boost/container/detail/destroyers.hpp>
Chris@101 37 #include <boost/container/detail/iterator.hpp>
Chris@101 38 #include <boost/container/detail/iterators.hpp>
Chris@101 39 #include <boost/container/detail/iterator_to_raw_pointer.hpp>
Chris@101 40 #include <boost/container/detail/mpl.hpp>
Chris@101 41 #include <boost/container/detail/next_capacity.hpp>
Chris@101 42 #include <boost/container/detail/to_raw_pointer.hpp>
Chris@101 43 #include <boost/container/detail/type_traits.hpp>
Chris@101 44 #include <boost/container/detail/version_type.hpp>
Chris@101 45 // intrusive
Chris@101 46 #include <boost/intrusive/pointer_traits.hpp>
Chris@101 47 // move
Chris@101 48 #include <boost/move/adl_move_swap.hpp>
Chris@101 49 #include <boost/move/iterator.hpp>
Chris@101 50 #include <boost/move/traits.hpp>
Chris@101 51 #include <boost/move/utility_core.hpp>
Chris@101 52 // move/detail
Chris@101 53 #if defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
Chris@101 54 #include <boost/move/detail/fwd_macros.hpp>
Chris@101 55 #endif
Chris@101 56 #include <boost/move/detail/move_helpers.hpp>
Chris@101 57 // other
Chris@101 58 #include <boost/core/no_exceptions_support.hpp>
Chris@101 59 #include <boost/assert.hpp>
Chris@16 60
Chris@101 61 //std
Chris@101 62 #if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
Chris@101 63 #include <initializer_list> //for std::initializer_list
Chris@101 64 #endif
Chris@16 65
Chris@16 66 namespace boost {
Chris@16 67 namespace container {
Chris@16 68
Chris@101 69 #ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
Chris@16 70
Chris@16 71 //#define BOOST_CONTAINER_VECTOR_ITERATOR_IS_POINTER
Chris@16 72
Chris@16 73 namespace container_detail {
Chris@16 74
Chris@16 75 #ifndef BOOST_CONTAINER_VECTOR_ITERATOR_IS_POINTER
Chris@16 76
Chris@16 77 template <class Pointer, bool IsConst>
Chris@16 78 class vec_iterator
Chris@16 79 {
Chris@16 80 public:
Chris@101 81 typedef std::random_access_iterator_tag iterator_category;
Chris@16 82 typedef typename boost::intrusive::pointer_traits<Pointer>::element_type value_type;
Chris@16 83 typedef typename boost::intrusive::pointer_traits<Pointer>::difference_type difference_type;
Chris@16 84 typedef typename if_c
Chris@16 85 < IsConst
Chris@16 86 , typename boost::intrusive::pointer_traits<Pointer>::template
Chris@16 87 rebind_pointer<const value_type>::type
Chris@16 88 , Pointer
Chris@16 89 >::type pointer;
Chris@101 90 typedef typename boost::intrusive::pointer_traits<pointer> ptr_traits;
Chris@101 91 typedef typename ptr_traits::reference reference;
Chris@16 92
Chris@101 93 #ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
Chris@16 94 private:
Chris@16 95 Pointer m_ptr;
Chris@16 96
Chris@16 97 public:
Chris@101 98 const Pointer &get_ptr() const BOOST_NOEXCEPT_OR_NOTHROW
Chris@16 99 { return m_ptr; }
Chris@16 100
Chris@101 101 Pointer &get_ptr() BOOST_NOEXCEPT_OR_NOTHROW
Chris@16 102 { return m_ptr; }
Chris@16 103
Chris@101 104 explicit vec_iterator(Pointer ptr) BOOST_NOEXCEPT_OR_NOTHROW
Chris@16 105 : m_ptr(ptr)
Chris@16 106 {}
Chris@101 107 #endif //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
Chris@16 108
Chris@16 109 public:
Chris@16 110
Chris@16 111 //Constructors
Chris@101 112 vec_iterator() BOOST_NOEXCEPT_OR_NOTHROW
Chris@101 113 : m_ptr() //Value initialization to achieve "null iterators" (N3644)
Chris@16 114 {}
Chris@16 115
Chris@101 116 vec_iterator(vec_iterator<Pointer, false> const& other) BOOST_NOEXCEPT_OR_NOTHROW
Chris@16 117 : m_ptr(other.get_ptr())
Chris@16 118 {}
Chris@16 119
Chris@16 120 //Pointer like operators
Chris@101 121 reference operator*() const BOOST_NOEXCEPT_OR_NOTHROW
Chris@16 122 { return *m_ptr; }
Chris@16 123
Chris@101 124 pointer operator->() const BOOST_NOEXCEPT_OR_NOTHROW
Chris@16 125 { return ::boost::intrusive::pointer_traits<pointer>::pointer_to(this->operator*()); }
Chris@16 126
Chris@101 127 reference operator[](difference_type off) const BOOST_NOEXCEPT_OR_NOTHROW
Chris@16 128 { return m_ptr[off]; }
Chris@16 129
Chris@16 130 //Increment / Decrement
Chris@101 131 vec_iterator& operator++() BOOST_NOEXCEPT_OR_NOTHROW
Chris@16 132 { ++m_ptr; return *this; }
Chris@16 133
Chris@101 134 vec_iterator operator++(int) BOOST_NOEXCEPT_OR_NOTHROW
Chris@16 135 { return vec_iterator(m_ptr++); }
Chris@16 136
Chris@101 137 vec_iterator& operator--() BOOST_NOEXCEPT_OR_NOTHROW
Chris@16 138 { --m_ptr; return *this; }
Chris@16 139
Chris@101 140 vec_iterator operator--(int) BOOST_NOEXCEPT_OR_NOTHROW
Chris@16 141 { return vec_iterator(m_ptr--); }
Chris@16 142
Chris@16 143 //Arithmetic
Chris@101 144 vec_iterator& operator+=(difference_type off) BOOST_NOEXCEPT_OR_NOTHROW
Chris@16 145 { m_ptr += off; return *this; }
Chris@16 146
Chris@101 147 vec_iterator& operator-=(difference_type off) BOOST_NOEXCEPT_OR_NOTHROW
Chris@16 148 { m_ptr -= off; return *this; }
Chris@16 149
Chris@101 150 friend vec_iterator operator+(const vec_iterator &x, difference_type off) BOOST_NOEXCEPT_OR_NOTHROW
Chris@16 151 { return vec_iterator(x.m_ptr+off); }
Chris@16 152
Chris@101 153 friend vec_iterator operator+(difference_type off, vec_iterator right) BOOST_NOEXCEPT_OR_NOTHROW
Chris@16 154 { right.m_ptr += off; return right; }
Chris@16 155
Chris@101 156 friend vec_iterator operator-(vec_iterator left, difference_type off) BOOST_NOEXCEPT_OR_NOTHROW
Chris@16 157 { left.m_ptr -= off; return left; }
Chris@16 158
Chris@101 159 friend difference_type operator-(const vec_iterator &left, const vec_iterator& right) BOOST_NOEXCEPT_OR_NOTHROW
Chris@16 160 { return left.m_ptr - right.m_ptr; }
Chris@16 161
Chris@16 162 //Comparison operators
Chris@101 163 friend bool operator== (const vec_iterator& l, const vec_iterator& r) BOOST_NOEXCEPT_OR_NOTHROW
Chris@16 164 { return l.m_ptr == r.m_ptr; }
Chris@16 165
Chris@101 166 friend bool operator!= (const vec_iterator& l, const vec_iterator& r) BOOST_NOEXCEPT_OR_NOTHROW
Chris@16 167 { return l.m_ptr != r.m_ptr; }
Chris@16 168
Chris@101 169 friend bool operator< (const vec_iterator& l, const vec_iterator& r) BOOST_NOEXCEPT_OR_NOTHROW
Chris@16 170 { return l.m_ptr < r.m_ptr; }
Chris@16 171
Chris@101 172 friend bool operator<= (const vec_iterator& l, const vec_iterator& r) BOOST_NOEXCEPT_OR_NOTHROW
Chris@16 173 { return l.m_ptr <= r.m_ptr; }
Chris@16 174
Chris@101 175 friend bool operator> (const vec_iterator& l, const vec_iterator& r) BOOST_NOEXCEPT_OR_NOTHROW
Chris@16 176 { return l.m_ptr > r.m_ptr; }
Chris@16 177
Chris@101 178 friend bool operator>= (const vec_iterator& l, const vec_iterator& r) BOOST_NOEXCEPT_OR_NOTHROW
Chris@16 179 { return l.m_ptr >= r.m_ptr; }
Chris@16 180 };
Chris@16 181
Chris@16 182 } //namespace container_detail {
Chris@16 183
Chris@16 184 template<class Pointer, bool IsConst>
Chris@101 185 const Pointer &vector_iterator_get_ptr(const container_detail::vec_iterator<Pointer, IsConst> &it) BOOST_NOEXCEPT_OR_NOTHROW
Chris@16 186 { return it.get_ptr(); }
Chris@16 187
Chris@16 188 template<class Pointer, bool IsConst>
Chris@101 189 Pointer &get_ptr(container_detail::vec_iterator<Pointer, IsConst> &it) BOOST_NOEXCEPT_OR_NOTHROW
Chris@16 190 { return it.get_ptr(); }
Chris@16 191
Chris@16 192 namespace container_detail {
Chris@16 193
Chris@16 194 #else //ifndef BOOST_CONTAINER_VECTOR_ITERATOR_IS_POINTER
Chris@16 195
Chris@16 196 template< class MaybeConstPointer
Chris@16 197 , bool ElementTypeIsConst
Chris@16 198 = is_const< typename boost::intrusive::pointer_traits<MaybeConstPointer>::element_type>::value >
Chris@16 199 struct vector_get_ptr_pointer_to_non_const
Chris@16 200 {
Chris@16 201 typedef MaybeConstPointer const_pointer;
Chris@16 202 typedef boost::intrusive::pointer_traits<const_pointer> pointer_traits_t;
Chris@16 203 typedef typename pointer_traits_t::element_type element_type;
Chris@16 204 typedef typename remove_const<element_type>::type non_const_element_type;
Chris@16 205 typedef typename pointer_traits_t
Chris@16 206 ::template rebind_pointer<non_const_element_type>::type return_type;
Chris@16 207
Chris@101 208 static return_type get_ptr(const const_pointer &ptr) BOOST_NOEXCEPT_OR_NOTHROW
Chris@16 209 { return boost::intrusive::pointer_traits<return_type>::const_cast_from(ptr); }
Chris@16 210 };
Chris@16 211
Chris@16 212 template<class Pointer>
Chris@16 213 struct vector_get_ptr_pointer_to_non_const<Pointer, false>
Chris@16 214 {
Chris@16 215 typedef const Pointer & return_type;
Chris@101 216 static return_type get_ptr(const Pointer &ptr) BOOST_NOEXCEPT_OR_NOTHROW
Chris@16 217 { return ptr; }
Chris@16 218 };
Chris@16 219
Chris@16 220 } //namespace container_detail {
Chris@16 221
Chris@16 222 template<class MaybeConstPointer>
Chris@16 223 typename container_detail::vector_get_ptr_pointer_to_non_const<MaybeConstPointer>::return_type
Chris@101 224 vector_iterator_get_ptr(const MaybeConstPointer &ptr) BOOST_NOEXCEPT_OR_NOTHROW
Chris@16 225 {
Chris@16 226 return container_detail::vector_get_ptr_pointer_to_non_const<MaybeConstPointer>::get_ptr(ptr);
Chris@16 227 }
Chris@16 228
Chris@16 229 namespace container_detail {
Chris@16 230
Chris@16 231 #endif //#ifndef BOOST_CONTAINER_VECTOR_ITERATOR_IS_POINTER
Chris@16 232
Chris@101 233 struct uninitialized_size_t {};
Chris@101 234 static const uninitialized_size_t uninitialized_size = uninitialized_size_t();
Chris@101 235
Chris@101 236 template <class T>
Chris@101 237 struct vector_value_traits_base
Chris@101 238 {
Chris@101 239 static const bool trivial_dctr = is_trivially_destructible<T>::value;
Chris@101 240 static const bool trivial_dctr_after_move = has_trivial_destructor_after_move<T>::value;
Chris@101 241 static const bool trivial_copy = is_trivially_copy_constructible<T>::value;
Chris@101 242 static const bool nothrow_copy = is_nothrow_copy_constructible<T>::value || trivial_copy;
Chris@101 243 static const bool trivial_assign = is_trivially_copy_assignable<T>::value;
Chris@101 244 static const bool nothrow_assign = is_nothrow_copy_assignable<T>::value || trivial_assign;
Chris@101 245 };
Chris@101 246
Chris@101 247
Chris@101 248 template <class Allocator>
Chris@16 249 struct vector_value_traits
Chris@101 250 : public vector_value_traits_base<typename Allocator::value_type>
Chris@16 251 {
Chris@101 252 typedef vector_value_traits_base<typename Allocator::value_type> base_t;
Chris@16 253 //This is the anti-exception array destructor
Chris@16 254 //to deallocate values already constructed
Chris@16 255 typedef typename container_detail::if_c
Chris@101 256 <base_t::trivial_dctr
Chris@16 257 ,container_detail::null_scoped_destructor_n<Allocator>
Chris@16 258 ,container_detail::scoped_destructor_n<Allocator>
Chris@16 259 >::type ArrayDestructor;
Chris@16 260 //This is the anti-exception array deallocator
Chris@101 261 typedef container_detail::scoped_array_deallocator<Allocator> ArrayDeallocator;
Chris@16 262 };
Chris@16 263
Chris@16 264 //!This struct deallocates and allocated memory
Chris@16 265 template < class Allocator
Chris@101 266 , class AllocatorVersion = typename container_detail::version<Allocator>::type
Chris@16 267 >
Chris@16 268 struct vector_alloc_holder
Chris@16 269 : public Allocator
Chris@16 270 {
Chris@16 271 private:
Chris@16 272 BOOST_MOVABLE_BUT_NOT_COPYABLE(vector_alloc_holder)
Chris@16 273
Chris@16 274 public:
Chris@101 275 typedef Allocator allocator_type;
Chris@16 276 typedef boost::container::allocator_traits<Allocator> allocator_traits_type;
Chris@16 277 typedef typename allocator_traits_type::pointer pointer;
Chris@16 278 typedef typename allocator_traits_type::size_type size_type;
Chris@16 279 typedef typename allocator_traits_type::value_type value_type;
Chris@16 280
Chris@101 281 static bool is_propagable_from(const allocator_type &from_alloc, pointer p, const allocator_type &to_alloc, bool const propagate_allocator)
Chris@101 282 {
Chris@101 283 (void)propagate_allocator; (void)p; (void)to_alloc; (void)from_alloc;
Chris@101 284 return (!allocator_traits_type::is_partially_propagable::value ||
Chris@101 285 !allocator_traits_type::storage_is_unpropagable(from_alloc, p)) &&
Chris@101 286 (propagate_allocator || allocator_traits_type::equal(from_alloc, to_alloc));
Chris@101 287 }
Chris@101 288
Chris@101 289 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)
Chris@101 290 {
Chris@101 291 (void)propagate_allocator; (void)l_p; (void)r_p; (void)l_a; (void)r_a;
Chris@101 292 return (!allocator_traits_type::is_partially_propagable::value ||
Chris@101 293 (!allocator_traits_type::storage_is_unpropagable(r_a, r_p) &&
Chris@101 294 !allocator_traits_type::storage_is_unpropagable(l_a, l_p))
Chris@101 295 ) && (propagate_allocator || allocator_traits_type::equal(l_a, r_a));
Chris@101 296 }
Chris@101 297
Chris@16 298 //Constructor, does not throw
Chris@16 299 vector_alloc_holder()
Chris@101 300 BOOST_NOEXCEPT_IF(container_detail::is_nothrow_default_constructible<Allocator>::value)
Chris@16 301 : Allocator(), m_start(), m_size(), m_capacity()
Chris@16 302 {}
Chris@16 303
Chris@16 304 //Constructor, does not throw
Chris@16 305 template<class AllocConvertible>
Chris@101 306 explicit vector_alloc_holder(BOOST_FWD_REF(AllocConvertible) a) BOOST_NOEXCEPT_OR_NOTHROW
Chris@16 307 : Allocator(boost::forward<AllocConvertible>(a)), m_start(), m_size(), m_capacity()
Chris@16 308 {}
Chris@16 309
Chris@16 310 //Constructor, does not throw
Chris@16 311 template<class AllocConvertible>
Chris@101 312 vector_alloc_holder(uninitialized_size_t, BOOST_FWD_REF(AllocConvertible) a, size_type initial_size)
Chris@16 313 : Allocator(boost::forward<AllocConvertible>(a))
Chris@16 314 , m_start()
Chris@16 315 , m_size(initial_size) //Size is initialized here so vector should only call uninitialized_xxx after this
Chris@16 316 , m_capacity()
Chris@16 317 {
Chris@16 318 if(initial_size){
Chris@101 319 pointer reuse = 0;
Chris@101 320 m_start = this->allocation_command(allocate_new, initial_size, m_capacity = initial_size, reuse);
Chris@16 321 }
Chris@16 322 }
Chris@16 323
Chris@16 324 //Constructor, does not throw
Chris@101 325 vector_alloc_holder(uninitialized_size_t, size_type initial_size)
Chris@16 326 : Allocator()
Chris@16 327 , m_start()
Chris@16 328 , m_size(initial_size) //Size is initialized here so vector should only call uninitialized_xxx after this
Chris@16 329 , m_capacity()
Chris@16 330 {
Chris@16 331 if(initial_size){
Chris@101 332 pointer reuse = 0;
Chris@101 333 m_start = this->allocation_command(allocate_new, initial_size, m_capacity = initial_size, reuse);
Chris@16 334 }
Chris@16 335 }
Chris@16 336
Chris@101 337 vector_alloc_holder(BOOST_RV_REF(vector_alloc_holder) holder) BOOST_NOEXCEPT_OR_NOTHROW
Chris@101 338 : Allocator(BOOST_MOVE_BASE(Allocator, holder))
Chris@16 339 , m_start(holder.m_start)
Chris@16 340 , m_size(holder.m_size)
Chris@16 341 , m_capacity(holder.m_capacity)
Chris@16 342 {
Chris@16 343 holder.m_start = pointer();
Chris@16 344 holder.m_size = holder.m_capacity = 0;
Chris@16 345 }
Chris@16 346
Chris@101 347 vector_alloc_holder(pointer p, size_type capacity, BOOST_RV_REF(vector_alloc_holder) holder)
Chris@101 348 : Allocator(BOOST_MOVE_BASE(Allocator, holder))
Chris@101 349 , m_start(p)
Chris@101 350 , m_size(holder.m_size)
Chris@101 351 , m_capacity(capacity)
Chris@16 352 {
Chris@101 353 allocator_type &this_alloc = this->alloc();
Chris@101 354 allocator_type &x_alloc = holder.alloc();
Chris@101 355 if(this->is_propagable_from(x_alloc, holder.start(), this_alloc, true)){
Chris@101 356 if(this->m_capacity){
Chris@101 357 this->alloc().deallocate(this->m_start, this->m_capacity);
Chris@101 358 }
Chris@101 359 m_start = holder.m_start;
Chris@101 360 m_capacity = holder.m_capacity;
Chris@101 361 holder.m_start = pointer();
Chris@101 362 holder.m_capacity = holder.m_size = 0;
Chris@101 363 }
Chris@101 364 else if(this->m_capacity < holder.m_size){
Chris@101 365 size_type const n = holder.m_size;
Chris@101 366 pointer reuse = pointer();
Chris@101 367 m_start = this->allocation_command(allocate_new, n, m_capacity = n, reuse);
Chris@101 368 #ifdef BOOST_CONTAINER_VECTOR_ALLOC_STATS
Chris@101 369 this->num_alloc += n != 0;
Chris@101 370 #endif
Chris@16 371 }
Chris@16 372 }
Chris@16 373
Chris@101 374 vector_alloc_holder(pointer p, size_type n)
Chris@101 375 BOOST_NOEXCEPT_IF(container_detail::is_nothrow_default_constructible<Allocator>::value)
Chris@101 376 : Allocator()
Chris@101 377 , m_start(p)
Chris@101 378 , m_size()
Chris@101 379 , m_capacity(n)
Chris@101 380 {}
Chris@16 381
Chris@101 382 template<class AllocFwd>
Chris@101 383 vector_alloc_holder(pointer p, size_type n, BOOST_FWD_REF(AllocFwd) a)
Chris@101 384 : Allocator(::boost::forward<AllocFwd>(a))
Chris@101 385 , m_start(p)
Chris@101 386 , m_size()
Chris@101 387 , m_capacity(n)
Chris@101 388 {}
Chris@101 389
Chris@101 390 ~vector_alloc_holder() BOOST_NOEXCEPT_OR_NOTHROW
Chris@16 391 {
Chris@16 392 if(this->m_capacity){
Chris@16 393 this->alloc().deallocate(this->m_start, this->m_capacity);
Chris@16 394 }
Chris@16 395 }
Chris@16 396
Chris@101 397 pointer allocation_command(boost::container::allocation_type command,
Chris@101 398 size_type limit_size, size_type &prefer_in_recvd_out_size, pointer &reuse)
Chris@16 399 {
Chris@101 400 typedef typename container_detail::version<Allocator>::type alloc_version;
Chris@101 401 return this->priv_allocation_command(alloc_version(), command, limit_size, prefer_in_recvd_out_size, reuse);
Chris@101 402 }
Chris@101 403
Chris@101 404 bool try_expand_fwd(size_type at_least)
Chris@101 405 {
Chris@101 406 //There is not enough memory, try to expand the old one
Chris@101 407 const size_type new_cap = this->capacity() + at_least;
Chris@101 408 size_type real_cap = new_cap;
Chris@101 409 pointer reuse = this->start();
Chris@101 410 bool const success = !!this->allocation_command(expand_fwd, new_cap, real_cap, reuse);
Chris@101 411 //Check for forward expansion
Chris@101 412 if(success){
Chris@101 413 #ifdef BOOST_CONTAINER_VECTOR_ALLOC_STATS
Chris@101 414 ++this->num_expand_fwd;
Chris@101 415 #endif
Chris@101 416 this->capacity(real_cap);
Chris@101 417 }
Chris@101 418 return success;
Chris@16 419 }
Chris@16 420
Chris@16 421 size_type next_capacity(size_type additional_objects) const
Chris@16 422 {
Chris@101 423 return next_capacity_calculator
Chris@101 424 <size_type, NextCapacityDouble //NextCapacity60Percent
Chris@101 425 >::get( allocator_traits_type::max_size(this->alloc())
Chris@101 426 , this->m_capacity, additional_objects );
Chris@16 427 }
Chris@16 428
Chris@16 429 pointer m_start;
Chris@16 430 size_type m_size;
Chris@16 431 size_type m_capacity;
Chris@16 432
Chris@101 433 void swap_resources(vector_alloc_holder &x) BOOST_NOEXCEPT_OR_NOTHROW
Chris@16 434 {
Chris@101 435 boost::adl_move_swap(this->m_start, x.m_start);
Chris@101 436 boost::adl_move_swap(this->m_size, x.m_size);
Chris@101 437 boost::adl_move_swap(this->m_capacity, x.m_capacity);
Chris@16 438 }
Chris@16 439
Chris@101 440 void steal_resources(vector_alloc_holder &x) BOOST_NOEXCEPT_OR_NOTHROW
Chris@16 441 {
Chris@16 442 this->m_start = x.m_start;
Chris@16 443 this->m_size = x.m_size;
Chris@16 444 this->m_capacity = x.m_capacity;
Chris@16 445 x.m_start = pointer();
Chris@16 446 x.m_size = x.m_capacity = 0;
Chris@16 447 }
Chris@16 448
Chris@101 449 Allocator &alloc() BOOST_NOEXCEPT_OR_NOTHROW
Chris@16 450 { return *this; }
Chris@16 451
Chris@101 452 const Allocator &alloc() const BOOST_NOEXCEPT_OR_NOTHROW
Chris@16 453 { return *this; }
Chris@16 454
Chris@101 455 const pointer &start() const BOOST_NOEXCEPT_OR_NOTHROW { return m_start; }
Chris@101 456 const size_type &capacity() const BOOST_NOEXCEPT_OR_NOTHROW { return m_capacity; }
Chris@101 457 void start(const pointer &p) BOOST_NOEXCEPT_OR_NOTHROW { m_start = p; }
Chris@101 458 void capacity(const size_type &c) BOOST_NOEXCEPT_OR_NOTHROW { m_capacity = c; }
Chris@101 459
Chris@101 460 private:
Chris@101 461 void priv_first_allocation(size_type cap)
Chris@101 462 {
Chris@101 463 if(cap){
Chris@101 464 pointer reuse = 0;
Chris@101 465 m_start = this->allocation_command(allocate_new, cap, cap, reuse);
Chris@101 466 m_capacity = cap;
Chris@101 467 #ifdef BOOST_CONTAINER_VECTOR_ALLOC_STATS
Chris@101 468 ++this->num_alloc;
Chris@101 469 #endif
Chris@101 470 }
Chris@101 471 }
Chris@101 472
Chris@101 473 pointer priv_allocation_command(version_1, boost::container::allocation_type command,
Chris@101 474 size_type ,
Chris@101 475 size_type &prefer_in_recvd_out_size,
Chris@101 476 pointer &reuse)
Chris@101 477 {
Chris@101 478 (void)command;
Chris@101 479 BOOST_ASSERT( (command & allocate_new));
Chris@101 480 BOOST_ASSERT(!(command & nothrow_allocation));
Chris@101 481 pointer const p = allocator_traits_type::allocate(this->alloc(), prefer_in_recvd_out_size, reuse);
Chris@101 482 reuse = pointer();
Chris@101 483 return p;
Chris@101 484 }
Chris@101 485
Chris@101 486 pointer priv_allocation_command(version_2, boost::container::allocation_type command,
Chris@101 487 size_type limit_size,
Chris@101 488 size_type &prefer_in_recvd_out_size,
Chris@101 489 pointer &reuse)
Chris@101 490 {
Chris@101 491 return this->alloc().allocation_command(command, limit_size, prefer_in_recvd_out_size, reuse);
Chris@101 492 }
Chris@16 493 };
Chris@16 494
Chris@16 495 //!This struct deallocates and allocated memory
Chris@16 496 template <class Allocator>
Chris@101 497 struct vector_alloc_holder<Allocator, version_0>
Chris@16 498 : public Allocator
Chris@16 499 {
Chris@16 500 private:
Chris@16 501 BOOST_MOVABLE_BUT_NOT_COPYABLE(vector_alloc_holder)
Chris@16 502
Chris@16 503 public:
Chris@16 504 typedef boost::container::allocator_traits<Allocator> allocator_traits_type;
Chris@16 505 typedef typename allocator_traits_type::pointer pointer;
Chris@16 506 typedef typename allocator_traits_type::size_type size_type;
Chris@16 507 typedef typename allocator_traits_type::value_type value_type;
Chris@16 508
Chris@16 509 template <class OtherAllocator, class OtherAllocatorVersion>
Chris@16 510 friend struct vector_alloc_holder;
Chris@16 511
Chris@16 512 //Constructor, does not throw
Chris@16 513 vector_alloc_holder()
Chris@101 514 BOOST_NOEXCEPT_IF(container_detail::is_nothrow_default_constructible<Allocator>::value)
Chris@16 515 : Allocator(), m_size()
Chris@16 516 {}
Chris@16 517
Chris@16 518 //Constructor, does not throw
Chris@16 519 template<class AllocConvertible>
Chris@101 520 explicit vector_alloc_holder(BOOST_FWD_REF(AllocConvertible) a) BOOST_NOEXCEPT_OR_NOTHROW
Chris@16 521 : Allocator(boost::forward<AllocConvertible>(a)), m_size()
Chris@16 522 {}
Chris@16 523
Chris@16 524 //Constructor, does not throw
Chris@16 525 template<class AllocConvertible>
Chris@101 526 vector_alloc_holder(uninitialized_size_t, BOOST_FWD_REF(AllocConvertible) a, size_type initial_size)
Chris@16 527 : Allocator(boost::forward<AllocConvertible>(a))
Chris@16 528 , m_size(initial_size) //Size is initialized here...
Chris@16 529 {
Chris@16 530 //... and capacity here, so vector, must call uninitialized_xxx in the derived constructor
Chris@101 531 this->priv_first_allocation(initial_size);
Chris@16 532 }
Chris@16 533
Chris@16 534 //Constructor, does not throw
Chris@101 535 vector_alloc_holder(uninitialized_size_t, size_type initial_size)
Chris@16 536 : Allocator()
Chris@16 537 , m_size(initial_size) //Size is initialized here...
Chris@16 538 {
Chris@16 539 //... and capacity here, so vector, must call uninitialized_xxx in the derived constructor
Chris@101 540 this->priv_first_allocation(initial_size);
Chris@16 541 }
Chris@16 542
Chris@16 543 vector_alloc_holder(BOOST_RV_REF(vector_alloc_holder) holder)
Chris@101 544 : Allocator(BOOST_MOVE_BASE(Allocator, holder))
Chris@16 545 , m_size(holder.m_size) //Size is initialized here so vector should only call uninitialized_xxx after this
Chris@16 546 {
Chris@16 547 ::boost::container::uninitialized_move_alloc_n
Chris@16 548 (this->alloc(), container_detail::to_raw_pointer(holder.start()), m_size, container_detail::to_raw_pointer(this->start()));
Chris@16 549 }
Chris@16 550
Chris@16 551 template<class OtherAllocator, class OtherAllocatorVersion>
Chris@16 552 vector_alloc_holder(BOOST_RV_REF_BEG vector_alloc_holder<OtherAllocator, OtherAllocatorVersion> BOOST_RV_REF_END holder)
Chris@16 553 : Allocator()
Chris@16 554 , m_size(holder.m_size) //Initialize it to m_size as first_allocation can only succeed or abort
Chris@16 555 {
Chris@16 556 //Different allocator type so we must check we have enough storage
Chris@16 557 const size_type n = holder.m_size;
Chris@101 558 this->priv_first_allocation(n);
Chris@16 559 ::boost::container::uninitialized_move_alloc_n
Chris@16 560 (this->alloc(), container_detail::to_raw_pointer(holder.start()), n, container_detail::to_raw_pointer(this->start()));
Chris@16 561 }
Chris@16 562
Chris@101 563 void priv_first_allocation(size_type cap)
Chris@16 564 {
Chris@16 565 if(cap > Allocator::internal_capacity){
Chris@16 566 throw_bad_alloc();
Chris@16 567 }
Chris@16 568 }
Chris@16 569
Chris@101 570 void deep_swap(vector_alloc_holder &x)
Chris@16 571 {
Chris@101 572 this->priv_deep_swap(x);
Chris@16 573 }
Chris@16 574
Chris@16 575 template<class OtherAllocator, class OtherAllocatorVersion>
Chris@101 576 void deep_swap(vector_alloc_holder<OtherAllocator, OtherAllocatorVersion> &x)
Chris@16 577 {
Chris@16 578 if(this->m_size > OtherAllocator::internal_capacity || x.m_size > Allocator::internal_capacity){
Chris@16 579 throw_bad_alloc();
Chris@16 580 }
Chris@101 581 this->priv_deep_swap(x);
Chris@16 582 }
Chris@16 583
Chris@101 584 void swap_resources(vector_alloc_holder &x) BOOST_NOEXCEPT_OR_NOTHROW
Chris@101 585 { //Containers with version 0 allocators can't be moved without moving elements one by one
Chris@16 586 throw_bad_alloc();
Chris@16 587 }
Chris@16 588
Chris@101 589
Chris@101 590 void steal_resources(vector_alloc_holder &)
Chris@101 591 { //Containers with version 0 allocators can't be moved without moving elements one by one
Chris@101 592 throw_bad_alloc();
Chris@101 593 }
Chris@101 594
Chris@101 595 Allocator &alloc() BOOST_NOEXCEPT_OR_NOTHROW
Chris@16 596 { return *this; }
Chris@16 597
Chris@101 598 const Allocator &alloc() const BOOST_NOEXCEPT_OR_NOTHROW
Chris@16 599 { return *this; }
Chris@16 600
Chris@101 601 bool try_expand_fwd(size_type at_least)
Chris@101 602 { return !at_least; }
Chris@101 603
Chris@101 604 pointer start() const BOOST_NOEXCEPT_OR_NOTHROW { return Allocator::internal_storage(); }
Chris@101 605 size_type capacity() const BOOST_NOEXCEPT_OR_NOTHROW { return Allocator::internal_capacity; }
Chris@16 606 size_type m_size;
Chris@16 607
Chris@16 608 private:
Chris@16 609
Chris@16 610 template<class OtherAllocator, class OtherAllocatorVersion>
Chris@101 611 void priv_deep_swap(vector_alloc_holder<OtherAllocator, OtherAllocatorVersion> &x)
Chris@16 612 {
Chris@101 613 const size_type MaxTmpStorage = sizeof(value_type)*Allocator::internal_capacity;
Chris@16 614 value_type *const first_this = container_detail::to_raw_pointer(this->start());
Chris@16 615 value_type *const first_x = container_detail::to_raw_pointer(x.start());
Chris@16 616
Chris@16 617 if(this->m_size < x.m_size){
Chris@16 618 boost::container::deep_swap_alloc_n<MaxTmpStorage>(this->alloc(), first_this, this->m_size, first_x, x.m_size);
Chris@16 619 }
Chris@16 620 else{
Chris@16 621 boost::container::deep_swap_alloc_n<MaxTmpStorage>(this->alloc(), first_x, x.m_size, first_this, this->m_size);
Chris@16 622 }
Chris@101 623 boost::adl_move_swap(this->m_size, x.m_size);
Chris@16 624 }
Chris@16 625 };
Chris@16 626
Chris@16 627 } //namespace container_detail {
Chris@16 628
Chris@101 629 #endif //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
Chris@16 630
Chris@16 631 //! A vector is a sequence that supports random access to elements, constant
Chris@16 632 //! time insertion and removal of elements at the end, and linear time insertion
Chris@16 633 //! and removal of elements at the beginning or in the middle. The number of
Chris@16 634 //! elements in a vector may vary dynamically; memory management is automatic.
Chris@101 635 //!
Chris@101 636 //! \tparam T The type of object that is stored in the vector
Chris@101 637 //! \tparam Allocator The allocator used for all internal memory management
Chris@101 638 template <class T, class Allocator BOOST_CONTAINER_DOCONLY(= new_allocator<T>) >
Chris@16 639 class vector
Chris@16 640 {
Chris@101 641 #ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
Chris@101 642
Chris@101 643 typedef typename container_detail::version<Allocator>::type alloc_version;
Chris@101 644 typedef boost::container::container_detail::vector_alloc_holder<Allocator> alloc_holder_t;
Chris@101 645 alloc_holder_t m_holder;
Chris@16 646 typedef allocator_traits<Allocator> allocator_traits_type;
Chris@16 647 template <class U, class UAllocator>
Chris@16 648 friend class vector;
Chris@16 649
Chris@101 650 typedef typename allocator_traits_type::pointer pointer_impl;
Chris@16 651 typedef container_detail::vec_iterator<pointer_impl, false> iterator_impl;
Chris@16 652 typedef container_detail::vec_iterator<pointer_impl, true > const_iterator_impl;
Chris@16 653
Chris@101 654 protected:
Chris@101 655 static bool is_propagable_from(const Allocator &from_alloc, pointer_impl p, const Allocator &to_alloc, bool const propagate_allocator)
Chris@101 656 { return alloc_holder_t::is_propagable_from(from_alloc, p, to_alloc, propagate_allocator); }
Chris@101 657
Chris@101 658 static bool are_swap_propagable( const Allocator &l_a, pointer_impl l_p
Chris@101 659 , const Allocator &r_a, pointer_impl r_p, bool const propagate_allocator)
Chris@101 660 { return alloc_holder_t::are_swap_propagable(l_a, l_p, r_a, r_p, propagate_allocator); }
Chris@101 661
Chris@101 662 #endif //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
Chris@16 663 public:
Chris@16 664 //////////////////////////////////////////////
Chris@16 665 //
Chris@16 666 // types
Chris@16 667 //
Chris@16 668 //////////////////////////////////////////////
Chris@16 669
Chris@16 670 typedef T value_type;
Chris@16 671 typedef typename ::boost::container::allocator_traits<Allocator>::pointer pointer;
Chris@16 672 typedef typename ::boost::container::allocator_traits<Allocator>::const_pointer const_pointer;
Chris@16 673 typedef typename ::boost::container::allocator_traits<Allocator>::reference reference;
Chris@16 674 typedef typename ::boost::container::allocator_traits<Allocator>::const_reference const_reference;
Chris@16 675 typedef typename ::boost::container::allocator_traits<Allocator>::size_type size_type;
Chris@16 676 typedef typename ::boost::container::allocator_traits<Allocator>::difference_type difference_type;
Chris@16 677 typedef Allocator allocator_type;
Chris@16 678 typedef Allocator stored_allocator_type;
Chris@101 679 #if defined BOOST_CONTAINER_VECTOR_ITERATOR_IS_POINTER
Chris@16 680 typedef BOOST_CONTAINER_IMPDEF(pointer) iterator;
Chris@16 681 typedef BOOST_CONTAINER_IMPDEF(const_pointer) const_iterator;
Chris@16 682 #else
Chris@16 683 typedef BOOST_CONTAINER_IMPDEF(iterator_impl) iterator;
Chris@16 684 typedef BOOST_CONTAINER_IMPDEF(const_iterator_impl) const_iterator;
Chris@16 685 #endif
Chris@101 686 typedef BOOST_CONTAINER_IMPDEF(boost::container::reverse_iterator<iterator>) reverse_iterator;
Chris@101 687 typedef BOOST_CONTAINER_IMPDEF(boost::container::reverse_iterator<const_iterator>) const_reverse_iterator;
Chris@16 688
Chris@101 689 #ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
Chris@16 690 private:
Chris@16 691 BOOST_COPYABLE_AND_MOVABLE(vector)
Chris@101 692 typedef container_detail::vector_value_traits<Allocator> value_traits;
Chris@101 693 typedef constant_iterator<T, difference_type> cvalue_iterator;
Chris@16 694
Chris@101 695 protected:
Chris@16 696
Chris@101 697 void steal_resources(vector &x)
Chris@101 698 { return this->m_holder.steal_resources(x.m_holder); }
Chris@101 699
Chris@101 700 struct initial_capacity_t{};
Chris@101 701 template<class AllocFwd>
Chris@101 702 vector(initial_capacity_t, pointer initial_memory, size_type capacity, BOOST_FWD_REF(AllocFwd) a)
Chris@101 703 : m_holder(initial_memory, capacity, ::boost::forward<AllocFwd>(a))
Chris@101 704 {}
Chris@101 705
Chris@101 706 vector(initial_capacity_t, pointer initial_memory, size_type capacity)
Chris@101 707 : m_holder(initial_memory, capacity)
Chris@101 708 {}
Chris@101 709
Chris@101 710 #endif //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
Chris@16 711
Chris@16 712 public:
Chris@16 713 //////////////////////////////////////////////
Chris@16 714 //
Chris@16 715 // construct/copy/destroy
Chris@16 716 //
Chris@16 717 //////////////////////////////////////////////
Chris@16 718
Chris@16 719 //! <b>Effects</b>: Constructs a vector taking the allocator as parameter.
Chris@16 720 //!
Chris@101 721 //! <b>Throws</b>: Nothing.
Chris@16 722 //!
Chris@16 723 //! <b>Complexity</b>: Constant.
Chris@101 724 vector() BOOST_NOEXCEPT_OR_NOTHROW
Chris@16 725 : m_holder()
Chris@16 726 {}
Chris@16 727
Chris@16 728 //! <b>Effects</b>: Constructs a vector taking the allocator as parameter.
Chris@16 729 //!
Chris@16 730 //! <b>Throws</b>: Nothing
Chris@16 731 //!
Chris@16 732 //! <b>Complexity</b>: Constant.
Chris@101 733 explicit vector(const allocator_type& a) BOOST_NOEXCEPT_OR_NOTHROW
Chris@16 734 : m_holder(a)
Chris@16 735 {}
Chris@16 736
Chris@101 737 //! <b>Effects</b>: Constructs a vector and inserts n value initialized values.
Chris@16 738 //!
Chris@101 739 //! <b>Throws</b>: If allocator_type's allocation
Chris@101 740 //! throws or T's value initialization throws.
Chris@16 741 //!
Chris@16 742 //! <b>Complexity</b>: Linear to n.
Chris@16 743 explicit vector(size_type n)
Chris@101 744 : m_holder(container_detail::uninitialized_size, n)
Chris@16 745 {
Chris@101 746 #ifdef BOOST_CONTAINER_VECTOR_ALLOC_STATS
Chris@101 747 this->num_alloc += n != 0;
Chris@101 748 #endif
Chris@16 749 boost::container::uninitialized_value_init_alloc_n
Chris@16 750 (this->m_holder.alloc(), n, container_detail::to_raw_pointer(this->m_holder.start()));
Chris@16 751 }
Chris@16 752
Chris@16 753 //! <b>Effects</b>: Constructs a vector that will use a copy of allocator a
Chris@16 754 //! and inserts n default initialized values.
Chris@16 755 //!
Chris@101 756 //! <b>Throws</b>: If allocator_type's allocation
Chris@101 757 //! throws or T's default initialization throws.
Chris@16 758 //!
Chris@16 759 //! <b>Complexity</b>: Linear to n.
Chris@16 760 //!
Chris@16 761 //! <b>Note</b>: Non-standard extension
Chris@101 762 vector(size_type n, default_init_t)
Chris@101 763 : m_holder(container_detail::uninitialized_size, n)
Chris@16 764 {
Chris@101 765 #ifdef BOOST_CONTAINER_VECTOR_ALLOC_STATS
Chris@101 766 this->num_alloc += n != 0;
Chris@101 767 #endif
Chris@101 768 boost::container::uninitialized_default_init_alloc_n
Chris@101 769 (this->m_holder.alloc(), n, container_detail::to_raw_pointer(this->m_holder.start()));
Chris@101 770 }
Chris@101 771
Chris@101 772 //! <b>Effects</b>: Constructs a vector that will use a copy of allocator a
Chris@101 773 //! and inserts n value initialized values.
Chris@101 774 //!
Chris@101 775 //! <b>Throws</b>: If allocator_type's allocation
Chris@101 776 //! throws or T's value initialization throws.
Chris@101 777 //!
Chris@101 778 //! <b>Complexity</b>: Linear to n.
Chris@101 779 explicit vector(size_type n, const allocator_type &a)
Chris@101 780 : m_holder(container_detail::uninitialized_size, a, n)
Chris@101 781 {
Chris@101 782 #ifdef BOOST_CONTAINER_VECTOR_ALLOC_STATS
Chris@101 783 this->num_alloc += n != 0;
Chris@101 784 #endif
Chris@101 785 boost::container::uninitialized_value_init_alloc_n
Chris@101 786 (this->m_holder.alloc(), n, container_detail::to_raw_pointer(this->m_holder.start()));
Chris@101 787 }
Chris@101 788
Chris@101 789 //! <b>Effects</b>: Constructs a vector that will use a copy of allocator a
Chris@101 790 //! and inserts n default initialized values.
Chris@101 791 //!
Chris@101 792 //! <b>Throws</b>: If allocator_type's allocation
Chris@101 793 //! throws or T's default initialization throws.
Chris@101 794 //!
Chris@101 795 //! <b>Complexity</b>: Linear to n.
Chris@101 796 //!
Chris@101 797 //! <b>Note</b>: Non-standard extension
Chris@101 798 vector(size_type n, default_init_t, const allocator_type &a)
Chris@101 799 : m_holder(container_detail::uninitialized_size, a, n)
Chris@101 800 {
Chris@101 801 #ifdef BOOST_CONTAINER_VECTOR_ALLOC_STATS
Chris@101 802 this->num_alloc += n != 0;
Chris@101 803 #endif
Chris@16 804 boost::container::uninitialized_default_init_alloc_n
Chris@16 805 (this->m_holder.alloc(), n, container_detail::to_raw_pointer(this->m_holder.start()));
Chris@16 806 }
Chris@16 807
Chris@16 808 //! <b>Effects</b>: Constructs a vector
Chris@16 809 //! and inserts n copies of value.
Chris@16 810 //!
Chris@101 811 //! <b>Throws</b>: If allocator_type's allocation
Chris@16 812 //! throws or T's copy constructor throws.
Chris@16 813 //!
Chris@16 814 //! <b>Complexity</b>: Linear to n.
Chris@16 815 vector(size_type n, const T& value)
Chris@101 816 : m_holder(container_detail::uninitialized_size, n)
Chris@16 817 {
Chris@101 818 #ifdef BOOST_CONTAINER_VECTOR_ALLOC_STATS
Chris@101 819 this->num_alloc += n != 0;
Chris@101 820 #endif
Chris@16 821 boost::container::uninitialized_fill_alloc_n
Chris@16 822 (this->m_holder.alloc(), value, n, container_detail::to_raw_pointer(this->m_holder.start()));
Chris@16 823 }
Chris@16 824
Chris@16 825 //! <b>Effects</b>: Constructs a vector that will use a copy of allocator a
Chris@16 826 //! and inserts n copies of value.
Chris@16 827 //!
Chris@16 828 //! <b>Throws</b>: If allocation
Chris@16 829 //! throws or T's copy constructor throws.
Chris@16 830 //!
Chris@16 831 //! <b>Complexity</b>: Linear to n.
Chris@16 832 vector(size_type n, const T& value, const allocator_type& a)
Chris@101 833 : m_holder(container_detail::uninitialized_size, a, n)
Chris@16 834 {
Chris@101 835 #ifdef BOOST_CONTAINER_VECTOR_ALLOC_STATS
Chris@101 836 this->num_alloc += n != 0;
Chris@101 837 #endif
Chris@16 838 boost::container::uninitialized_fill_alloc_n
Chris@16 839 (this->m_holder.alloc(), value, n, container_detail::to_raw_pointer(this->m_holder.start()));
Chris@16 840 }
Chris@16 841
Chris@16 842 //! <b>Effects</b>: Constructs a vector
Chris@16 843 //! and inserts a copy of the range [first, last) in the vector.
Chris@16 844 //!
Chris@101 845 //! <b>Throws</b>: If allocator_type's allocation
Chris@101 846 //! throws or T's constructor taking a dereferenced InIt throws.
Chris@16 847 //!
Chris@16 848 //! <b>Complexity</b>: Linear to the range [first, last).
Chris@16 849 template <class InIt>
Chris@16 850 vector(InIt first, InIt last)
Chris@16 851 : m_holder()
Chris@101 852 { this->assign(first, last); }
Chris@16 853
Chris@16 854 //! <b>Effects</b>: Constructs a vector that will use a copy of allocator a
Chris@16 855 //! and inserts a copy of the range [first, last) in the vector.
Chris@16 856 //!
Chris@101 857 //! <b>Throws</b>: If allocator_type's allocation
Chris@101 858 //! throws or T's constructor taking a dereferenced InIt throws.
Chris@16 859 //!
Chris@16 860 //! <b>Complexity</b>: Linear to the range [first, last).
Chris@16 861 template <class InIt>
Chris@16 862 vector(InIt first, InIt last, const allocator_type& a)
Chris@16 863 : m_holder(a)
Chris@101 864 { this->assign(first, last); }
Chris@16 865
Chris@16 866 //! <b>Effects</b>: Copy constructs a vector.
Chris@16 867 //!
Chris@16 868 //! <b>Postcondition</b>: x == *this.
Chris@16 869 //!
Chris@101 870 //! <b>Throws</b>: If allocator_type's allocation
Chris@16 871 //! throws or T's copy constructor throws.
Chris@16 872 //!
Chris@16 873 //! <b>Complexity</b>: Linear to the elements x contains.
Chris@16 874 vector(const vector &x)
Chris@101 875 : m_holder( container_detail::uninitialized_size
Chris@101 876 , allocator_traits_type::select_on_container_copy_construction(x.m_holder.alloc())
Chris@101 877 , x.size())
Chris@16 878 {
Chris@101 879 #ifdef BOOST_CONTAINER_VECTOR_ALLOC_STATS
Chris@101 880 this->num_alloc += x.size() != 0;
Chris@101 881 #endif
Chris@16 882 ::boost::container::uninitialized_copy_alloc_n
Chris@16 883 ( this->m_holder.alloc(), container_detail::to_raw_pointer(x.m_holder.start())
Chris@16 884 , x.size(), container_detail::to_raw_pointer(this->m_holder.start()));
Chris@16 885 }
Chris@16 886
Chris@101 887 //! <b>Effects</b>: Move constructor. Moves x's resources to *this.
Chris@16 888 //!
Chris@16 889 //! <b>Throws</b>: Nothing
Chris@16 890 //!
Chris@16 891 //! <b>Complexity</b>: Constant.
Chris@101 892 vector(BOOST_RV_REF(vector) x) BOOST_NOEXCEPT_OR_NOTHROW
Chris@101 893 : m_holder(boost::move(x.m_holder))
Chris@101 894 { BOOST_STATIC_ASSERT((!allocator_traits_type::is_partially_propagable::value)); }
Chris@101 895
Chris@101 896 #if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
Chris@101 897 //! <b>Effects</b>: Constructs a vector that will use a copy of allocator a
Chris@101 898 //! and inserts a copy of the range [il.begin(), il.last()) in the vector
Chris@101 899 //!
Chris@101 900 //! <b>Throws</b>: If T's constructor taking a dereferenced initializer_list iterator throws.
Chris@101 901 //!
Chris@101 902 //! <b>Complexity</b>: Linear to the range [il.begin(), il.end()).
Chris@101 903 vector(std::initializer_list<value_type> il, const allocator_type& a = allocator_type())
Chris@101 904 : m_holder(a)
Chris@101 905 {
Chris@101 906 this->assign(il.begin(), il.end());
Chris@101 907 }
Chris@101 908 #endif
Chris@16 909
Chris@16 910 #if !defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
Chris@16 911
Chris@101 912 //! <b>Effects</b>: Move constructor. Moves x's resources to *this.
Chris@16 913 //!
Chris@16 914 //! <b>Throws</b>: If T's move constructor or allocation throws
Chris@16 915 //!
Chris@16 916 //! <b>Complexity</b>: Linear.
Chris@16 917 //!
Chris@101 918 //! <b>Note</b>: Non-standard extension to support static_vector
Chris@16 919 template<class OtherAllocator>
Chris@101 920 vector(BOOST_RV_REF_BEG vector<T, OtherAllocator> BOOST_RV_REF_END x
Chris@101 921 , typename container_detail::enable_if_c
Chris@101 922 < container_detail::is_version<OtherAllocator, 0>::value>::type * = 0
Chris@101 923 )
Chris@101 924 : m_holder(boost::move(x.m_holder))
Chris@16 925 {}
Chris@16 926
Chris@16 927 #endif //!defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
Chris@16 928
Chris@16 929 //! <b>Effects</b>: Copy constructs a vector using the specified allocator.
Chris@16 930 //!
Chris@16 931 //! <b>Postcondition</b>: x == *this.
Chris@16 932 //!
Chris@16 933 //! <b>Throws</b>: If allocation
Chris@16 934 //! throws or T's copy constructor throws.
Chris@16 935 //!
Chris@16 936 //! <b>Complexity</b>: Linear to the elements x contains.
Chris@16 937 vector(const vector &x, const allocator_type &a)
Chris@101 938 : m_holder(container_detail::uninitialized_size, a, x.size())
Chris@16 939 {
Chris@101 940 #ifdef BOOST_CONTAINER_VECTOR_ALLOC_STATS
Chris@101 941 this->num_alloc += x.size() != 0;
Chris@101 942 #endif
Chris@16 943 ::boost::container::uninitialized_copy_alloc_n_source
Chris@16 944 ( this->m_holder.alloc(), container_detail::to_raw_pointer(x.m_holder.start())
Chris@16 945 , x.size(), container_detail::to_raw_pointer(this->m_holder.start()));
Chris@16 946 }
Chris@16 947
Chris@16 948 //! <b>Effects</b>: Move constructor using the specified allocator.
Chris@101 949 //! Moves x's resources to *this if a == allocator_type().
Chris@16 950 //! Otherwise copies values from x to *this.
Chris@16 951 //!
Chris@16 952 //! <b>Throws</b>: If allocation or T's copy constructor throws.
Chris@16 953 //!
Chris@101 954 //! <b>Complexity</b>: Constant if a == x.get_allocator(), linear otherwise.
Chris@101 955 vector(BOOST_RV_REF(vector) x, const allocator_type &a)
Chris@101 956 : m_holder( container_detail::uninitialized_size, a
Chris@101 957 , is_propagable_from(x.get_stored_allocator(), x.m_holder.start(), a, true) ? 0 : x.size()
Chris@101 958 )
Chris@16 959 {
Chris@101 960 if(is_propagable_from(x.get_stored_allocator(), x.m_holder.start(), a, true)){
Chris@101 961 this->m_holder.steal_resources(x.m_holder);
Chris@16 962 }
Chris@16 963 else{
Chris@101 964 const size_type n = x.size();
Chris@101 965 #ifdef BOOST_CONTAINER_VECTOR_ALLOC_STATS
Chris@101 966 this->num_alloc += n != 0;
Chris@101 967 #endif
Chris@16 968 ::boost::container::uninitialized_move_alloc_n_source
Chris@101 969 ( this->m_holder.alloc(), container_detail::to_raw_pointer(x.m_holder.start())
Chris@16 970 , n, container_detail::to_raw_pointer(this->m_holder.start()));
Chris@16 971 }
Chris@16 972 }
Chris@16 973
Chris@16 974 //! <b>Effects</b>: Destroys the vector. All stored values are destroyed
Chris@16 975 //! and used memory is deallocated.
Chris@16 976 //!
Chris@16 977 //! <b>Throws</b>: Nothing.
Chris@16 978 //!
Chris@16 979 //! <b>Complexity</b>: Linear to the number of elements.
Chris@101 980 ~vector() BOOST_NOEXCEPT_OR_NOTHROW
Chris@16 981 {
Chris@16 982 boost::container::destroy_alloc_n
Chris@16 983 (this->get_stored_allocator(), container_detail::to_raw_pointer(this->m_holder.start()), this->m_holder.m_size);
Chris@16 984 //vector_alloc_holder deallocates the data
Chris@101 985 }
Chris@16 986
Chris@16 987 //! <b>Effects</b>: Makes *this contain the same elements as x.
Chris@16 988 //!
Chris@16 989 //! <b>Postcondition</b>: this->size() == x.size(). *this contains a copy
Chris@16 990 //! of each of x's elements.
Chris@16 991 //!
Chris@16 992 //! <b>Throws</b>: If memory allocation throws or T's copy/move constructor/assignment throws.
Chris@16 993 //!
Chris@16 994 //! <b>Complexity</b>: Linear to the number of elements in x.
Chris@16 995 vector& operator=(BOOST_COPY_ASSIGN_REF(vector) x)
Chris@16 996 {
Chris@16 997 if (&x != this){
Chris@101 998 this->priv_copy_assign(x);
Chris@16 999 }
Chris@16 1000 return *this;
Chris@16 1001 }
Chris@16 1002
Chris@101 1003 #if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
Chris@101 1004 //! <b>Effects</b>: Make *this container contains elements from il.
Chris@101 1005 //!
Chris@101 1006 //! <b>Complexity</b>: Linear to the range [il.begin(), il.end()).
Chris@101 1007 vector& operator=(std::initializer_list<value_type> il)
Chris@101 1008 {
Chris@101 1009 this->assign(il.begin(), il.end());
Chris@101 1010 return *this;
Chris@101 1011 }
Chris@101 1012 #endif
Chris@101 1013
Chris@101 1014 //! <b>Effects</b>: Move assignment. All x's values are transferred to *this.
Chris@16 1015 //!
Chris@16 1016 //! <b>Postcondition</b>: x.empty(). *this contains a the elements x had
Chris@16 1017 //! before the function.
Chris@16 1018 //!
Chris@101 1019 //! <b>Throws</b>: If allocator_traits_type::propagate_on_container_move_assignment
Chris@101 1020 //! is false and (allocation throws or value_type's move constructor throws)
Chris@16 1021 //!
Chris@101 1022 //! <b>Complexity</b>: Constant if allocator_traits_type::
Chris@101 1023 //! propagate_on_container_move_assignment is true or
Chris@101 1024 //! this->get>allocator() == x.get_allocator(). Linear otherwise.
Chris@16 1025 vector& operator=(BOOST_RV_REF(vector) x)
Chris@101 1026 BOOST_NOEXCEPT_IF(allocator_traits_type::propagate_on_container_move_assignment::value
Chris@101 1027 || allocator_traits_type::is_always_equal::value)
Chris@16 1028 {
Chris@101 1029 this->priv_move_assign(boost::move(x));
Chris@16 1030 return *this;
Chris@16 1031 }
Chris@16 1032
Chris@16 1033 #if !defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
Chris@16 1034
Chris@101 1035 //! <b>Effects</b>: Move assignment. All x's values are transferred to *this.
Chris@16 1036 //!
Chris@16 1037 //! <b>Postcondition</b>: x.empty(). *this contains a the elements x had
Chris@16 1038 //! before the function.
Chris@16 1039 //!
Chris@16 1040 //! <b>Throws</b>: If move constructor/assignment of T throws or allocation throws
Chris@16 1041 //!
Chris@16 1042 //! <b>Complexity</b>: Linear.
Chris@101 1043 //!
Chris@101 1044 //! <b>Note</b>: Non-standard extension to support static_vector
Chris@101 1045 template<class OtherAllocator>
Chris@101 1046 typename container_detail::enable_if_c
Chris@101 1047 < container_detail::is_version<OtherAllocator, 0>::value &&
Chris@101 1048 !container_detail::is_same<OtherAllocator, allocator_type>::value
Chris@101 1049 , vector& >::type
Chris@101 1050 operator=(BOOST_RV_REF_BEG vector<value_type, OtherAllocator> BOOST_RV_REF_END x)
Chris@16 1051 {
Chris@101 1052 this->priv_move_assign(boost::move(x));
Chris@101 1053 return *this;
Chris@101 1054 }
Chris@101 1055
Chris@101 1056 //! <b>Effects</b>: Copy assignment. All x's values are copied to *this.
Chris@101 1057 //!
Chris@101 1058 //! <b>Postcondition</b>: x.empty(). *this contains a the elements x had
Chris@101 1059 //! before the function.
Chris@101 1060 //!
Chris@101 1061 //! <b>Throws</b>: If move constructor/assignment of T throws or allocation throws
Chris@101 1062 //!
Chris@101 1063 //! <b>Complexity</b>: Linear.
Chris@101 1064 //!
Chris@101 1065 //! <b>Note</b>: Non-standard extension to support static_vector
Chris@101 1066 template<class OtherAllocator>
Chris@101 1067 typename container_detail::enable_if_c
Chris@101 1068 < container_detail::is_version<OtherAllocator, 0>::value &&
Chris@101 1069 !container_detail::is_same<OtherAllocator, allocator_type>::value
Chris@101 1070 , vector& >::type
Chris@101 1071 operator=(const vector<value_type, OtherAllocator> &x)
Chris@101 1072 {
Chris@101 1073 this->priv_copy_assign(x);
Chris@16 1074 return *this;
Chris@16 1075 }
Chris@16 1076
Chris@16 1077 #endif
Chris@16 1078
Chris@16 1079 //! <b>Effects</b>: Assigns the the range [first, last) to *this.
Chris@16 1080 //!
Chris@16 1081 //! <b>Throws</b>: If memory allocation throws or T's copy/move constructor/assignment or
Chris@16 1082 //! T's constructor/assignment from dereferencing InpIt throws.
Chris@16 1083 //!
Chris@16 1084 //! <b>Complexity</b>: Linear to n.
Chris@16 1085 template <class InIt>
Chris@16 1086 void assign(InIt first, InIt last
Chris@101 1087 BOOST_CONTAINER_DOCIGN(BOOST_MOVE_I typename container_detail::enable_if_c
Chris@101 1088 < !container_detail::is_convertible<InIt BOOST_MOVE_I size_type>::value &&
Chris@101 1089 ( container_detail::is_input_iterator<InIt>::value ||
Chris@101 1090 container_detail::is_same<alloc_version BOOST_MOVE_I version_0>::value )
Chris@101 1091 >::type * = 0) )
Chris@16 1092 {
Chris@16 1093 //Overwrite all elements we can from [first, last)
Chris@16 1094 iterator cur = this->begin();
Chris@16 1095 const iterator end_it = this->end();
Chris@16 1096 for ( ; first != last && cur != end_it; ++cur, ++first){
Chris@16 1097 *cur = *first;
Chris@16 1098 }
Chris@16 1099
Chris@16 1100 if (first == last){
Chris@16 1101 //There are no more elements in the sequence, erase remaining
Chris@101 1102 T* const end_pos = this->back_raw();
Chris@101 1103 const size_type n = static_cast<size_type>(end_pos - container_detail::iterator_to_raw_pointer(cur));
Chris@16 1104 this->priv_destroy_last_n(n);
Chris@16 1105 }
Chris@16 1106 else{
Chris@16 1107 //There are more elements in the range, insert the remaining ones
Chris@16 1108 this->insert(this->cend(), first, last);
Chris@16 1109 }
Chris@16 1110 }
Chris@16 1111
Chris@101 1112 #if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
Chris@101 1113 //! <b>Effects</b>: Assigns the the range [il.begin(), il.end()) to *this.
Chris@101 1114 //!
Chris@101 1115 //! <b>Throws</b>: If memory allocation throws or
Chris@101 1116 //! T's constructor from dereferencing iniializer_list iterator throws.
Chris@101 1117 //!
Chris@101 1118 void assign(std::initializer_list<T> il)
Chris@101 1119 {
Chris@101 1120 this->assign(il.begin(), il.end());
Chris@101 1121 }
Chris@101 1122 #endif
Chris@101 1123
Chris@101 1124 //! <b>Effects</b>: Assigns the the range [first, last) to *this.
Chris@101 1125 //!
Chris@101 1126 //! <b>Throws</b>: If memory allocation throws or T's copy/move constructor/assignment or
Chris@101 1127 //! T's constructor/assignment from dereferencing InpIt throws.
Chris@101 1128 //!
Chris@101 1129 //! <b>Complexity</b>: Linear to n.
Chris@101 1130 template <class FwdIt>
Chris@101 1131 void assign(FwdIt first, FwdIt last
Chris@101 1132 BOOST_CONTAINER_DOCIGN(BOOST_MOVE_I typename container_detail::enable_if_c
Chris@101 1133 < !container_detail::is_convertible<FwdIt BOOST_MOVE_I size_type>::value &&
Chris@101 1134 ( !container_detail::is_input_iterator<FwdIt>::value &&
Chris@101 1135 !container_detail::is_same<alloc_version BOOST_MOVE_I version_0>::value )
Chris@101 1136 >::type * = 0)
Chris@101 1137 )
Chris@101 1138 {
Chris@101 1139 //For Fwd iterators the standard only requires EmplaceConstructible and assignable from *first
Chris@101 1140 //so we can't do any backwards allocation
Chris@101 1141 const size_type input_sz = static_cast<size_type>(boost::container::iterator_distance(first, last));
Chris@101 1142 const size_type old_capacity = this->capacity();
Chris@101 1143 if(input_sz > old_capacity){ //If input range is too big, we need to reallocate
Chris@101 1144 size_type real_cap = 0;
Chris@101 1145 pointer reuse(this->m_holder.start());
Chris@101 1146 pointer const ret(this->m_holder.allocation_command(allocate_new|expand_fwd, input_sz, real_cap = input_sz, reuse));
Chris@101 1147 if(!reuse){ //New allocation, just emplace new values
Chris@101 1148 #ifdef BOOST_CONTAINER_VECTOR_ALLOC_STATS
Chris@101 1149 ++this->num_alloc;
Chris@101 1150 #endif
Chris@101 1151 pointer const old_p = this->m_holder.start();
Chris@101 1152 if(old_p){
Chris@101 1153 this->priv_destroy_all();
Chris@101 1154 this->m_holder.alloc().deallocate(old_p, old_capacity);
Chris@101 1155 }
Chris@101 1156 this->m_holder.start(ret);
Chris@101 1157 this->m_holder.capacity(real_cap);
Chris@101 1158 this->m_holder.m_size = 0;
Chris@101 1159 this->priv_uninitialized_construct_at_end(first, last);
Chris@101 1160 return;
Chris@101 1161 }
Chris@101 1162 else{
Chris@101 1163 #ifdef BOOST_CONTAINER_VECTOR_ALLOC_STATS
Chris@101 1164 ++this->num_expand_fwd;
Chris@101 1165 #endif
Chris@101 1166 this->m_holder.capacity(real_cap);
Chris@101 1167 //Forward expansion, use assignment + back deletion/construction that comes later
Chris@101 1168 }
Chris@101 1169 }
Chris@101 1170 //Overwrite all elements we can from [first, last)
Chris@101 1171 iterator cur = this->begin();
Chris@101 1172 const iterator end_it = this->end();
Chris@101 1173 for ( ; first != last && cur != end_it; ++cur, ++first){
Chris@101 1174 *cur = *first;
Chris@101 1175 }
Chris@101 1176
Chris@101 1177 if (first == last){
Chris@101 1178 //There are no more elements in the sequence, erase remaining
Chris@101 1179 this->priv_destroy_last_n(this->size() - input_sz);
Chris@101 1180 }
Chris@101 1181 else{
Chris@101 1182 //Uninitialized construct at end the remaining range
Chris@101 1183 this->priv_uninitialized_construct_at_end(first, last);
Chris@101 1184 }
Chris@101 1185 }
Chris@101 1186
Chris@16 1187 //! <b>Effects</b>: Assigns the n copies of val to *this.
Chris@16 1188 //!
Chris@16 1189 //! <b>Throws</b>: If memory allocation throws or
Chris@16 1190 //! T's copy/move constructor/assignment throws.
Chris@16 1191 //!
Chris@16 1192 //! <b>Complexity</b>: Linear to n.
Chris@16 1193 void assign(size_type n, const value_type& val)
Chris@16 1194 { this->assign(cvalue_iterator(val, n), cvalue_iterator()); }
Chris@16 1195
Chris@16 1196 //! <b>Effects</b>: Returns a copy of the internal allocator.
Chris@16 1197 //!
Chris@16 1198 //! <b>Throws</b>: If allocator's copy constructor throws.
Chris@16 1199 //!
Chris@16 1200 //! <b>Complexity</b>: Constant.
Chris@101 1201 allocator_type get_allocator() const BOOST_NOEXCEPT_OR_NOTHROW
Chris@16 1202 { return this->m_holder.alloc(); }
Chris@16 1203
Chris@16 1204 //! <b>Effects</b>: Returns a reference to the internal allocator.
Chris@16 1205 //!
Chris@16 1206 //! <b>Throws</b>: Nothing
Chris@16 1207 //!
Chris@16 1208 //! <b>Complexity</b>: Constant.
Chris@16 1209 //!
Chris@16 1210 //! <b>Note</b>: Non-standard extension.
Chris@101 1211 stored_allocator_type &get_stored_allocator() BOOST_NOEXCEPT_OR_NOTHROW
Chris@16 1212 { return this->m_holder.alloc(); }
Chris@16 1213
Chris@16 1214 //! <b>Effects</b>: Returns a reference to the internal allocator.
Chris@16 1215 //!
Chris@16 1216 //! <b>Throws</b>: Nothing
Chris@16 1217 //!
Chris@16 1218 //! <b>Complexity</b>: Constant.
Chris@16 1219 //!
Chris@16 1220 //! <b>Note</b>: Non-standard extension.
Chris@101 1221 const stored_allocator_type &get_stored_allocator() const BOOST_NOEXCEPT_OR_NOTHROW
Chris@16 1222 { return this->m_holder.alloc(); }
Chris@16 1223
Chris@16 1224 //////////////////////////////////////////////
Chris@16 1225 //
Chris@16 1226 // iterators
Chris@16 1227 //
Chris@16 1228 //////////////////////////////////////////////
Chris@16 1229
Chris@16 1230 //! <b>Effects</b>: Returns an iterator to the first element contained in the vector.
Chris@16 1231 //!
Chris@16 1232 //! <b>Throws</b>: Nothing.
Chris@16 1233 //!
Chris@16 1234 //! <b>Complexity</b>: Constant.
Chris@101 1235 iterator begin() BOOST_NOEXCEPT_OR_NOTHROW
Chris@16 1236 { return iterator(this->m_holder.start()); }
Chris@16 1237
Chris@16 1238 //! <b>Effects</b>: Returns a const_iterator to the first element contained in the vector.
Chris@16 1239 //!
Chris@16 1240 //! <b>Throws</b>: Nothing.
Chris@16 1241 //!
Chris@16 1242 //! <b>Complexity</b>: Constant.
Chris@101 1243 const_iterator begin() const BOOST_NOEXCEPT_OR_NOTHROW
Chris@16 1244 { return const_iterator(this->m_holder.start()); }
Chris@16 1245
Chris@16 1246 //! <b>Effects</b>: Returns an iterator to the end of the vector.
Chris@16 1247 //!
Chris@16 1248 //! <b>Throws</b>: Nothing.
Chris@16 1249 //!
Chris@16 1250 //! <b>Complexity</b>: Constant.
Chris@101 1251 iterator end() BOOST_NOEXCEPT_OR_NOTHROW
Chris@16 1252 { return iterator(this->m_holder.start() + this->m_holder.m_size); }
Chris@16 1253
Chris@16 1254 //! <b>Effects</b>: Returns a const_iterator to the end of the vector.
Chris@16 1255 //!
Chris@16 1256 //! <b>Throws</b>: Nothing.
Chris@16 1257 //!
Chris@16 1258 //! <b>Complexity</b>: Constant.
Chris@101 1259 const_iterator end() const BOOST_NOEXCEPT_OR_NOTHROW
Chris@16 1260 { return this->cend(); }
Chris@16 1261
Chris@16 1262 //! <b>Effects</b>: Returns a reverse_iterator pointing to the beginning
Chris@16 1263 //! of the reversed vector.
Chris@16 1264 //!
Chris@16 1265 //! <b>Throws</b>: Nothing.
Chris@16 1266 //!
Chris@16 1267 //! <b>Complexity</b>: Constant.
Chris@101 1268 reverse_iterator rbegin() BOOST_NOEXCEPT_OR_NOTHROW
Chris@16 1269 { return reverse_iterator(this->end()); }
Chris@16 1270
Chris@16 1271 //! <b>Effects</b>: Returns a const_reverse_iterator pointing to the beginning
Chris@16 1272 //! of the reversed vector.
Chris@16 1273 //!
Chris@16 1274 //! <b>Throws</b>: Nothing.
Chris@16 1275 //!
Chris@16 1276 //! <b>Complexity</b>: Constant.
Chris@101 1277 const_reverse_iterator rbegin() const BOOST_NOEXCEPT_OR_NOTHROW
Chris@16 1278 { return this->crbegin(); }
Chris@16 1279
Chris@16 1280 //! <b>Effects</b>: Returns a reverse_iterator pointing to the end
Chris@16 1281 //! of the reversed vector.
Chris@16 1282 //!
Chris@16 1283 //! <b>Throws</b>: Nothing.
Chris@16 1284 //!
Chris@16 1285 //! <b>Complexity</b>: Constant.
Chris@101 1286 reverse_iterator rend() BOOST_NOEXCEPT_OR_NOTHROW
Chris@16 1287 { return reverse_iterator(this->begin()); }
Chris@16 1288
Chris@16 1289 //! <b>Effects</b>: Returns a const_reverse_iterator pointing to the end
Chris@16 1290 //! of the reversed vector.
Chris@16 1291 //!
Chris@16 1292 //! <b>Throws</b>: Nothing.
Chris@16 1293 //!
Chris@16 1294 //! <b>Complexity</b>: Constant.
Chris@101 1295 const_reverse_iterator rend() const BOOST_NOEXCEPT_OR_NOTHROW
Chris@16 1296 { return this->crend(); }
Chris@16 1297
Chris@16 1298 //! <b>Effects</b>: Returns a const_iterator to the first element contained in the vector.
Chris@16 1299 //!
Chris@16 1300 //! <b>Throws</b>: Nothing.
Chris@16 1301 //!
Chris@16 1302 //! <b>Complexity</b>: Constant.
Chris@101 1303 const_iterator cbegin() const BOOST_NOEXCEPT_OR_NOTHROW
Chris@16 1304 { return const_iterator(this->m_holder.start()); }
Chris@16 1305
Chris@16 1306 //! <b>Effects</b>: Returns a const_iterator to the end of the vector.
Chris@16 1307 //!
Chris@16 1308 //! <b>Throws</b>: Nothing.
Chris@16 1309 //!
Chris@16 1310 //! <b>Complexity</b>: Constant.
Chris@101 1311 const_iterator cend() const BOOST_NOEXCEPT_OR_NOTHROW
Chris@16 1312 { return const_iterator(this->m_holder.start() + this->m_holder.m_size); }
Chris@16 1313
Chris@16 1314 //! <b>Effects</b>: Returns a const_reverse_iterator pointing to the beginning
Chris@16 1315 //! of the reversed vector.
Chris@16 1316 //!
Chris@16 1317 //! <b>Throws</b>: Nothing.
Chris@16 1318 //!
Chris@16 1319 //! <b>Complexity</b>: Constant.
Chris@101 1320 const_reverse_iterator crbegin() const BOOST_NOEXCEPT_OR_NOTHROW
Chris@16 1321 { return const_reverse_iterator(this->end());}
Chris@16 1322
Chris@16 1323 //! <b>Effects</b>: Returns a const_reverse_iterator pointing to the end
Chris@16 1324 //! of the reversed vector.
Chris@16 1325 //!
Chris@16 1326 //! <b>Throws</b>: Nothing.
Chris@16 1327 //!
Chris@16 1328 //! <b>Complexity</b>: Constant.
Chris@101 1329 const_reverse_iterator crend() const BOOST_NOEXCEPT_OR_NOTHROW
Chris@16 1330 { return const_reverse_iterator(this->begin()); }
Chris@16 1331
Chris@16 1332 //////////////////////////////////////////////
Chris@16 1333 //
Chris@16 1334 // capacity
Chris@16 1335 //
Chris@16 1336 //////////////////////////////////////////////
Chris@16 1337
Chris@16 1338 //! <b>Effects</b>: Returns true if the vector contains no elements.
Chris@16 1339 //!
Chris@16 1340 //! <b>Throws</b>: Nothing.
Chris@16 1341 //!
Chris@16 1342 //! <b>Complexity</b>: Constant.
Chris@101 1343 bool empty() const BOOST_NOEXCEPT_OR_NOTHROW
Chris@16 1344 { return !this->m_holder.m_size; }
Chris@16 1345
Chris@16 1346 //! <b>Effects</b>: Returns the number of the elements contained in the vector.
Chris@16 1347 //!
Chris@16 1348 //! <b>Throws</b>: Nothing.
Chris@16 1349 //!
Chris@16 1350 //! <b>Complexity</b>: Constant.
Chris@101 1351 size_type size() const BOOST_NOEXCEPT_OR_NOTHROW
Chris@16 1352 { return this->m_holder.m_size; }
Chris@16 1353
Chris@16 1354 //! <b>Effects</b>: Returns the largest possible size of the vector.
Chris@16 1355 //!
Chris@16 1356 //! <b>Throws</b>: Nothing.
Chris@16 1357 //!
Chris@16 1358 //! <b>Complexity</b>: Constant.
Chris@101 1359 size_type max_size() const BOOST_NOEXCEPT_OR_NOTHROW
Chris@16 1360 { return allocator_traits_type::max_size(this->m_holder.alloc()); }
Chris@16 1361
Chris@16 1362 //! <b>Effects</b>: Inserts or erases elements at the end such that
Chris@16 1363 //! the size becomes n. New elements are value initialized.
Chris@16 1364 //!
Chris@101 1365 //! <b>Throws</b>: If memory allocation throws, or T's copy/move or value initialization throws.
Chris@16 1366 //!
Chris@16 1367 //! <b>Complexity</b>: Linear to the difference between size() and new_size.
Chris@16 1368 void resize(size_type new_size)
Chris@101 1369 { this->priv_resize(new_size, value_init); }
Chris@16 1370
Chris@16 1371 //! <b>Effects</b>: Inserts or erases elements at the end such that
Chris@101 1372 //! the size becomes n. New elements are default initialized.
Chris@16 1373 //!
Chris@101 1374 //! <b>Throws</b>: If memory allocation throws, or T's copy/move or default initialization throws.
Chris@16 1375 //!
Chris@16 1376 //! <b>Complexity</b>: Linear to the difference between size() and new_size.
Chris@16 1377 //!
Chris@16 1378 //! <b>Note</b>: Non-standard extension
Chris@16 1379 void resize(size_type new_size, default_init_t)
Chris@101 1380 { this->priv_resize(new_size, default_init); }
Chris@16 1381
Chris@16 1382 //! <b>Effects</b>: Inserts or erases elements at the end such that
Chris@16 1383 //! the size becomes n. New elements are copy constructed from x.
Chris@16 1384 //!
Chris@101 1385 //! <b>Throws</b>: If memory allocation throws, or T's copy/move constructor throws.
Chris@16 1386 //!
Chris@16 1387 //! <b>Complexity</b>: Linear to the difference between size() and new_size.
Chris@16 1388 void resize(size_type new_size, const T& x)
Chris@101 1389 { this->priv_resize(new_size, x); }
Chris@16 1390
Chris@16 1391 //! <b>Effects</b>: Number of elements for which memory has been allocated.
Chris@16 1392 //! capacity() is always greater than or equal to size().
Chris@16 1393 //!
Chris@16 1394 //! <b>Throws</b>: Nothing.
Chris@16 1395 //!
Chris@16 1396 //! <b>Complexity</b>: Constant.
Chris@101 1397 size_type capacity() const BOOST_NOEXCEPT_OR_NOTHROW
Chris@16 1398 { return this->m_holder.capacity(); }
Chris@16 1399
Chris@16 1400 //! <b>Effects</b>: If n is less than or equal to capacity(), this call has no
Chris@16 1401 //! effect. Otherwise, it is a request for allocation of additional memory.
Chris@16 1402 //! If the request is successful, then capacity() is greater than or equal to
Chris@16 1403 //! n; otherwise, capacity() is unchanged. In either case, size() is unchanged.
Chris@16 1404 //!
Chris@16 1405 //! <b>Throws</b>: If memory allocation allocation throws or T's copy/move constructor throws.
Chris@16 1406 void reserve(size_type new_cap)
Chris@16 1407 {
Chris@16 1408 if (this->capacity() < new_cap){
Chris@101 1409 this->priv_reserve_no_capacity(new_cap, alloc_version());
Chris@16 1410 }
Chris@16 1411 }
Chris@16 1412
Chris@16 1413 //! <b>Effects</b>: Tries to deallocate the excess of memory created
Chris@16 1414 //! with previous allocations. The size of the vector is unchanged
Chris@16 1415 //!
Chris@16 1416 //! <b>Throws</b>: If memory allocation throws, or T's copy/move constructor throws.
Chris@16 1417 //!
Chris@16 1418 //! <b>Complexity</b>: Linear to size().
Chris@16 1419 void shrink_to_fit()
Chris@16 1420 { this->priv_shrink_to_fit(alloc_version()); }
Chris@16 1421
Chris@16 1422 //////////////////////////////////////////////
Chris@16 1423 //
Chris@16 1424 // element access
Chris@16 1425 //
Chris@16 1426 //////////////////////////////////////////////
Chris@16 1427
Chris@16 1428 //! <b>Requires</b>: !empty()
Chris@16 1429 //!
Chris@16 1430 //! <b>Effects</b>: Returns a reference to the first
Chris@16 1431 //! element of the container.
Chris@16 1432 //!
Chris@16 1433 //! <b>Throws</b>: Nothing.
Chris@16 1434 //!
Chris@16 1435 //! <b>Complexity</b>: Constant.
Chris@101 1436 reference front() BOOST_NOEXCEPT_OR_NOTHROW
Chris@16 1437 { return *this->m_holder.start(); }
Chris@16 1438
Chris@16 1439 //! <b>Requires</b>: !empty()
Chris@16 1440 //!
Chris@16 1441 //! <b>Effects</b>: Returns a const reference to the first
Chris@16 1442 //! element of the container.
Chris@16 1443 //!
Chris@16 1444 //! <b>Throws</b>: Nothing.
Chris@16 1445 //!
Chris@16 1446 //! <b>Complexity</b>: Constant.
Chris@101 1447 const_reference front() const BOOST_NOEXCEPT_OR_NOTHROW
Chris@16 1448 { return *this->m_holder.start(); }
Chris@16 1449
Chris@16 1450 //! <b>Requires</b>: !empty()
Chris@16 1451 //!
Chris@16 1452 //! <b>Effects</b>: Returns a reference to the last
Chris@16 1453 //! element of the container.
Chris@16 1454 //!
Chris@16 1455 //! <b>Throws</b>: Nothing.
Chris@16 1456 //!
Chris@16 1457 //! <b>Complexity</b>: Constant.
Chris@101 1458 reference back() BOOST_NOEXCEPT_OR_NOTHROW
Chris@101 1459 {
Chris@101 1460 BOOST_ASSERT(this->m_holder.m_size > 0);
Chris@101 1461 return this->m_holder.start()[this->m_holder.m_size - 1];
Chris@101 1462 }
Chris@16 1463
Chris@16 1464 //! <b>Requires</b>: !empty()
Chris@16 1465 //!
Chris@16 1466 //! <b>Effects</b>: Returns a const reference to the last
Chris@16 1467 //! element of the container.
Chris@16 1468 //!
Chris@16 1469 //! <b>Throws</b>: Nothing.
Chris@16 1470 //!
Chris@16 1471 //! <b>Complexity</b>: Constant.
Chris@101 1472 const_reference back() const BOOST_NOEXCEPT_OR_NOTHROW
Chris@101 1473 {
Chris@101 1474 BOOST_ASSERT(this->m_holder.m_size > 0);
Chris@101 1475 return this->m_holder.start()[this->m_holder.m_size - 1];
Chris@101 1476 }
Chris@16 1477
Chris@16 1478 //! <b>Requires</b>: size() > n.
Chris@16 1479 //!
Chris@16 1480 //! <b>Effects</b>: Returns a reference to the nth element
Chris@16 1481 //! from the beginning of the container.
Chris@16 1482 //!
Chris@16 1483 //! <b>Throws</b>: Nothing.
Chris@16 1484 //!
Chris@16 1485 //! <b>Complexity</b>: Constant.
Chris@101 1486 reference operator[](size_type n) BOOST_NOEXCEPT_OR_NOTHROW
Chris@101 1487 {
Chris@101 1488 BOOST_ASSERT(this->m_holder.m_size > n);
Chris@101 1489 return this->m_holder.start()[n];
Chris@101 1490 }
Chris@16 1491
Chris@16 1492 //! <b>Requires</b>: size() > n.
Chris@16 1493 //!
Chris@16 1494 //! <b>Effects</b>: Returns a const reference to the nth element
Chris@16 1495 //! from the beginning of the container.
Chris@16 1496 //!
Chris@16 1497 //! <b>Throws</b>: Nothing.
Chris@16 1498 //!
Chris@16 1499 //! <b>Complexity</b>: Constant.
Chris@101 1500 const_reference operator[](size_type n) const BOOST_NOEXCEPT_OR_NOTHROW
Chris@101 1501 {
Chris@101 1502 return this->m_holder.start()[n];
Chris@101 1503 }
Chris@101 1504
Chris@101 1505 //! <b>Requires</b>: size() >= n.
Chris@101 1506 //!
Chris@101 1507 //! <b>Effects</b>: Returns an iterator to the nth element
Chris@101 1508 //! from the beginning of the container. Returns end()
Chris@101 1509 //! if n == size().
Chris@101 1510 //!
Chris@101 1511 //! <b>Throws</b>: Nothing.
Chris@101 1512 //!
Chris@101 1513 //! <b>Complexity</b>: Constant.
Chris@101 1514 //!
Chris@101 1515 //! <b>Note</b>: Non-standard extension
Chris@101 1516 iterator nth(size_type n) BOOST_NOEXCEPT_OR_NOTHROW
Chris@101 1517 {
Chris@101 1518 BOOST_ASSERT(this->m_holder.m_size >= n);
Chris@101 1519 return iterator(this->m_holder.start()+n);
Chris@101 1520 }
Chris@101 1521
Chris@101 1522 //! <b>Requires</b>: size() >= n.
Chris@101 1523 //!
Chris@101 1524 //! <b>Effects</b>: Returns a const_iterator to the nth element
Chris@101 1525 //! from the beginning of the container. Returns end()
Chris@101 1526 //! if n == size().
Chris@101 1527 //!
Chris@101 1528 //! <b>Throws</b>: Nothing.
Chris@101 1529 //!
Chris@101 1530 //! <b>Complexity</b>: Constant.
Chris@101 1531 //!
Chris@101 1532 //! <b>Note</b>: Non-standard extension
Chris@101 1533 const_iterator nth(size_type n) const BOOST_NOEXCEPT_OR_NOTHROW
Chris@101 1534 {
Chris@101 1535 BOOST_ASSERT(this->m_holder.m_size >= n);
Chris@101 1536 return const_iterator(this->m_holder.start()+n);
Chris@101 1537 }
Chris@101 1538
Chris@101 1539 //! <b>Requires</b>: size() >= n.
Chris@101 1540 //!
Chris@101 1541 //! <b>Effects</b>: Returns an iterator to the nth element
Chris@101 1542 //! from the beginning of the container. Returns end()
Chris@101 1543 //! if n == size().
Chris@101 1544 //!
Chris@101 1545 //! <b>Throws</b>: Nothing.
Chris@101 1546 //!
Chris@101 1547 //! <b>Complexity</b>: Constant.
Chris@101 1548 //!
Chris@101 1549 //! <b>Note</b>: Non-standard extension
Chris@101 1550 size_type index_of(iterator p) BOOST_NOEXCEPT_OR_NOTHROW
Chris@101 1551 { return this->priv_index_of(vector_iterator_get_ptr(p)); }
Chris@101 1552
Chris@101 1553 //! <b>Requires</b>: begin() <= p <= end().
Chris@101 1554 //!
Chris@101 1555 //! <b>Effects</b>: Returns the index of the element pointed by p
Chris@101 1556 //! and size() if p == end().
Chris@101 1557 //!
Chris@101 1558 //! <b>Throws</b>: Nothing.
Chris@101 1559 //!
Chris@101 1560 //! <b>Complexity</b>: Constant.
Chris@101 1561 //!
Chris@101 1562 //! <b>Note</b>: Non-standard extension
Chris@101 1563 size_type index_of(const_iterator p) const BOOST_NOEXCEPT_OR_NOTHROW
Chris@101 1564 { return this->priv_index_of(vector_iterator_get_ptr(p)); }
Chris@16 1565
Chris@16 1566 //! <b>Requires</b>: size() > n.
Chris@16 1567 //!
Chris@16 1568 //! <b>Effects</b>: Returns a reference to the nth element
Chris@16 1569 //! from the beginning of the container.
Chris@16 1570 //!
Chris@16 1571 //! <b>Throws</b>: std::range_error if n >= size()
Chris@16 1572 //!
Chris@16 1573 //! <b>Complexity</b>: Constant.
Chris@16 1574 reference at(size_type n)
Chris@16 1575 { this->priv_check_range(n); return this->m_holder.start()[n]; }
Chris@16 1576
Chris@16 1577 //! <b>Requires</b>: size() > n.
Chris@16 1578 //!
Chris@16 1579 //! <b>Effects</b>: Returns a const reference to the nth element
Chris@16 1580 //! from the beginning of the container.
Chris@16 1581 //!
Chris@16 1582 //! <b>Throws</b>: std::range_error if n >= size()
Chris@16 1583 //!
Chris@16 1584 //! <b>Complexity</b>: Constant.
Chris@16 1585 const_reference at(size_type n) const
Chris@16 1586 { this->priv_check_range(n); return this->m_holder.start()[n]; }
Chris@16 1587
Chris@16 1588 //////////////////////////////////////////////
Chris@16 1589 //
Chris@16 1590 // data access
Chris@16 1591 //
Chris@16 1592 //////////////////////////////////////////////
Chris@16 1593
Chris@101 1594 //! <b>Returns</b>: A pointer such that [data(),data() + size()) is a valid range.
Chris@16 1595 //! For a non-empty vector, data() == &front().
Chris@16 1596 //!
Chris@16 1597 //! <b>Throws</b>: Nothing.
Chris@16 1598 //!
Chris@16 1599 //! <b>Complexity</b>: Constant.
Chris@101 1600 T* data() BOOST_NOEXCEPT_OR_NOTHROW
Chris@16 1601 { return container_detail::to_raw_pointer(this->m_holder.start()); }
Chris@16 1602
Chris@101 1603 //! <b>Returns</b>: A pointer such that [data(),data() + size()) is a valid range.
Chris@16 1604 //! For a non-empty vector, data() == &front().
Chris@16 1605 //!
Chris@16 1606 //! <b>Throws</b>: Nothing.
Chris@16 1607 //!
Chris@16 1608 //! <b>Complexity</b>: Constant.
Chris@101 1609 const T * data() const BOOST_NOEXCEPT_OR_NOTHROW
Chris@16 1610 { return container_detail::to_raw_pointer(this->m_holder.start()); }
Chris@16 1611
Chris@16 1612 //////////////////////////////////////////////
Chris@16 1613 //
Chris@16 1614 // modifiers
Chris@16 1615 //
Chris@16 1616 //////////////////////////////////////////////
Chris@16 1617
Chris@101 1618 #if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) || defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
Chris@16 1619 //! <b>Effects</b>: Inserts an object of type T constructed with
Chris@16 1620 //! std::forward<Args>(args)... in the end of the vector.
Chris@16 1621 //!
Chris@16 1622 //! <b>Throws</b>: If memory allocation throws or the in-place constructor throws or
Chris@101 1623 //! T's copy/move constructor throws.
Chris@16 1624 //!
Chris@16 1625 //! <b>Complexity</b>: Amortized constant time.
Chris@16 1626 template<class ...Args>
Chris@101 1627 void emplace_back(BOOST_FWD_REF(Args)...args)
Chris@16 1628 {
Chris@101 1629 if (BOOST_LIKELY(this->room_enough())){
Chris@16 1630 //There is more memory, just construct a new object at the end
Chris@101 1631 allocator_traits_type::construct(this->m_holder.alloc(), this->back_raw(), ::boost::forward<Args>(args)...);
Chris@16 1632 ++this->m_holder.m_size;
Chris@16 1633 }
Chris@16 1634 else{
Chris@16 1635 typedef container_detail::insert_emplace_proxy<Allocator, T*, Args...> type;
Chris@16 1636 this->priv_forward_range_insert_no_capacity
Chris@101 1637 (this->back_ptr(), 1, type(::boost::forward<Args>(args)...), alloc_version());
Chris@16 1638 }
Chris@16 1639 }
Chris@16 1640
Chris@101 1641 //! <b>Effects</b>: Inserts an object of type T constructed with
Chris@101 1642 //! std::forward<Args>(args)... in the end of the vector.
Chris@101 1643 //!
Chris@101 1644 //! <b>Throws</b>: If the in-place constructor throws.
Chris@101 1645 //!
Chris@101 1646 //! <b>Complexity</b>: Constant time.
Chris@101 1647 //!
Chris@101 1648 //! <b>Note</b>: Non-standard extension.
Chris@101 1649 template<class ...Args>
Chris@101 1650 bool stable_emplace_back(BOOST_FWD_REF(Args)...args)
Chris@101 1651 {
Chris@101 1652 const bool is_room_enough = this->room_enough() || (alloc_version::value == 2 && this->m_holder.try_expand_fwd(1u));
Chris@101 1653 if (BOOST_LIKELY(is_room_enough)){
Chris@101 1654 //There is more memory, just construct a new object at the end
Chris@101 1655 allocator_traits_type::construct(this->m_holder.alloc(), this->back_raw(), ::boost::forward<Args>(args)...);
Chris@101 1656 ++this->m_holder.m_size;
Chris@101 1657 }
Chris@101 1658 return is_room_enough;
Chris@101 1659 }
Chris@101 1660
Chris@16 1661 //! <b>Requires</b>: position must be a valid iterator of *this.
Chris@16 1662 //!
Chris@16 1663 //! <b>Effects</b>: Inserts an object of type T constructed with
Chris@16 1664 //! std::forward<Args>(args)... before position
Chris@16 1665 //!
Chris@16 1666 //! <b>Throws</b>: If memory allocation throws or the in-place constructor throws or
Chris@101 1667 //! T's copy/move constructor/assignment throws.
Chris@16 1668 //!
Chris@16 1669 //! <b>Complexity</b>: If position is end(), amortized constant time
Chris@16 1670 //! Linear time otherwise.
Chris@16 1671 template<class ...Args>
Chris@101 1672 iterator emplace(const_iterator position, BOOST_FWD_REF(Args) ...args)
Chris@16 1673 {
Chris@16 1674 //Just call more general insert(pos, size, value) and return iterator
Chris@16 1675 typedef container_detail::insert_emplace_proxy<Allocator, T*, Args...> type;
Chris@101 1676 return this->priv_forward_range_insert( vector_iterator_get_ptr(position), 1
Chris@101 1677 , type(::boost::forward<Args>(args)...));
Chris@16 1678 }
Chris@16 1679
Chris@101 1680 #else // !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
Chris@16 1681
Chris@101 1682 #define BOOST_CONTAINER_VECTOR_EMPLACE_CODE(N) \
Chris@101 1683 BOOST_MOVE_TMPL_LT##N BOOST_MOVE_CLASS##N BOOST_MOVE_GT##N \
Chris@101 1684 void emplace_back(BOOST_MOVE_UREF##N)\
Chris@101 1685 {\
Chris@101 1686 if (BOOST_LIKELY(this->room_enough())){\
Chris@101 1687 allocator_traits_type::construct (this->m_holder.alloc()\
Chris@101 1688 , this->back_raw() BOOST_MOVE_I##N BOOST_MOVE_FWD##N);\
Chris@101 1689 ++this->m_holder.m_size;\
Chris@101 1690 }\
Chris@101 1691 else{\
Chris@101 1692 typedef container_detail::insert_emplace_proxy_arg##N<Allocator, T* BOOST_MOVE_I##N BOOST_MOVE_TARG##N> type;\
Chris@101 1693 this->priv_forward_range_insert_no_capacity\
Chris@101 1694 ( this->back_ptr(), 1, type(BOOST_MOVE_FWD##N), alloc_version());\
Chris@101 1695 }\
Chris@101 1696 }\
Chris@101 1697 \
Chris@101 1698 BOOST_MOVE_TMPL_LT##N BOOST_MOVE_CLASS##N BOOST_MOVE_GT##N \
Chris@101 1699 bool stable_emplace_back(BOOST_MOVE_UREF##N)\
Chris@101 1700 {\
Chris@101 1701 const bool is_room_enough = this->room_enough() || (alloc_version::value == 2 && this->m_holder.try_expand_fwd(1u));\
Chris@101 1702 if (BOOST_LIKELY(is_room_enough)){\
Chris@101 1703 allocator_traits_type::construct (this->m_holder.alloc()\
Chris@101 1704 , this->back_raw() BOOST_MOVE_I##N BOOST_MOVE_FWD##N);\
Chris@101 1705 ++this->m_holder.m_size;\
Chris@101 1706 }\
Chris@101 1707 return is_room_enough;\
Chris@101 1708 }\
Chris@101 1709 \
Chris@101 1710 BOOST_MOVE_TMPL_LT##N BOOST_MOVE_CLASS##N BOOST_MOVE_GT##N \
Chris@101 1711 iterator emplace(const_iterator pos BOOST_MOVE_I##N BOOST_MOVE_UREF##N)\
Chris@101 1712 {\
Chris@101 1713 typedef container_detail::insert_emplace_proxy_arg##N<Allocator, T* BOOST_MOVE_I##N BOOST_MOVE_TARG##N> type;\
Chris@101 1714 return this->priv_forward_range_insert(vector_iterator_get_ptr(pos), 1, type(BOOST_MOVE_FWD##N));\
Chris@101 1715 }\
Chris@101 1716 //
Chris@101 1717 BOOST_MOVE_ITERATE_0TO9(BOOST_CONTAINER_VECTOR_EMPLACE_CODE)
Chris@101 1718 #undef BOOST_CONTAINER_VECTOR_EMPLACE_CODE
Chris@16 1719
Chris@101 1720 #endif
Chris@16 1721
Chris@16 1722 #if defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
Chris@16 1723 //! <b>Effects</b>: Inserts a copy of x at the end of the vector.
Chris@16 1724 //!
Chris@16 1725 //! <b>Throws</b>: If memory allocation throws or
Chris@16 1726 //! T's copy/move constructor throws.
Chris@16 1727 //!
Chris@16 1728 //! <b>Complexity</b>: Amortized constant time.
Chris@16 1729 void push_back(const T &x);
Chris@16 1730
Chris@16 1731 //! <b>Effects</b>: Constructs a new element in the end of the vector
Chris@101 1732 //! and moves the resources of x to this new element.
Chris@16 1733 //!
Chris@16 1734 //! <b>Throws</b>: If memory allocation throws or
Chris@101 1735 //! T's copy/move constructor throws.
Chris@16 1736 //!
Chris@16 1737 //! <b>Complexity</b>: Amortized constant time.
Chris@16 1738 void push_back(T &&x);
Chris@16 1739 #else
Chris@16 1740 BOOST_MOVE_CONVERSION_AWARE_CATCH(push_back, T, void, priv_push_back)
Chris@16 1741 #endif
Chris@101 1742
Chris@16 1743 #if defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
Chris@16 1744 //! <b>Requires</b>: position must be a valid iterator of *this.
Chris@16 1745 //!
Chris@16 1746 //! <b>Effects</b>: Insert a copy of x before position.
Chris@16 1747 //!
Chris@16 1748 //! <b>Throws</b>: If memory allocation throws or T's copy/move constructor/assignment throws.
Chris@16 1749 //!
Chris@16 1750 //! <b>Complexity</b>: If position is end(), amortized constant time
Chris@16 1751 //! Linear time otherwise.
Chris@16 1752 iterator insert(const_iterator position, const T &x);
Chris@16 1753
Chris@16 1754 //! <b>Requires</b>: position must be a valid iterator of *this.
Chris@16 1755 //!
Chris@101 1756 //! <b>Effects</b>: Insert a new element before position with x's resources.
Chris@16 1757 //!
Chris@16 1758 //! <b>Throws</b>: If memory allocation throws.
Chris@16 1759 //!
Chris@16 1760 //! <b>Complexity</b>: If position is end(), amortized constant time
Chris@16 1761 //! Linear time otherwise.
Chris@16 1762 iterator insert(const_iterator position, T &&x);
Chris@16 1763 #else
Chris@16 1764 BOOST_MOVE_CONVERSION_AWARE_CATCH_1ARG(insert, T, iterator, priv_insert, const_iterator, const_iterator)
Chris@16 1765 #endif
Chris@16 1766
Chris@16 1767 //! <b>Requires</b>: p must be a valid iterator of *this.
Chris@16 1768 //!
Chris@16 1769 //! <b>Effects</b>: Insert n copies of x before pos.
Chris@16 1770 //!
Chris@16 1771 //! <b>Returns</b>: an iterator to the first inserted element or p if n is 0.
Chris@16 1772 //!
Chris@101 1773 //! <b>Throws</b>: If memory allocation throws or T's copy/move constructor throws.
Chris@16 1774 //!
Chris@16 1775 //! <b>Complexity</b>: Linear to n.
Chris@16 1776 iterator insert(const_iterator p, size_type n, const T& x)
Chris@16 1777 {
Chris@101 1778 container_detail::insert_n_copies_proxy<Allocator, T*> proxy(x);
Chris@101 1779 return this->priv_forward_range_insert(vector_iterator_get_ptr(p), n, proxy);
Chris@16 1780 }
Chris@16 1781
Chris@16 1782 //! <b>Requires</b>: p must be a valid iterator of *this.
Chris@16 1783 //!
Chris@16 1784 //! <b>Effects</b>: Insert a copy of the [first, last) range before pos.
Chris@16 1785 //!
Chris@16 1786 //! <b>Returns</b>: an iterator to the first inserted element or pos if first == last.
Chris@16 1787 //!
Chris@16 1788 //! <b>Throws</b>: If memory allocation throws, T's constructor from a
Chris@16 1789 //! dereferenced InpIt throws or T's copy/move constructor/assignment throws.
Chris@16 1790 //!
Chris@101 1791 //! <b>Complexity</b>: Linear to boost::container::iterator_distance [first, last).
Chris@16 1792 template <class InIt>
Chris@16 1793 iterator insert(const_iterator pos, InIt first, InIt last
Chris@101 1794 BOOST_CONTAINER_DOCIGN(BOOST_MOVE_I typename container_detail::enable_if_c
Chris@101 1795 < !container_detail::is_convertible<InIt BOOST_MOVE_I size_type>::value
Chris@16 1796 && container_detail::is_input_iterator<InIt>::value
Chris@101 1797 >::type * = 0)
Chris@16 1798 )
Chris@16 1799 {
Chris@16 1800 const size_type n_pos = pos - this->cbegin();
Chris@16 1801 iterator it(vector_iterator_get_ptr(pos));
Chris@16 1802 for(;first != last; ++first){
Chris@16 1803 it = this->emplace(it, *first);
Chris@16 1804 ++it;
Chris@16 1805 }
Chris@16 1806 return iterator(this->m_holder.start() + n_pos);
Chris@16 1807 }
Chris@16 1808
Chris@16 1809 #if !defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
Chris@16 1810 template <class FwdIt>
Chris@16 1811 iterator insert(const_iterator pos, FwdIt first, FwdIt last
Chris@16 1812 , typename container_detail::enable_if_c
Chris@16 1813 < !container_detail::is_convertible<FwdIt, size_type>::value
Chris@16 1814 && !container_detail::is_input_iterator<FwdIt>::value
Chris@16 1815 >::type * = 0
Chris@16 1816 )
Chris@16 1817 {
Chris@101 1818 container_detail::insert_range_proxy<Allocator, FwdIt, T*> proxy(first);
Chris@101 1819 return this->priv_forward_range_insert(vector_iterator_get_ptr(pos), boost::container::iterator_distance(first, last), proxy);
Chris@101 1820 }
Chris@101 1821 #endif
Chris@101 1822
Chris@101 1823 //! <b>Requires</b>: p must be a valid iterator of *this. num, must
Chris@101 1824 //! be equal to boost::container::iterator_distance(first, last)
Chris@101 1825 //!
Chris@101 1826 //! <b>Effects</b>: Insert a copy of the [first, last) range before pos.
Chris@101 1827 //!
Chris@101 1828 //! <b>Returns</b>: an iterator to the first inserted element or pos if first == last.
Chris@101 1829 //!
Chris@101 1830 //! <b>Throws</b>: If memory allocation throws, T's constructor from a
Chris@101 1831 //! dereferenced InpIt throws or T's copy/move constructor/assignment throws.
Chris@101 1832 //!
Chris@101 1833 //! <b>Complexity</b>: Linear to boost::container::iterator_distance [first, last).
Chris@101 1834 //!
Chris@101 1835 //! <b>Note</b>: This function avoids a linear operation to calculate boost::container::iterator_distance[first, last)
Chris@101 1836 //! for forward and bidirectional iterators, and a one by one insertion for input iterators. This is a
Chris@101 1837 //! a non-standard extension.
Chris@101 1838 #if !defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
Chris@101 1839 template <class InIt>
Chris@101 1840 iterator insert(const_iterator pos, size_type num, InIt first, InIt last)
Chris@101 1841 {
Chris@101 1842 BOOST_ASSERT(container_detail::is_input_iterator<InIt>::value ||
Chris@101 1843 num == static_cast<size_type>(boost::container::iterator_distance(first, last)));
Chris@101 1844 (void)last;
Chris@101 1845 container_detail::insert_range_proxy<Allocator, InIt, T*> proxy(first);
Chris@101 1846 return this->priv_forward_range_insert(vector_iterator_get_ptr(pos), num, proxy);
Chris@101 1847 }
Chris@101 1848 #endif
Chris@101 1849
Chris@101 1850 #if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
Chris@101 1851 //! <b>Requires</b>: position must be a valid iterator of *this.
Chris@101 1852 //!
Chris@101 1853 //! <b>Effects</b>: Insert a copy of the [il.begin(), il.end()) range before position.
Chris@101 1854 //!
Chris@101 1855 //! <b>Returns</b>: an iterator to the first inserted element or position if first == last.
Chris@101 1856 //!
Chris@101 1857 //! <b>Complexity</b>: Linear to the range [il.begin(), il.end()).
Chris@101 1858 iterator insert(const_iterator position, std::initializer_list<value_type> il)
Chris@101 1859 {
Chris@101 1860 return this->insert(position, il.begin(), il.end());
Chris@16 1861 }
Chris@16 1862 #endif
Chris@16 1863
Chris@16 1864 //! <b>Effects</b>: Removes the last element from the vector.
Chris@16 1865 //!
Chris@16 1866 //! <b>Throws</b>: Nothing.
Chris@16 1867 //!
Chris@16 1868 //! <b>Complexity</b>: Constant time.
Chris@101 1869 void pop_back() BOOST_NOEXCEPT_OR_NOTHROW
Chris@16 1870 {
Chris@16 1871 //Destroy last element
Chris@101 1872 this->priv_destroy_last();
Chris@16 1873 }
Chris@16 1874
Chris@16 1875 //! <b>Effects</b>: Erases the element at position pos.
Chris@16 1876 //!
Chris@16 1877 //! <b>Throws</b>: Nothing.
Chris@16 1878 //!
Chris@16 1879 //! <b>Complexity</b>: Linear to the elements between pos and the
Chris@16 1880 //! last element. Constant if pos is the last element.
Chris@16 1881 iterator erase(const_iterator position)
Chris@16 1882 {
Chris@101 1883 const pointer p = vector_iterator_get_ptr(position);
Chris@101 1884 T *const pos_ptr = container_detail::to_raw_pointer(p);
Chris@101 1885 T *const beg_ptr = container_detail::to_raw_pointer(this->m_holder.start());
Chris@101 1886 T *const new_end_ptr = ::boost::container::move(pos_ptr + 1, beg_ptr + this->m_holder.m_size, pos_ptr);
Chris@16 1887 //Move elements forward and destroy last
Chris@101 1888 this->priv_destroy_last(pos_ptr == new_end_ptr);
Chris@101 1889 return iterator(p);
Chris@16 1890 }
Chris@16 1891
Chris@16 1892 //! <b>Effects</b>: Erases the elements pointed by [first, last).
Chris@16 1893 //!
Chris@16 1894 //! <b>Throws</b>: Nothing.
Chris@16 1895 //!
Chris@16 1896 //! <b>Complexity</b>: Linear to the distance between first and last
Chris@16 1897 //! plus linear to the elements between pos and the last element.
Chris@16 1898 iterator erase(const_iterator first, const_iterator last)
Chris@16 1899 {
Chris@16 1900 if (first != last){
Chris@101 1901 T* const old_end_ptr = this->back_raw();
Chris@101 1902 T* const first_ptr = container_detail::to_raw_pointer(vector_iterator_get_ptr(first));
Chris@101 1903 T* const last_ptr = container_detail::to_raw_pointer(vector_iterator_get_ptr(last));
Chris@101 1904 T* const ptr = container_detail::to_raw_pointer(boost::container::move(last_ptr, old_end_ptr, first_ptr));
Chris@101 1905 this->priv_destroy_last_n(old_end_ptr - ptr, last_ptr == old_end_ptr);
Chris@16 1906 }
Chris@16 1907 return iterator(vector_iterator_get_ptr(first));
Chris@16 1908 }
Chris@16 1909
Chris@16 1910 //! <b>Effects</b>: Swaps the contents of *this and x.
Chris@16 1911 //!
Chris@16 1912 //! <b>Throws</b>: Nothing.
Chris@16 1913 //!
Chris@16 1914 //! <b>Complexity</b>: Constant.
Chris@101 1915 void swap(vector& x)
Chris@101 1916 BOOST_NOEXCEPT_IF( ((allocator_traits_type::propagate_on_container_swap::value
Chris@101 1917 || allocator_traits_type::is_always_equal::value) &&
Chris@101 1918 !container_detail::is_version<Allocator, 0>::value))
Chris@16 1919 {
Chris@101 1920 this->priv_swap(x, container_detail::bool_<container_detail::is_version<Allocator, 0>::value>());
Chris@16 1921 }
Chris@16 1922
Chris@16 1923 #ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
Chris@16 1924
Chris@16 1925 //! <b>Effects</b>: Swaps the contents of *this and x.
Chris@16 1926 //!
Chris@101 1927 //! <b>Throws</b>: Nothing.
Chris@16 1928 //!
Chris@16 1929 //! <b>Complexity</b>: Linear
Chris@16 1930 //!
Chris@101 1931 //! <b>Note</b>: Non-standard extension to support static_vector
Chris@16 1932 template<class OtherAllocator>
Chris@101 1933 void swap(vector<T, OtherAllocator> & x
Chris@101 1934 , typename container_detail::enable_if_c
Chris@101 1935 < container_detail::is_version<OtherAllocator, 0>::value &&
Chris@101 1936 !container_detail::is_same<OtherAllocator, allocator_type>::value >::type * = 0
Chris@101 1937 )
Chris@101 1938 { this->m_holder.deep_swap(x.m_holder); }
Chris@16 1939
Chris@16 1940 #endif //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
Chris@16 1941
Chris@16 1942 //! <b>Effects</b>: Erases all the elements of the vector.
Chris@16 1943 //!
Chris@16 1944 //! <b>Throws</b>: Nothing.
Chris@16 1945 //!
Chris@101 1946 //! <b>Complexity</b>: Linear to the number of elements in the container.
Chris@101 1947 void clear() BOOST_NOEXCEPT_OR_NOTHROW
Chris@16 1948 { this->priv_destroy_all(); }
Chris@16 1949
Chris@101 1950 //! <b>Effects</b>: Returns true if x and y are equal
Chris@101 1951 //!
Chris@101 1952 //! <b>Complexity</b>: Linear to the number of elements in the container.
Chris@101 1953 friend bool operator==(const vector& x, const vector& y)
Chris@101 1954 { return x.size() == y.size() && ::boost::container::algo_equal(x.begin(), x.end(), y.begin()); }
Chris@101 1955
Chris@101 1956 //! <b>Effects</b>: Returns true if x and y are unequal
Chris@101 1957 //!
Chris@101 1958 //! <b>Complexity</b>: Linear to the number of elements in the container.
Chris@101 1959 friend bool operator!=(const vector& x, const vector& y)
Chris@101 1960 { return !(x == y); }
Chris@101 1961
Chris@101 1962 //! <b>Effects</b>: Returns true if x is less than y
Chris@101 1963 //!
Chris@101 1964 //! <b>Complexity</b>: Linear to the number of elements in the container.
Chris@101 1965 friend bool operator<(const vector& x, const vector& y)
Chris@101 1966 {
Chris@101 1967 const_iterator first1(x.cbegin()), first2(y.cbegin());
Chris@101 1968 const const_iterator last1(x.cend()), last2(y.cend());
Chris@101 1969 for ( ; (first1 != last1) && (first2 != last2); ++first1, ++first2 ) {
Chris@101 1970 if (*first1 < *first2) return true;
Chris@101 1971 if (*first2 < *first1) return false;
Chris@101 1972 }
Chris@101 1973 return (first1 == last1) && (first2 != last2);
Chris@101 1974 }
Chris@101 1975
Chris@101 1976 //! <b>Effects</b>: Returns true if x is greater than y
Chris@101 1977 //!
Chris@101 1978 //! <b>Complexity</b>: Linear to the number of elements in the container.
Chris@101 1979 friend bool operator>(const vector& x, const vector& y)
Chris@101 1980 { return y < x; }
Chris@101 1981
Chris@101 1982 //! <b>Effects</b>: Returns true if x is equal or less than y
Chris@101 1983 //!
Chris@101 1984 //! <b>Complexity</b>: Linear to the number of elements in the container.
Chris@101 1985 friend bool operator<=(const vector& x, const vector& y)
Chris@101 1986 { return !(y < x); }
Chris@101 1987
Chris@101 1988 //! <b>Effects</b>: Returns true if x is equal or greater than y
Chris@101 1989 //!
Chris@101 1990 //! <b>Complexity</b>: Linear to the number of elements in the container.
Chris@101 1991 friend bool operator>=(const vector& x, const vector& y)
Chris@101 1992 { return !(x < y); }
Chris@101 1993
Chris@101 1994 //! <b>Effects</b>: x.swap(y)
Chris@101 1995 //!
Chris@101 1996 //! <b>Complexity</b>: Constant.
Chris@101 1997 friend void swap(vector& x, vector& y)
Chris@101 1998 { x.swap(y); }
Chris@101 1999
Chris@101 2000 #ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
Chris@101 2001 //! <b>Effects</b>: If n is less than or equal to capacity(), this call has no
Chris@101 2002 //! effect. Otherwise, it is a request for allocation of additional memory
Chris@101 2003 //! (memory expansion) that will not invalidate iterators.
Chris@101 2004 //! If the request is successful, then capacity() is greater than or equal to
Chris@101 2005 //! n; otherwise, capacity() is unchanged. In either case, size() is unchanged.
Chris@101 2006 //!
Chris@101 2007 //! <b>Throws</b>: If memory allocation allocation throws or T's copy/move constructor throws.
Chris@101 2008 //!
Chris@101 2009 //! <b>Note</b>: Non-standard extension.
Chris@101 2010 bool stable_reserve(size_type new_cap)
Chris@101 2011 {
Chris@101 2012 const size_type cp = this->capacity();
Chris@101 2013 return cp >= new_cap || (alloc_version::value == 2 && this->m_holder.try_expand_fwd(new_cap - cp));
Chris@101 2014 }
Chris@16 2015
Chris@16 2016 //Absolutely experimental. This function might change, disappear or simply crash!
Chris@16 2017 template<class BiDirPosConstIt, class BiDirValueIt>
Chris@101 2018 void insert_ordered_at(const size_type element_count, BiDirPosConstIt last_position_it, BiDirValueIt last_value_it)
Chris@16 2019 {
Chris@101 2020 const size_type old_size_pos = this->size();
Chris@101 2021 this->reserve(old_size_pos + element_count);
Chris@101 2022 T* const begin_ptr = container_detail::to_raw_pointer(this->m_holder.start());
Chris@101 2023 size_type insertions_left = element_count;
Chris@101 2024 size_type next_pos = old_size_pos;
Chris@101 2025 size_type hole_size = element_count;
Chris@16 2026
Chris@101 2027 //Exception rollback. If any copy throws before the hole is filled, values
Chris@101 2028 //already inserted/copied at the end of the buffer will be destroyed.
Chris@101 2029 typename value_traits::ArrayDestructor past_hole_values_destroyer
Chris@101 2030 (begin_ptr + old_size_pos + element_count, this->m_holder.alloc(), size_type(0u));
Chris@101 2031 //Loop for each insertion backwards, first moving the elements after the insertion point,
Chris@101 2032 //then inserting the element.
Chris@101 2033 while(insertions_left){
Chris@101 2034 size_type pos = static_cast<size_type>(*(--last_position_it));
Chris@101 2035 while(pos == size_type(-1)){
Chris@101 2036 --last_value_it;
Chris@101 2037 pos = static_cast<size_type>(*(--last_position_it));
Chris@101 2038 }
Chris@101 2039
Chris@101 2040 BOOST_ASSERT(pos != size_type(-1) && pos <= old_size_pos);
Chris@101 2041 //If needed shift the range after the insertion point and the previous insertion point.
Chris@101 2042 //Function will take care if the shift crosses the size() boundary, using copy/move
Chris@101 2043 //or uninitialized copy/move if necessary.
Chris@101 2044 size_type new_hole_size = (pos != next_pos)
Chris@101 2045 ? priv_insert_ordered_at_shift_range(pos, next_pos, this->size(), insertions_left)
Chris@101 2046 : hole_size
Chris@101 2047 ;
Chris@101 2048 if(new_hole_size > 0){
Chris@101 2049 //The hole was reduced by priv_insert_ordered_at_shift_range so expand exception rollback range backwards
Chris@101 2050 past_hole_values_destroyer.increment_size_backwards(next_pos - pos);
Chris@101 2051 //Insert the new value in the hole
Chris@101 2052 allocator_traits_type::construct(this->m_holder.alloc(), begin_ptr + pos + insertions_left - 1, *(--last_value_it));
Chris@101 2053 --new_hole_size;
Chris@101 2054 if(new_hole_size == 0){
Chris@101 2055 //Hole was just filled, disable exception rollback and change vector size
Chris@101 2056 past_hole_values_destroyer.release();
Chris@101 2057 this->m_holder.m_size += element_count;
Chris@101 2058 }
Chris@101 2059 else{
Chris@101 2060 //The hole was reduced by the new insertion by one
Chris@101 2061 past_hole_values_destroyer.increment_size_backwards(size_type(1u));
Chris@101 2062 }
Chris@101 2063 }
Chris@101 2064 else{
Chris@101 2065 if(hole_size){
Chris@101 2066 //Hole was just filled by priv_insert_ordered_at_shift_range, disable exception rollback and change vector size
Chris@101 2067 past_hole_values_destroyer.release();
Chris@101 2068 this->m_holder.m_size += element_count;
Chris@101 2069 }
Chris@101 2070 //Insert the new value in the already constructed range
Chris@101 2071 begin_ptr[pos + insertions_left - 1] = *(--last_value_it);
Chris@101 2072 }
Chris@101 2073 --insertions_left;
Chris@101 2074 hole_size = new_hole_size;
Chris@101 2075 next_pos = pos;
Chris@101 2076 }
Chris@16 2077 }
Chris@16 2078
Chris@16 2079 private:
Chris@16 2080
Chris@101 2081 bool room_enough() const
Chris@101 2082 { return this->m_holder.m_size < this->m_holder.capacity(); }
Chris@101 2083
Chris@101 2084 pointer back_ptr() const
Chris@101 2085 { return this->m_holder.start() + this->m_holder.m_size; }
Chris@101 2086
Chris@101 2087 T* back_raw() const
Chris@101 2088 { return container_detail::to_raw_pointer(this->m_holder.start()) + this->m_holder.m_size; }
Chris@101 2089
Chris@101 2090 size_type priv_index_of(pointer p) const
Chris@101 2091 {
Chris@101 2092 BOOST_ASSERT(this->m_holder.start() <= p);
Chris@101 2093 BOOST_ASSERT(p <= (this->m_holder.start()+this->size()));
Chris@101 2094 return static_cast<size_type>(p - this->m_holder.start());
Chris@101 2095 }
Chris@101 2096
Chris@101 2097 template<class OtherAllocator>
Chris@16 2098 void priv_move_assign(BOOST_RV_REF_BEG vector<T, OtherAllocator> BOOST_RV_REF_END x
Chris@16 2099 , typename container_detail::enable_if_c
Chris@101 2100 < container_detail::is_version<OtherAllocator, 0>::value >::type * = 0)
Chris@16 2101 {
Chris@101 2102 if(!container_detail::is_same<OtherAllocator, allocator_type>::value &&
Chris@101 2103 this->capacity() < x.size()){
Chris@16 2104 throw_bad_alloc();
Chris@16 2105 }
Chris@16 2106 T* const this_start = container_detail::to_raw_pointer(m_holder.start());
Chris@16 2107 T* const other_start = container_detail::to_raw_pointer(x.m_holder.start());
Chris@16 2108 const size_type this_sz = m_holder.m_size;
Chris@16 2109 const size_type other_sz = static_cast<size_type>(x.m_holder.m_size);
Chris@16 2110 boost::container::move_assign_range_alloc_n(this->m_holder.alloc(), other_start, other_sz, this_start, this_sz);
Chris@16 2111 this->m_holder.m_size = other_sz;
Chris@16 2112 }
Chris@16 2113
Chris@101 2114 template<class OtherAllocator>
Chris@101 2115 void priv_move_assign(BOOST_RV_REF_BEG vector<T, OtherAllocator> BOOST_RV_REF_END x
Chris@16 2116 , typename container_detail::enable_if_c
Chris@101 2117 < !container_detail::is_version<OtherAllocator, 0>::value &&
Chris@101 2118 container_detail::is_same<OtherAllocator, allocator_type>::value>::type * = 0)
Chris@16 2119 {
Chris@16 2120 //for move constructor, no aliasing (&x != this) is assummed.
Chris@101 2121 BOOST_ASSERT(this != &x);
Chris@16 2122 allocator_type &this_alloc = this->m_holder.alloc();
Chris@16 2123 allocator_type &x_alloc = x.m_holder.alloc();
Chris@101 2124 const bool propagate_alloc = allocator_traits_type::propagate_on_container_move_assignment::value;
Chris@101 2125
Chris@101 2126 const bool is_propagable_from_x = is_propagable_from(x_alloc, x.m_holder.start(), this_alloc, propagate_alloc);
Chris@101 2127 const bool is_propagable_from_t = is_propagable_from(this_alloc, m_holder.start(), x_alloc, propagate_alloc);
Chris@101 2128 const bool are_both_propagable = is_propagable_from_x && is_propagable_from_t;
Chris@101 2129
Chris@101 2130 //Resources can be transferred if both allocators are
Chris@101 2131 //going to be equal after this function (either propagated or already equal)
Chris@101 2132 if(are_both_propagable){
Chris@16 2133 //Destroy objects but retain memory in case x reuses it in the future
Chris@16 2134 this->clear();
Chris@101 2135 this->m_holder.swap_resources(x.m_holder);
Chris@16 2136 }
Chris@101 2137 else if(is_propagable_from_x){
Chris@101 2138 this->clear();
Chris@101 2139 this->m_holder.alloc().deallocate(this->m_holder.m_start, this->m_holder.m_capacity);
Chris@101 2140 this->m_holder.steal_resources(x.m_holder);
Chris@101 2141 }
Chris@101 2142 //Else do a one by one move
Chris@16 2143 else{
Chris@101 2144 this->assign( boost::make_move_iterator(container_detail::iterator_to_raw_pointer(x.begin()))
Chris@101 2145 , boost::make_move_iterator(container_detail::iterator_to_raw_pointer(x.end() ))
Chris@101 2146 );
Chris@16 2147 }
Chris@101 2148 //Move allocator if needed
Chris@101 2149 container_detail::move_alloc(this_alloc, x_alloc, container_detail::bool_<propagate_alloc>());
Chris@16 2150 }
Chris@16 2151
Chris@101 2152 template<class OtherAllocator>
Chris@101 2153 void priv_copy_assign(const vector<T, OtherAllocator> &x
Chris@16 2154 , typename container_detail::enable_if_c
Chris@101 2155 < container_detail::is_version<OtherAllocator, 0>::value >::type * = 0)
Chris@16 2156 {
Chris@101 2157 if(!container_detail::is_same<OtherAllocator, allocator_type>::value &&
Chris@101 2158 this->capacity() < x.size()){
Chris@101 2159 throw_bad_alloc();
Chris@101 2160 }
Chris@16 2161 T* const this_start = container_detail::to_raw_pointer(m_holder.start());
Chris@16 2162 T* const other_start = container_detail::to_raw_pointer(x.m_holder.start());
Chris@16 2163 const size_type this_sz = m_holder.m_size;
Chris@16 2164 const size_type other_sz = static_cast<size_type>(x.m_holder.m_size);
Chris@16 2165 boost::container::copy_assign_range_alloc_n(this->m_holder.alloc(), other_start, other_sz, this_start, this_sz);
Chris@16 2166 this->m_holder.m_size = other_sz;
Chris@16 2167 }
Chris@16 2168
Chris@101 2169 template<class OtherAllocator>
Chris@101 2170 void priv_copy_assign(const vector<T, OtherAllocator> &x
Chris@16 2171 , typename container_detail::enable_if_c
Chris@101 2172 < !container_detail::is_version<OtherAllocator, 0>::value &&
Chris@101 2173 container_detail::is_same<OtherAllocator, allocator_type>::value >::type * = 0)
Chris@16 2174 {
Chris@16 2175 allocator_type &this_alloc = this->m_holder.alloc();
Chris@16 2176 const allocator_type &x_alloc = x.m_holder.alloc();
Chris@16 2177 container_detail::bool_<allocator_traits_type::
Chris@16 2178 propagate_on_container_copy_assignment::value> flag;
Chris@16 2179 if(flag && this_alloc != x_alloc){
Chris@16 2180 this->clear();
Chris@16 2181 this->shrink_to_fit();
Chris@16 2182 }
Chris@16 2183 container_detail::assign_alloc(this_alloc, x_alloc, flag);
Chris@16 2184 this->assign( container_detail::to_raw_pointer(x.m_holder.start())
Chris@16 2185 , container_detail::to_raw_pointer(x.m_holder.start() + x.m_holder.m_size));
Chris@16 2186 }
Chris@16 2187
Chris@101 2188 template<class Vector> //Template it to avoid it in explicit instantiations
Chris@101 2189 void priv_swap(Vector &x, container_detail::true_type) //version_0
Chris@101 2190 { this->m_holder.deep_swap(x.m_holder); }
Chris@101 2191
Chris@101 2192 template<class Vector> //Template it to avoid it in explicit instantiations
Chris@101 2193 void priv_swap(Vector &x, container_detail::false_type) //version_N
Chris@16 2194 {
Chris@101 2195 const bool propagate_alloc = allocator_traits_type::propagate_on_container_swap::value;
Chris@101 2196 if(are_swap_propagable( this->get_stored_allocator(), this->m_holder.start()
Chris@101 2197 , x.get_stored_allocator(), this->m_holder.start(), propagate_alloc)){
Chris@101 2198 //Just swap internals
Chris@101 2199 this->m_holder.swap_resources(x.m_holder);
Chris@101 2200 }
Chris@101 2201 else{
Chris@101 2202 //Else swap element by element...
Chris@101 2203 bool const t_smaller = this->size() < x.size();
Chris@101 2204 vector &sml = t_smaller ? *this : x;
Chris@101 2205 vector &big = t_smaller ? x : *this;
Chris@101 2206
Chris@101 2207 size_type const common_elements = sml.size();
Chris@101 2208 for(size_type i = 0; i != common_elements; ++i){
Chris@101 2209 boost::adl_move_swap(sml[i], big[i]);
Chris@101 2210 }
Chris@101 2211 //... and move-insert the remaining range
Chris@101 2212 sml.insert( sml.cend()
Chris@101 2213 , boost::make_move_iterator(container_detail::iterator_to_raw_pointer(big.nth(common_elements)))
Chris@101 2214 , boost::make_move_iterator(container_detail::iterator_to_raw_pointer(big.end()))
Chris@101 2215 );
Chris@101 2216 }
Chris@101 2217 //And now swap the allocator
Chris@101 2218 container_detail::swap_alloc(this->m_holder.alloc(), x.m_holder.alloc(), container_detail::bool_<propagate_alloc>());
Chris@16 2219 }
Chris@16 2220
Chris@101 2221 void priv_reserve_no_capacity(size_type, version_0)
Chris@101 2222 { throw_bad_alloc(); }
Chris@101 2223
Chris@101 2224 container_detail::insert_range_proxy<Allocator, boost::move_iterator<T*>, T*> priv_dummy_empty_proxy()
Chris@101 2225 {
Chris@101 2226 return container_detail::insert_range_proxy<Allocator, boost::move_iterator<T*>, T*>
Chris@101 2227 (::boost::make_move_iterator((T *)0));
Chris@101 2228 }
Chris@101 2229
Chris@101 2230 void priv_reserve_no_capacity(size_type new_cap, version_1)
Chris@16 2231 {
Chris@16 2232 //There is not enough memory, allocate a new buffer
Chris@101 2233 //Pass the hint so that allocators can take advantage of this.
Chris@101 2234 pointer const p = allocator_traits_type::allocate(this->m_holder.alloc(), new_cap, this->m_holder.m_start);
Chris@101 2235 //We will reuse insert code, so create a dummy input iterator
Chris@101 2236 this->priv_forward_range_insert_new_allocation
Chris@101 2237 ( container_detail::to_raw_pointer(p), new_cap, this->back_raw(), 0, this->priv_dummy_empty_proxy());
Chris@16 2238 }
Chris@16 2239
Chris@101 2240 void priv_reserve_no_capacity(size_type new_cap, version_2)
Chris@16 2241 {
Chris@16 2242 //There is not enough memory, allocate a new
Chris@16 2243 //buffer or expand the old one.
Chris@16 2244 bool same_buffer_start;
Chris@16 2245 size_type real_cap = 0;
Chris@101 2246 pointer reuse = 0;
Chris@101 2247 pointer const ret(this->m_holder.allocation_command(allocate_new | expand_fwd | expand_bwd, new_cap, real_cap = new_cap, reuse));
Chris@16 2248
Chris@16 2249 //Check for forward expansion
Chris@101 2250 same_buffer_start = reuse && this->m_holder.start() == ret;
Chris@16 2251 if(same_buffer_start){
Chris@16 2252 #ifdef BOOST_CONTAINER_VECTOR_ALLOC_STATS
Chris@16 2253 ++this->num_expand_fwd;
Chris@16 2254 #endif
Chris@16 2255 this->m_holder.capacity(real_cap);
Chris@16 2256 }
Chris@101 2257 else{ //If there is no forward expansion, move objects, we will reuse insertion code
Chris@101 2258 T * const new_mem = container_detail::to_raw_pointer(ret);
Chris@101 2259 T * const ins_pos = this->back_raw();
Chris@101 2260 if(reuse){ //Backwards (and possibly forward) expansion
Chris@16 2261 #ifdef BOOST_CONTAINER_VECTOR_ALLOC_STATS
Chris@16 2262 ++this->num_expand_bwd;
Chris@16 2263 #endif
Chris@16 2264 this->priv_forward_range_insert_expand_backwards
Chris@101 2265 ( new_mem , real_cap, ins_pos, 0, this->priv_dummy_empty_proxy());
Chris@16 2266 }
Chris@101 2267 else{ //New buffer
Chris@16 2268 #ifdef BOOST_CONTAINER_VECTOR_ALLOC_STATS
Chris@16 2269 ++this->num_alloc;
Chris@16 2270 #endif
Chris@101 2271 this->priv_forward_range_insert_new_allocation
Chris@101 2272 ( new_mem, real_cap, ins_pos, 0, this->priv_dummy_empty_proxy());
Chris@16 2273 }
Chris@16 2274 }
Chris@16 2275 }
Chris@16 2276
Chris@101 2277 void priv_destroy_last() BOOST_NOEXCEPT_OR_NOTHROW
Chris@16 2278 {
Chris@101 2279 if(!value_traits::trivial_dctr){
Chris@101 2280 value_type* const p = this->back_raw() - 1;
Chris@101 2281 allocator_traits_type::destroy(this->get_stored_allocator(), p);
Chris@101 2282 }
Chris@101 2283 --this->m_holder.m_size;
Chris@16 2284 }
Chris@16 2285
Chris@101 2286 void priv_destroy_last(const bool moved) BOOST_NOEXCEPT_OR_NOTHROW
Chris@16 2287 {
Chris@101 2288 (void)moved;
Chris@101 2289 if(!(value_traits::trivial_dctr || (value_traits::trivial_dctr_after_move && moved))){
Chris@101 2290 value_type* const p = this->back_raw() - 1;
Chris@16 2291 allocator_traits_type::destroy(this->get_stored_allocator(), p);
Chris@101 2292 }
Chris@101 2293 --this->m_holder.m_size;
Chris@16 2294 }
Chris@16 2295
Chris@101 2296 void priv_destroy_last_n(const size_type n) BOOST_NOEXCEPT_OR_NOTHROW
Chris@16 2297 {
Chris@101 2298 BOOST_ASSERT(n <= this->m_holder.m_size);
Chris@101 2299 if(!value_traits::trivial_dctr){
Chris@101 2300 T* const destroy_pos = container_detail::to_raw_pointer(this->m_holder.start()) + (this->m_holder.m_size-n);
Chris@101 2301 boost::container::destroy_alloc_n(this->get_stored_allocator(), destroy_pos, n);
Chris@101 2302 }
Chris@16 2303 this->m_holder.m_size -= n;
Chris@16 2304 }
Chris@16 2305
Chris@101 2306 void priv_destroy_last_n(const size_type n, const bool moved) BOOST_NOEXCEPT_OR_NOTHROW
Chris@101 2307 {
Chris@101 2308 BOOST_ASSERT(n <= this->m_holder.m_size);
Chris@101 2309 (void)moved;
Chris@101 2310 if(!(value_traits::trivial_dctr || (value_traits::trivial_dctr_after_move && moved))){
Chris@101 2311 T* const destroy_pos = container_detail::to_raw_pointer(this->m_holder.start()) + (this->m_holder.m_size-n);
Chris@101 2312 boost::container::destroy_alloc_n(this->get_stored_allocator(), destroy_pos, n);
Chris@101 2313 }
Chris@101 2314 this->m_holder.m_size -= n;
Chris@101 2315 }
Chris@101 2316
Chris@101 2317 template<class InpIt>
Chris@101 2318 void priv_uninitialized_construct_at_end(InpIt first, InpIt last)
Chris@101 2319 {
Chris@101 2320 T* const old_end_pos = this->back_raw();
Chris@101 2321 T* const new_end_pos = boost::container::uninitialized_copy_alloc(this->m_holder.alloc(), first, last, old_end_pos);
Chris@101 2322 this->m_holder.m_size += new_end_pos - old_end_pos;
Chris@101 2323 }
Chris@101 2324
Chris@101 2325 void priv_destroy_all() BOOST_NOEXCEPT_OR_NOTHROW
Chris@16 2326 {
Chris@16 2327 boost::container::destroy_alloc_n
Chris@16 2328 (this->get_stored_allocator(), container_detail::to_raw_pointer(this->m_holder.start()), this->m_holder.m_size);
Chris@16 2329 this->m_holder.m_size = 0;
Chris@16 2330 }
Chris@16 2331
Chris@16 2332 template<class U>
Chris@16 2333 iterator priv_insert(const const_iterator &p, BOOST_FWD_REF(U) x)
Chris@16 2334 {
Chris@16 2335 return this->priv_forward_range_insert
Chris@101 2336 ( vector_iterator_get_ptr(p), 1, container_detail::get_insert_value_proxy<T*, Allocator>(::boost::forward<U>(x)));
Chris@16 2337 }
Chris@16 2338
Chris@101 2339 container_detail::insert_copy_proxy<Allocator, T*> priv_single_insert_proxy(const T &x)
Chris@101 2340 { return container_detail::insert_copy_proxy<Allocator, T*> (x); }
Chris@101 2341
Chris@101 2342 container_detail::insert_move_proxy<Allocator, T*> priv_single_insert_proxy(BOOST_RV_REF(T) x)
Chris@101 2343 { return container_detail::insert_move_proxy<Allocator, T*> (x); }
Chris@101 2344
Chris@101 2345 template <class U>
Chris@101 2346 void priv_push_back(BOOST_FWD_REF(U) u)
Chris@16 2347 {
Chris@101 2348 if (BOOST_LIKELY(this->room_enough())){
Chris@16 2349 //There is more memory, just construct a new object at the end
Chris@16 2350 allocator_traits_type::construct
Chris@16 2351 ( this->m_holder.alloc()
Chris@16 2352 , container_detail::to_raw_pointer(this->m_holder.start() + this->m_holder.m_size)
Chris@101 2353 , ::boost::forward<U>(u) );
Chris@16 2354 ++this->m_holder.m_size;
Chris@16 2355 }
Chris@16 2356 else{
Chris@101 2357 this->priv_forward_range_insert_no_capacity
Chris@101 2358 ( this->back_ptr(), 1
Chris@101 2359 , this->priv_single_insert_proxy(::boost::forward<U>(u)), alloc_version());
Chris@16 2360 }
Chris@16 2361 }
Chris@16 2362
Chris@101 2363 container_detail::insert_n_copies_proxy<Allocator, T*> priv_resize_proxy(const T &x)
Chris@101 2364 { return container_detail::insert_n_copies_proxy<Allocator, T*>(x); }
Chris@101 2365
Chris@101 2366 container_detail::insert_default_initialized_n_proxy<Allocator, T*> priv_resize_proxy(default_init_t)
Chris@101 2367 { return container_detail::insert_default_initialized_n_proxy<Allocator, T*>(); }
Chris@101 2368
Chris@101 2369 container_detail::insert_value_initialized_n_proxy<Allocator, T*> priv_resize_proxy(value_init_t)
Chris@101 2370 { return container_detail::insert_value_initialized_n_proxy<Allocator, T*>(); }
Chris@101 2371
Chris@101 2372 template <class U>
Chris@101 2373 void priv_resize(size_type new_size, const U& u)
Chris@16 2374 {
Chris@101 2375 const size_type sz = this->size();
Chris@101 2376 if (new_size < sz){
Chris@101 2377 //Destroy last elements
Chris@101 2378 this->priv_destroy_last_n(sz - new_size);
Chris@16 2379 }
Chris@16 2380 else{
Chris@101 2381 const size_type n = new_size - this->size();
Chris@101 2382 this->priv_forward_range_insert_at_end(n, this->priv_resize_proxy(u), alloc_version());
Chris@16 2383 }
Chris@16 2384 }
Chris@16 2385
Chris@101 2386 void priv_shrink_to_fit(version_0) BOOST_NOEXCEPT_OR_NOTHROW
Chris@16 2387 {}
Chris@16 2388
Chris@101 2389 void priv_shrink_to_fit(version_1)
Chris@16 2390 {
Chris@16 2391 const size_type cp = this->m_holder.capacity();
Chris@16 2392 if(cp){
Chris@16 2393 const size_type sz = this->size();
Chris@16 2394 if(!sz){
Chris@16 2395 this->m_holder.alloc().deallocate(this->m_holder.m_start, cp);
Chris@16 2396 this->m_holder.m_start = pointer();
Chris@16 2397 this->m_holder.m_capacity = 0;
Chris@16 2398 }
Chris@16 2399 else if(sz < cp){
Chris@16 2400 //Allocate a new buffer.
Chris@101 2401 //Pass the hint so that allocators can take advantage of this.
Chris@101 2402 pointer const p = allocator_traits_type::allocate(this->m_holder.alloc(), sz, this->m_holder.m_start);
Chris@16 2403
Chris@16 2404 //We will reuse insert code, so create a dummy input iterator
Chris@16 2405 #ifdef BOOST_CONTAINER_VECTOR_ALLOC_STATS
Chris@16 2406 ++this->num_alloc;
Chris@16 2407 #endif
Chris@16 2408 this->priv_forward_range_insert_new_allocation
Chris@101 2409 ( container_detail::to_raw_pointer(p), sz
Chris@16 2410 , container_detail::to_raw_pointer(this->m_holder.start())
Chris@101 2411 , 0, this->priv_dummy_empty_proxy());
Chris@16 2412 }
Chris@16 2413 }
Chris@16 2414 }
Chris@16 2415
Chris@101 2416 void priv_shrink_to_fit(version_2) BOOST_NOEXCEPT_OR_NOTHROW
Chris@16 2417 {
Chris@16 2418 const size_type cp = this->m_holder.capacity();
Chris@16 2419 if(cp){
Chris@16 2420 const size_type sz = this->size();
Chris@16 2421 if(!sz){
Chris@16 2422 this->m_holder.alloc().deallocate(this->m_holder.m_start, cp);
Chris@16 2423 this->m_holder.m_start = pointer();
Chris@16 2424 this->m_holder.m_capacity = 0;
Chris@16 2425 }
Chris@16 2426 else{
Chris@101 2427 size_type received_size = sz;
Chris@101 2428 pointer reuse(this->m_holder.start());
Chris@16 2429 if(this->m_holder.allocation_command
Chris@101 2430 (shrink_in_place | nothrow_allocation, cp, received_size, reuse)){
Chris@16 2431 this->m_holder.capacity(received_size);
Chris@16 2432 #ifdef BOOST_CONTAINER_VECTOR_ALLOC_STATS
Chris@16 2433 ++this->num_shrink;
Chris@16 2434 #endif
Chris@16 2435 }
Chris@16 2436 }
Chris@16 2437 }
Chris@16 2438 }
Chris@16 2439
Chris@16 2440 template <class InsertionProxy>
Chris@16 2441 iterator priv_forward_range_insert_no_capacity
Chris@101 2442 (const pointer &pos, const size_type, const InsertionProxy , version_0)
Chris@16 2443 {
Chris@16 2444 throw_bad_alloc();
Chris@16 2445 return iterator(pos);
Chris@16 2446 }
Chris@16 2447
Chris@16 2448 template <class InsertionProxy>
Chris@16 2449 iterator priv_forward_range_insert_no_capacity
Chris@101 2450 (const pointer &pos, const size_type n, const InsertionProxy insert_range_proxy, version_1)
Chris@16 2451 {
Chris@16 2452 //Check if we have enough memory or try to expand current memory
Chris@16 2453 const size_type n_pos = pos - this->m_holder.start();
Chris@16 2454 T *const raw_pos = container_detail::to_raw_pointer(pos);
Chris@16 2455
Chris@16 2456 const size_type new_cap = this->m_holder.next_capacity(n);
Chris@101 2457 //Pass the hint so that allocators can take advantage of this.
Chris@101 2458 T * const new_buf = container_detail::to_raw_pointer(allocator_traits_type::allocate(this->m_holder.alloc(), new_cap, this->m_holder.m_start));
Chris@16 2459 #ifdef BOOST_CONTAINER_VECTOR_ALLOC_STATS
Chris@16 2460 ++this->num_alloc;
Chris@16 2461 #endif
Chris@16 2462 this->priv_forward_range_insert_new_allocation
Chris@16 2463 ( new_buf, new_cap, raw_pos, n, insert_range_proxy);
Chris@16 2464 return iterator(this->m_holder.start() + n_pos);
Chris@16 2465 }
Chris@16 2466
Chris@16 2467 template <class InsertionProxy>
Chris@16 2468 iterator priv_forward_range_insert_no_capacity
Chris@101 2469 (const pointer &pos, const size_type n, const InsertionProxy insert_range_proxy, version_2)
Chris@16 2470 {
Chris@16 2471 //Check if we have enough memory or try to expand current memory
Chris@16 2472 T *const raw_pos = container_detail::to_raw_pointer(pos);
Chris@16 2473 const size_type n_pos = raw_pos - container_detail::to_raw_pointer(this->m_holder.start());
Chris@16 2474
Chris@16 2475 //There is not enough memory, allocate a new
Chris@16 2476 //buffer or expand the old one.
Chris@101 2477 size_type real_cap = this->m_holder.next_capacity(n);
Chris@101 2478 pointer reuse(this->m_holder.start());
Chris@101 2479 pointer const ret (this->m_holder.allocation_command
Chris@101 2480 (allocate_new | expand_fwd | expand_bwd, this->m_holder.m_size + n, real_cap, reuse));
Chris@16 2481
Chris@16 2482 //Buffer reallocated
Chris@101 2483 if(reuse){
Chris@16 2484 //Forward expansion, delay insertion
Chris@101 2485 if(this->m_holder.start() == ret){
Chris@16 2486 #ifdef BOOST_CONTAINER_VECTOR_ALLOC_STATS
Chris@16 2487 ++this->num_expand_fwd;
Chris@16 2488 #endif
Chris@16 2489 this->m_holder.capacity(real_cap);
Chris@16 2490 //Expand forward
Chris@16 2491 this->priv_forward_range_insert_expand_forward(raw_pos, n, insert_range_proxy);
Chris@16 2492 }
Chris@16 2493 //Backwards (and possibly forward) expansion
Chris@16 2494 else{
Chris@16 2495 #ifdef BOOST_CONTAINER_VECTOR_ALLOC_STATS
Chris@16 2496 ++this->num_expand_bwd;
Chris@16 2497 #endif
Chris@16 2498 this->priv_forward_range_insert_expand_backwards
Chris@101 2499 (container_detail::to_raw_pointer(ret), real_cap, raw_pos, n, insert_range_proxy);
Chris@16 2500 }
Chris@16 2501 }
Chris@16 2502 //New buffer
Chris@16 2503 else{
Chris@16 2504 #ifdef BOOST_CONTAINER_VECTOR_ALLOC_STATS
Chris@16 2505 ++this->num_alloc;
Chris@16 2506 #endif
Chris@16 2507 this->priv_forward_range_insert_new_allocation
Chris@101 2508 ( container_detail::to_raw_pointer(ret), real_cap, raw_pos, n, insert_range_proxy);
Chris@16 2509 }
Chris@16 2510
Chris@16 2511 return iterator(this->m_holder.start() + n_pos);
Chris@16 2512 }
Chris@16 2513
Chris@16 2514 template <class InsertionProxy>
Chris@16 2515 iterator priv_forward_range_insert
Chris@101 2516 (const pointer &pos, const size_type n, const InsertionProxy insert_range_proxy)
Chris@16 2517 {
Chris@101 2518 BOOST_ASSERT(this->m_holder.capacity() >= this->m_holder.m_size);
Chris@16 2519 //Check if we have enough memory or try to expand current memory
Chris@16 2520 const size_type remaining = this->m_holder.capacity() - this->m_holder.m_size;
Chris@16 2521
Chris@16 2522 bool same_buffer_start = n <= remaining;
Chris@16 2523 if (!same_buffer_start){
Chris@16 2524 return priv_forward_range_insert_no_capacity(pos, n, insert_range_proxy, alloc_version());
Chris@16 2525 }
Chris@16 2526 else{
Chris@16 2527 //Expand forward
Chris@16 2528 T *const raw_pos = container_detail::to_raw_pointer(pos);
Chris@16 2529 const size_type n_pos = raw_pos - container_detail::to_raw_pointer(this->m_holder.start());
Chris@16 2530 this->priv_forward_range_insert_expand_forward(raw_pos, n, insert_range_proxy);
Chris@16 2531 return iterator(this->m_holder.start() + n_pos);
Chris@16 2532 }
Chris@16 2533 }
Chris@16 2534
Chris@16 2535 template <class InsertionProxy>
Chris@16 2536 iterator priv_forward_range_insert_at_end
Chris@101 2537 (const size_type n, const InsertionProxy insert_range_proxy, version_0)
Chris@16 2538 {
Chris@16 2539 //Check if we have enough memory or try to expand current memory
Chris@16 2540 const size_type remaining = this->m_holder.capacity() - this->m_holder.m_size;
Chris@16 2541
Chris@16 2542 if (n > remaining){
Chris@16 2543 //This will trigger an error
Chris@16 2544 throw_bad_alloc();
Chris@16 2545 }
Chris@16 2546 this->priv_forward_range_insert_at_end_expand_forward(n, insert_range_proxy);
Chris@16 2547 return this->end();
Chris@16 2548 }
Chris@16 2549
Chris@101 2550 template <class InsertionProxy, class AllocVersion>
Chris@16 2551 iterator priv_forward_range_insert_at_end
Chris@101 2552 (const size_type n, const InsertionProxy insert_range_proxy, AllocVersion)
Chris@16 2553 {
Chris@101 2554 return this->priv_forward_range_insert(this->back_ptr(), n, insert_range_proxy);
Chris@16 2555 }
Chris@16 2556
Chris@16 2557 //Absolutely experimental. This function might change, disappear or simply crash!
Chris@16 2558 template<class BiDirPosConstIt, class BiDirSkipConstIt, class BiDirValueIt>
Chris@16 2559 void priv_insert_ordered_at( size_type element_count, BiDirPosConstIt last_position_it
Chris@16 2560 , bool do_skip, BiDirSkipConstIt last_skip_it, BiDirValueIt last_value_it)
Chris@16 2561 {
Chris@16 2562 const size_type old_size_pos = this->size();
Chris@16 2563 this->reserve(old_size_pos + element_count);
Chris@16 2564 T* const begin_ptr = container_detail::to_raw_pointer(this->m_holder.start());
Chris@16 2565 size_type insertions_left = element_count;
Chris@16 2566 size_type next_pos = old_size_pos;
Chris@16 2567 size_type hole_size = element_count;
Chris@16 2568
Chris@16 2569 //Exception rollback. If any copy throws before the hole is filled, values
Chris@16 2570 //already inserted/copied at the end of the buffer will be destroyed.
Chris@16 2571 typename value_traits::ArrayDestructor past_hole_values_destroyer
Chris@16 2572 (begin_ptr + old_size_pos + element_count, this->m_holder.alloc(), size_type(0u));
Chris@16 2573 //Loop for each insertion backwards, first moving the elements after the insertion point,
Chris@16 2574 //then inserting the element.
Chris@16 2575 while(insertions_left){
Chris@16 2576 if(do_skip){
Chris@16 2577 size_type n = *(--last_skip_it);
Chris@101 2578 boost::container::iterator_advance(last_value_it, -difference_type(n));
Chris@16 2579 }
Chris@16 2580 const size_type pos = static_cast<size_type>(*(--last_position_it));
Chris@16 2581 BOOST_ASSERT(pos <= old_size_pos);
Chris@16 2582 //If needed shift the range after the insertion point and the previous insertion point.
Chris@16 2583 //Function will take care if the shift crosses the size() boundary, using copy/move
Chris@16 2584 //or uninitialized copy/move if necessary.
Chris@16 2585 size_type new_hole_size = (pos != next_pos)
Chris@16 2586 ? priv_insert_ordered_at_shift_range(pos, next_pos, this->size(), insertions_left)
Chris@16 2587 : hole_size
Chris@16 2588 ;
Chris@16 2589 if(new_hole_size > 0){
Chris@16 2590 //The hole was reduced by priv_insert_ordered_at_shift_range so expand exception rollback range backwards
Chris@16 2591 past_hole_values_destroyer.increment_size_backwards(next_pos - pos);
Chris@16 2592 //Insert the new value in the hole
Chris@16 2593 allocator_traits_type::construct(this->m_holder.alloc(), begin_ptr + pos + insertions_left - 1, *(--last_value_it));
Chris@16 2594 --new_hole_size;
Chris@16 2595 if(new_hole_size == 0){
Chris@16 2596 //Hole was just filled, disable exception rollback and change vector size
Chris@16 2597 past_hole_values_destroyer.release();
Chris@16 2598 this->m_holder.m_size += element_count;
Chris@16 2599 }
Chris@16 2600 else{
Chris@16 2601 //The hole was reduced by the new insertion by one
Chris@16 2602 past_hole_values_destroyer.increment_size_backwards(size_type(1u));
Chris@16 2603 }
Chris@16 2604 }
Chris@16 2605 else{
Chris@16 2606 if(hole_size){
Chris@16 2607 //Hole was just filled by priv_insert_ordered_at_shift_range, disable exception rollback and change vector size
Chris@16 2608 past_hole_values_destroyer.release();
Chris@16 2609 this->m_holder.m_size += element_count;
Chris@16 2610 }
Chris@16 2611 //Insert the new value in the already constructed range
Chris@16 2612 begin_ptr[pos + insertions_left - 1] = *(--last_value_it);
Chris@16 2613 }
Chris@16 2614 --insertions_left;
Chris@16 2615 hole_size = new_hole_size;
Chris@16 2616 next_pos = pos;
Chris@16 2617 }
Chris@16 2618 }
Chris@16 2619
Chris@16 2620 //Takes the range pointed by [first_pos, last_pos) and shifts it to the right
Chris@16 2621 //by 'shift_count'. 'limit_pos' marks the end of constructed elements.
Chris@16 2622 //
Chris@16 2623 //Precondition: first_pos <= last_pos <= limit_pos
Chris@16 2624 //
Chris@16 2625 //The shift operation might cross limit_pos so elements to moved beyond limit_pos
Chris@16 2626 //are uninitialized_moved with an allocator. Other elements are moved.
Chris@16 2627 //
Chris@16 2628 //The shift operation might left uninitialized elements after limit_pos
Chris@16 2629 //and the number of uninitialized elements is returned by the function.
Chris@16 2630 //
Chris@16 2631 //Old situation:
Chris@16 2632 // first_pos last_pos old_limit
Chris@101 2633 // | | |
Chris@16 2634 // ____________V_______V__________________V_____________
Chris@16 2635 //| prefix | range | suffix |raw_mem ~
Chris@16 2636 //|____________|_______|__________________|_____________~
Chris@16 2637 //
Chris@101 2638 //New situation in Case A (hole_size == 0):
Chris@16 2639 // range is moved through move assignments
Chris@16 2640 //
Chris@16 2641 // first_pos last_pos limit_pos
Chris@101 2642 // | | |
Chris@16 2643 // ____________V_______V__________________V_____________
Chris@16 2644 //| prefix' | | | range |suffix'|raw_mem ~
Chris@16 2645 //|________________+______|___^___|_______|_____________~
Chris@16 2646 // | |
Chris@101 2647 // |_>_>_>_>_>^
Chris@16 2648 //
Chris@16 2649 //
Chris@16 2650 //New situation in Case B (hole_size > 0):
Chris@16 2651 // range is moved through uninitialized moves
Chris@16 2652 //
Chris@16 2653 // first_pos last_pos limit_pos
Chris@101 2654 // | | |
Chris@16 2655 // ____________V_______V__________________V________________
Chris@16 2656 //| prefix' | | | [hole] | range |
Chris@16 2657 //|_______________________________________|________|___^___|
Chris@16 2658 // | |
Chris@16 2659 // |_>_>_>_>_>_>_>_>_>_>_>_>_>_>_>_>_>_^
Chris@16 2660 //
Chris@16 2661 //New situation in Case C (hole_size == 0):
Chris@16 2662 // range is moved through move assignments and uninitialized moves
Chris@16 2663 //
Chris@16 2664 // first_pos last_pos limit_pos
Chris@101 2665 // | | |
Chris@16 2666 // ____________V_______V__________________V___
Chris@16 2667 //| prefix' | | | range |
Chris@16 2668 //|___________________________________|___^___|
Chris@16 2669 // | |
Chris@16 2670 // |_>_>_>_>_>_>_>_>_>_>_>^
Chris@16 2671 size_type priv_insert_ordered_at_shift_range
Chris@16 2672 (size_type first_pos, size_type last_pos, size_type limit_pos, size_type shift_count)
Chris@16 2673 {
Chris@16 2674 BOOST_ASSERT(first_pos <= last_pos);
Chris@16 2675 BOOST_ASSERT(last_pos <= limit_pos);
Chris@16 2676 //
Chris@16 2677 T* const begin_ptr = container_detail::to_raw_pointer(this->m_holder.start());
Chris@16 2678 T* const first_ptr = begin_ptr + first_pos;
Chris@16 2679 T* const last_ptr = begin_ptr + last_pos;
Chris@16 2680
Chris@16 2681 size_type hole_size = 0;
Chris@101 2682 //Case A:
Chris@16 2683 if((last_pos + shift_count) <= limit_pos){
Chris@16 2684 //All move assigned
Chris@101 2685 boost::container::move_backward(first_ptr, last_ptr, last_ptr + shift_count);
Chris@16 2686 }
Chris@16 2687 //Case B:
Chris@16 2688 else if((first_pos + shift_count) >= limit_pos){
Chris@16 2689 //All uninitialized_moved
Chris@16 2690 ::boost::container::uninitialized_move_alloc
Chris@16 2691 (this->m_holder.alloc(), first_ptr, last_ptr, first_ptr + shift_count);
Chris@16 2692 hole_size = last_pos + shift_count - limit_pos;
Chris@16 2693 }
Chris@16 2694 //Case C:
Chris@16 2695 else{
Chris@16 2696 //Some uninitialized_moved
Chris@16 2697 T* const limit_ptr = begin_ptr + limit_pos;
Chris@16 2698 T* const boundary_ptr = limit_ptr - shift_count;
Chris@16 2699 ::boost::container::uninitialized_move_alloc(this->m_holder.alloc(), boundary_ptr, last_ptr, limit_ptr);
Chris@16 2700 //The rest is move assigned
Chris@101 2701 boost::container::move_backward(first_ptr, boundary_ptr, limit_ptr);
Chris@16 2702 }
Chris@16 2703 return hole_size;
Chris@16 2704 }
Chris@16 2705
Chris@16 2706 private:
Chris@16 2707 template <class InsertionProxy>
Chris@16 2708 void priv_forward_range_insert_at_end_expand_forward(const size_type n, InsertionProxy insert_range_proxy)
Chris@16 2709 {
Chris@101 2710 T* const old_finish = this->back_raw();
Chris@101 2711 insert_range_proxy.uninitialized_copy_n_and_update(this->m_holder.alloc(), old_finish, n);
Chris@16 2712 this->m_holder.m_size += n;
Chris@16 2713 }
Chris@16 2714
Chris@16 2715 template <class InsertionProxy>
Chris@16 2716 void priv_forward_range_insert_expand_forward(T* const pos, const size_type n, InsertionProxy insert_range_proxy)
Chris@16 2717 {
Chris@16 2718 //n can't be 0, because there is nothing to do in that case
Chris@16 2719 if(!n) return;
Chris@16 2720 //There is enough memory
Chris@101 2721 T* const old_finish = this->back_raw();
Chris@16 2722 const size_type elems_after = old_finish - pos;
Chris@16 2723
Chris@16 2724 if (!elems_after){
Chris@101 2725 insert_range_proxy.uninitialized_copy_n_and_update(this->m_holder.alloc(), old_finish, n);
Chris@16 2726 this->m_holder.m_size += n;
Chris@16 2727 }
Chris@16 2728 else if (elems_after >= n){
Chris@16 2729 //New elements can be just copied.
Chris@16 2730 //Move to uninitialized memory last objects
Chris@16 2731 ::boost::container::uninitialized_move_alloc
Chris@16 2732 (this->m_holder.alloc(), old_finish - n, old_finish, old_finish);
Chris@16 2733 this->m_holder.m_size += n;
Chris@16 2734 //Copy previous to last objects to the initialized end
Chris@101 2735 boost::container::move_backward(pos, old_finish - n, old_finish);
Chris@16 2736 //Insert new objects in the pos
Chris@101 2737 insert_range_proxy.copy_n_and_update(this->m_holder.alloc(), pos, n);
Chris@16 2738 }
Chris@16 2739 else {
Chris@16 2740 //The new elements don't fit in the [pos, end()) range.
Chris@16 2741
Chris@16 2742 //Copy old [pos, end()) elements to the uninitialized memory (a gap is created)
Chris@16 2743 ::boost::container::uninitialized_move_alloc(this->m_holder.alloc(), pos, old_finish, pos + n);
Chris@16 2744 BOOST_TRY{
Chris@16 2745 //Copy first new elements in pos (gap is still there)
Chris@101 2746 insert_range_proxy.copy_n_and_update(this->m_holder.alloc(), pos, elems_after);
Chris@16 2747 //Copy to the beginning of the unallocated zone the last new elements (the gap is closed).
Chris@101 2748 insert_range_proxy.uninitialized_copy_n_and_update(this->m_holder.alloc(), old_finish, n - elems_after);
Chris@16 2749 this->m_holder.m_size += n;
Chris@16 2750 }
Chris@16 2751 BOOST_CATCH(...){
Chris@16 2752 boost::container::destroy_alloc_n(this->get_stored_allocator(), pos + n, elems_after);
Chris@16 2753 BOOST_RETHROW
Chris@16 2754 }
Chris@16 2755 BOOST_CATCH_END
Chris@16 2756 }
Chris@16 2757 }
Chris@16 2758
Chris@16 2759 template <class InsertionProxy>
Chris@16 2760 void priv_forward_range_insert_new_allocation
Chris@16 2761 (T* const new_start, size_type new_cap, T* const pos, const size_type n, InsertionProxy insert_range_proxy)
Chris@16 2762 {
Chris@16 2763 //n can be zero, if we want to reallocate!
Chris@16 2764 T *new_finish = new_start;
Chris@16 2765 T *old_finish;
Chris@16 2766 //Anti-exception rollbacks
Chris@101 2767 typename value_traits::ArrayDeallocator new_buffer_deallocator(new_start, this->m_holder.alloc(), new_cap);
Chris@101 2768 typename value_traits::ArrayDestructor new_values_destroyer(new_start, this->m_holder.alloc(), 0u);
Chris@16 2769
Chris@16 2770 //Initialize with [begin(), pos) old buffer
Chris@16 2771 //the start of the new buffer
Chris@101 2772 T * const old_buffer = container_detail::to_raw_pointer(this->m_holder.start());
Chris@16 2773 if(old_buffer){
Chris@16 2774 new_finish = ::boost::container::uninitialized_move_alloc
Chris@16 2775 (this->m_holder.alloc(), container_detail::to_raw_pointer(this->m_holder.start()), pos, old_finish = new_finish);
Chris@101 2776 new_values_destroyer.increment_size(new_finish - old_finish);
Chris@16 2777 }
Chris@16 2778 //Initialize new objects, starting from previous point
Chris@101 2779 old_finish = new_finish;
Chris@101 2780 insert_range_proxy.uninitialized_copy_n_and_update(this->m_holder.alloc(), old_finish, n);
Chris@16 2781 new_finish += n;
Chris@101 2782 new_values_destroyer.increment_size(new_finish - old_finish);
Chris@16 2783 //Initialize from the rest of the old buffer,
Chris@16 2784 //starting from previous point
Chris@16 2785 if(old_buffer){
Chris@16 2786 new_finish = ::boost::container::uninitialized_move_alloc
Chris@16 2787 (this->m_holder.alloc(), pos, old_buffer + this->m_holder.m_size, new_finish);
Chris@16 2788 //Destroy and deallocate old elements
Chris@16 2789 //If there is allocated memory, destroy and deallocate
Chris@16 2790 if(!value_traits::trivial_dctr_after_move)
Chris@16 2791 boost::container::destroy_alloc_n(this->get_stored_allocator(), old_buffer, this->m_holder.m_size);
Chris@16 2792 this->m_holder.alloc().deallocate(this->m_holder.start(), this->m_holder.capacity());
Chris@16 2793 }
Chris@16 2794 this->m_holder.start(new_start);
Chris@16 2795 this->m_holder.m_size = new_finish - new_start;
Chris@16 2796 this->m_holder.capacity(new_cap);
Chris@16 2797 //All construction successful, disable rollbacks
Chris@101 2798 new_values_destroyer.release();
Chris@101 2799 new_buffer_deallocator.release();
Chris@16 2800 }
Chris@16 2801
Chris@16 2802 template <class InsertionProxy>
Chris@16 2803 void priv_forward_range_insert_expand_backwards
Chris@16 2804 (T* const new_start, const size_type new_capacity,
Chris@16 2805 T* const pos, const size_type n, InsertionProxy insert_range_proxy)
Chris@16 2806 {
Chris@16 2807 //n can be zero to just expand capacity
Chris@16 2808 //Backup old data
Chris@16 2809 T* const old_start = container_detail::to_raw_pointer(this->m_holder.start());
Chris@16 2810 const size_type old_size = this->m_holder.m_size;
Chris@101 2811 T* const old_finish = old_start + old_size;
Chris@16 2812
Chris@16 2813 //We can have 8 possibilities:
Chris@16 2814 const size_type elemsbefore = static_cast<size_type>(pos - old_start);
Chris@16 2815 const size_type s_before = static_cast<size_type>(old_start - new_start);
Chris@16 2816 const size_type before_plus_new = elemsbefore + n;
Chris@16 2817
Chris@16 2818 //Update the vector buffer information to a safe state
Chris@16 2819 this->m_holder.start(new_start);
Chris@16 2820 this->m_holder.capacity(new_capacity);
Chris@16 2821 this->m_holder.m_size = 0;
Chris@16 2822
Chris@16 2823 //If anything goes wrong, this object will destroy
Chris@16 2824 //all the old objects to fulfill previous vector state
Chris@101 2825 typename value_traits::ArrayDestructor old_values_destroyer(old_start, this->m_holder.alloc(), old_size);
Chris@16 2826 //Check if s_before is big enough to hold the beginning of old data + new data
Chris@16 2827 if(s_before >= before_plus_new){
Chris@16 2828 //Copy first old values before pos, after that the new objects
Chris@101 2829 T *const new_elem_pos =
Chris@101 2830 ::boost::container::uninitialized_move_alloc(this->m_holder.alloc(), old_start, pos, new_start);
Chris@16 2831 this->m_holder.m_size = elemsbefore;
Chris@101 2832 insert_range_proxy.uninitialized_copy_n_and_update(this->m_holder.alloc(), new_elem_pos, n);
Chris@101 2833 this->m_holder.m_size = before_plus_new;
Chris@101 2834 const size_type new_size = old_size + n;
Chris@16 2835 //Check if s_before is so big that even copying the old data + new data
Chris@16 2836 //there is a gap between the new data and the old data
Chris@16 2837 if(s_before >= new_size){
Chris@16 2838 //Old situation:
Chris@16 2839 // _________________________________________________________
Chris@16 2840 //| raw_mem | old_begin | old_end |
Chris@16 2841 //| __________________________________|___________|_________|
Chris@16 2842 //
Chris@16 2843 //New situation:
Chris@16 2844 // _________________________________________________________
Chris@16 2845 //| old_begin | new | old_end | raw_mem |
Chris@16 2846 //|___________|__________|_________|________________________|
Chris@16 2847 //
Chris@16 2848 //Now initialize the rest of memory with the last old values
Chris@101 2849 if(before_plus_new != new_size){ //Special case to avoid operations in back insertion
Chris@101 2850 ::boost::container::uninitialized_move_alloc
Chris@101 2851 (this->m_holder.alloc(), pos, old_finish, new_start + before_plus_new);
Chris@101 2852 //All new elements correctly constructed, avoid new element destruction
Chris@101 2853 this->m_holder.m_size = new_size;
Chris@101 2854 }
Chris@16 2855 //Old values destroyed automatically with "old_values_destroyer"
Chris@16 2856 //when "old_values_destroyer" goes out of scope unless the have trivial
Chris@16 2857 //destructor after move.
Chris@16 2858 if(value_traits::trivial_dctr_after_move)
Chris@16 2859 old_values_destroyer.release();
Chris@16 2860 }
Chris@16 2861 //s_before is so big that divides old_end
Chris@16 2862 else{
Chris@16 2863 //Old situation:
Chris@16 2864 // __________________________________________________
Chris@16 2865 //| raw_mem | old_begin | old_end |
Chris@16 2866 //| ___________________________|___________|_________|
Chris@16 2867 //
Chris@16 2868 //New situation:
Chris@16 2869 // __________________________________________________
Chris@16 2870 //| old_begin | new | old_end | raw_mem |
Chris@16 2871 //|___________|__________|_________|_________________|
Chris@16 2872 //
Chris@16 2873 //Now initialize the rest of memory with the last old values
Chris@16 2874 //All new elements correctly constructed, avoid new element destruction
Chris@16 2875 const size_type raw_gap = s_before - before_plus_new;
Chris@101 2876 if(!value_traits::trivial_dctr){
Chris@101 2877 //Now initialize the rest of s_before memory with the
Chris@101 2878 //first of elements after new values
Chris@101 2879 ::boost::container::uninitialized_move_alloc_n
Chris@101 2880 (this->m_holder.alloc(), pos, raw_gap, new_start + before_plus_new);
Chris@101 2881 //Now we have a contiguous buffer so program trailing element destruction
Chris@101 2882 //and update size to the final size.
Chris@101 2883 old_values_destroyer.shrink_forward(new_size-s_before);
Chris@101 2884 this->m_holder.m_size = new_size;
Chris@101 2885 //Now move remaining last objects in the old buffer begin
Chris@101 2886 ::boost::container::move(pos + raw_gap, old_finish, old_start);
Chris@101 2887 //Once moved, avoid calling the destructors if trivial after move
Chris@101 2888 if(value_traits::trivial_dctr_after_move){
Chris@101 2889 old_values_destroyer.release();
Chris@101 2890 }
Chris@101 2891 }
Chris@101 2892 else{ //If trivial destructor, we can uninitialized copy + copy in a single uninitialized copy
Chris@101 2893 ::boost::container::uninitialized_move_alloc_n
Chris@101 2894 (this->m_holder.alloc(), pos, old_finish - pos, new_start + before_plus_new);
Chris@101 2895 this->m_holder.m_size = new_size;
Chris@101 2896 old_values_destroyer.release();
Chris@101 2897 }
Chris@16 2898 }
Chris@16 2899 }
Chris@16 2900 else{
Chris@16 2901 //Check if we have to do the insertion in two phases
Chris@16 2902 //since maybe s_before is not big enough and
Chris@16 2903 //the buffer was expanded both sides
Chris@16 2904 //
Chris@16 2905 //Old situation:
Chris@16 2906 // _________________________________________________
Chris@16 2907 //| raw_mem | old_begin + old_end | raw_mem |
Chris@16 2908 //|_________|_____________________|_________________|
Chris@16 2909 //
Chris@16 2910 //New situation with do_after:
Chris@16 2911 // _________________________________________________
Chris@16 2912 //| old_begin + new + old_end | raw_mem |
Chris@16 2913 //|___________________________________|_____________|
Chris@16 2914 //
Chris@16 2915 //New without do_after:
Chris@16 2916 // _________________________________________________
Chris@16 2917 //| old_begin + new + old_end | raw_mem |
Chris@16 2918 //|____________________________|____________________|
Chris@16 2919 //
Chris@16 2920 const bool do_after = n > s_before;
Chris@16 2921
Chris@16 2922 //Now we can have two situations: the raw_mem of the
Chris@16 2923 //beginning divides the old_begin, or the new elements:
Chris@16 2924 if (s_before <= elemsbefore) {
Chris@16 2925 //The raw memory divides the old_begin group:
Chris@16 2926 //
Chris@16 2927 //If we need two phase construction (do_after)
Chris@16 2928 //new group is divided in new = new_beg + new_end groups
Chris@16 2929 //In this phase only new_beg will be inserted
Chris@16 2930 //
Chris@16 2931 //Old situation:
Chris@16 2932 // _________________________________________________
Chris@16 2933 //| raw_mem | old_begin | old_end | raw_mem |
Chris@16 2934 //|_________|___________|_________|_________________|
Chris@16 2935 //
Chris@16 2936 //New situation with do_after(1):
Chris@16 2937 //This is not definitive situation, the second phase
Chris@16 2938 //will include
Chris@16 2939 // _________________________________________________
Chris@16 2940 //| old_begin | new_beg | old_end | raw_mem |
Chris@16 2941 //|___________|_________|_________|_________________|
Chris@16 2942 //
Chris@16 2943 //New situation without do_after:
Chris@16 2944 // _________________________________________________
Chris@16 2945 //| old_begin | new | old_end | raw_mem |
Chris@16 2946 //|___________|_____|_________|_____________________|
Chris@16 2947 //
Chris@16 2948 //Copy the first part of old_begin to raw_mem
Chris@16 2949 ::boost::container::uninitialized_move_alloc_n
Chris@16 2950 (this->m_holder.alloc(), old_start, s_before, new_start);
Chris@16 2951 //The buffer is all constructed until old_end,
Chris@101 2952 //so program trailing destruction and assign final size
Chris@101 2953 //if !do_after, s_before+n otherwise.
Chris@101 2954 size_type new_1st_range;
Chris@16 2955 if(do_after){
Chris@101 2956 new_1st_range = s_before;
Chris@101 2957 //release destroyer and update size
Chris@101 2958 old_values_destroyer.release();
Chris@16 2959 }
Chris@16 2960 else{
Chris@101 2961 new_1st_range = n;
Chris@101 2962 if(value_traits::trivial_dctr_after_move)
Chris@101 2963 old_values_destroyer.release();
Chris@101 2964 else{
Chris@101 2965 old_values_destroyer.shrink_forward(old_size - (s_before - n));
Chris@101 2966 }
Chris@101 2967 }
Chris@101 2968 this->m_holder.m_size = old_size + new_1st_range;
Chris@101 2969 //Now copy the second part of old_begin overwriting itself
Chris@101 2970 T *const next = ::boost::container::move(old_start + s_before, pos, old_start);
Chris@101 2971 //Now copy the new_beg elements
Chris@101 2972 insert_range_proxy.copy_n_and_update(this->m_holder.alloc(), next, new_1st_range);
Chris@101 2973
Chris@101 2974 //If there is no after work and the last old part needs to be moved to front, do it
Chris@101 2975 if(!do_after && (n != s_before)){
Chris@16 2976 //Now displace old_end elements
Chris@101 2977 ::boost::container::move(pos, old_finish, next + new_1st_range);
Chris@16 2978 }
Chris@16 2979 }
Chris@16 2980 else {
Chris@16 2981 //If we have to expand both sides,
Chris@16 2982 //we will play if the first new values so
Chris@16 2983 //calculate the upper bound of new values
Chris@16 2984
Chris@16 2985 //The raw memory divides the new elements
Chris@16 2986 //
Chris@16 2987 //If we need two phase construction (do_after)
Chris@16 2988 //new group is divided in new = new_beg + new_end groups
Chris@16 2989 //In this phase only new_beg will be inserted
Chris@16 2990 //
Chris@16 2991 //Old situation:
Chris@16 2992 // _______________________________________________________
Chris@16 2993 //| raw_mem | old_begin | old_end | raw_mem |
Chris@16 2994 //|_______________|___________|_________|_________________|
Chris@16 2995 //
Chris@16 2996 //New situation with do_after():
Chris@16 2997 // ____________________________________________________
Chris@16 2998 //| old_begin | new_beg | old_end | raw_mem |
Chris@16 2999 //|___________|_______________|_________|______________|
Chris@16 3000 //
Chris@16 3001 //New situation without do_after:
Chris@16 3002 // ______________________________________________________
Chris@16 3003 //| old_begin | new | old_end | raw_mem |
Chris@16 3004 //|___________|_____|_________|__________________________|
Chris@16 3005 //
Chris@16 3006 //First copy whole old_begin and part of new to raw_mem
Chris@16 3007 T * const new_pos = ::boost::container::uninitialized_move_alloc
Chris@16 3008 (this->m_holder.alloc(), old_start, pos, new_start);
Chris@16 3009 this->m_holder.m_size = elemsbefore;
Chris@16 3010 const size_type mid_n = s_before - elemsbefore;
Chris@101 3011 insert_range_proxy.uninitialized_copy_n_and_update(this->m_holder.alloc(), new_pos, mid_n);
Chris@16 3012 //The buffer is all constructed until old_end,
Chris@16 3013 //release destroyer
Chris@16 3014 this->m_holder.m_size = old_size + s_before;
Chris@16 3015 old_values_destroyer.release();
Chris@16 3016
Chris@16 3017 if(do_after){
Chris@16 3018 //Copy new_beg part
Chris@101 3019 insert_range_proxy.copy_n_and_update(this->m_holder.alloc(), old_start, elemsbefore);
Chris@16 3020 }
Chris@16 3021 else{
Chris@16 3022 //Copy all new elements
Chris@16 3023 const size_type rest_new = n - mid_n;
Chris@101 3024 insert_range_proxy.copy_n_and_update(this->m_holder.alloc(), old_start, rest_new);
Chris@101 3025 T* const move_start = old_start + rest_new;
Chris@16 3026 //Displace old_end
Chris@101 3027 T* const move_end = ::boost::container::move(pos, old_finish, move_start);
Chris@16 3028 //Destroy remaining moved elements from old_end except if they
Chris@16 3029 //have trivial destructor after being moved
Chris@16 3030 size_type n_destroy = s_before - n;
Chris@16 3031 if(!value_traits::trivial_dctr_after_move)
Chris@16 3032 boost::container::destroy_alloc_n(this->get_stored_allocator(), move_end, n_destroy);
Chris@16 3033 this->m_holder.m_size -= n_destroy;
Chris@16 3034 }
Chris@16 3035 }
Chris@16 3036
Chris@16 3037 //This is only executed if two phase construction is needed
Chris@16 3038 if(do_after){
Chris@16 3039 //The raw memory divides the new elements
Chris@16 3040 //
Chris@16 3041 //Old situation:
Chris@16 3042 // ______________________________________________________
Chris@16 3043 //| raw_mem | old_begin | old_end | raw_mem |
Chris@16 3044 //|______________|___________|____________|______________|
Chris@16 3045 //
Chris@16 3046 //New situation with do_after(1):
Chris@16 3047 // _______________________________________________________
Chris@16 3048 //| old_begin + new_beg | new_end |old_end | raw_mem |
Chris@16 3049 //|__________________________|_________|________|_________|
Chris@16 3050 //
Chris@16 3051 //New situation with do_after(2):
Chris@16 3052 // ______________________________________________________
Chris@16 3053 //| old_begin + new | old_end |raw |
Chris@16 3054 //|_______________________________________|_________|____|
Chris@16 3055 //
Chris@16 3056 const size_type n_after = n - s_before;
Chris@16 3057 const size_type elemsafter = old_size - elemsbefore;
Chris@16 3058
Chris@16 3059 //We can have two situations:
Chris@16 3060 if (elemsafter >= n_after){
Chris@16 3061 //The raw_mem from end will divide displaced old_end
Chris@16 3062 //
Chris@16 3063 //Old situation:
Chris@16 3064 // ______________________________________________________
Chris@16 3065 //| raw_mem | old_begin | old_end | raw_mem |
Chris@16 3066 //|______________|___________|____________|______________|
Chris@16 3067 //
Chris@16 3068 //New situation with do_after(1):
Chris@16 3069 // _______________________________________________________
Chris@16 3070 //| old_begin + new_beg | new_end |old_end | raw_mem |
Chris@16 3071 //|__________________________|_________|________|_________|
Chris@16 3072 //
Chris@16 3073 //First copy the part of old_end raw_mem
Chris@16 3074 T* finish_n = old_finish - n_after;
Chris@16 3075 ::boost::container::uninitialized_move_alloc
Chris@16 3076 (this->m_holder.alloc(), finish_n, old_finish, old_finish);
Chris@16 3077 this->m_holder.m_size += n_after;
Chris@16 3078 //Displace the rest of old_end to the new position
Chris@101 3079 boost::container::move_backward(pos, finish_n, old_finish);
Chris@16 3080 //Now overwrite with new_end
Chris@16 3081 //The new_end part is [first + (n - n_after), last)
Chris@101 3082 insert_range_proxy.copy_n_and_update(this->m_holder.alloc(), pos, n_after);
Chris@16 3083 }
Chris@16 3084 else {
Chris@16 3085 //The raw_mem from end will divide new_end part
Chris@16 3086 //
Chris@16 3087 //Old situation:
Chris@16 3088 // _____________________________________________________________
Chris@16 3089 //| raw_mem | old_begin | old_end | raw_mem |
Chris@16 3090 //|______________|___________|____________|_____________________|
Chris@16 3091 //
Chris@16 3092 //New situation with do_after(2):
Chris@16 3093 // _____________________________________________________________
Chris@16 3094 //| old_begin + new_beg | new_end |old_end | raw_mem |
Chris@16 3095 //|__________________________|_______________|________|_________|
Chris@16 3096 //
Chris@16 3097
Chris@16 3098 const size_type mid_last_dist = n_after - elemsafter;
Chris@16 3099 //First initialize data in raw memory
Chris@16 3100
Chris@16 3101 //Copy to the old_end part to the uninitialized zone leaving a gap.
Chris@16 3102 ::boost::container::uninitialized_move_alloc
Chris@16 3103 (this->m_holder.alloc(), pos, old_finish, old_finish + mid_last_dist);
Chris@16 3104
Chris@101 3105 typename value_traits::ArrayDestructor old_end_destroyer
Chris@101 3106 (old_finish + mid_last_dist, this->m_holder.alloc(), old_finish - pos);
Chris@16 3107
Chris@101 3108 //Copy the first part to the already constructed old_end zone
Chris@101 3109 insert_range_proxy.copy_n_and_update(this->m_holder.alloc(), pos, elemsafter);
Chris@101 3110 //Copy the rest to the uninitialized zone filling the gap
Chris@101 3111 insert_range_proxy.uninitialized_copy_n_and_update(this->m_holder.alloc(), old_finish, mid_last_dist);
Chris@101 3112 this->m_holder.m_size += n_after;
Chris@101 3113 old_end_destroyer.release();
Chris@16 3114 }
Chris@16 3115 }
Chris@16 3116 }
Chris@16 3117 }
Chris@16 3118
Chris@16 3119 void priv_check_range(size_type n) const
Chris@16 3120 {
Chris@16 3121 //If n is out of range, throw an out_of_range exception
Chris@16 3122 if (n >= this->size()){
Chris@16 3123 throw_out_of_range("vector::at out of range");
Chris@16 3124 }
Chris@16 3125 }
Chris@16 3126
Chris@16 3127 #ifdef BOOST_CONTAINER_VECTOR_ALLOC_STATS
Chris@16 3128 public:
Chris@16 3129 unsigned int num_expand_fwd;
Chris@16 3130 unsigned int num_expand_bwd;
Chris@16 3131 unsigned int num_shrink;
Chris@16 3132 unsigned int num_alloc;
Chris@16 3133 void reset_alloc_stats()
Chris@16 3134 { num_expand_fwd = num_expand_bwd = num_alloc = 0, num_shrink = 0; }
Chris@16 3135 #endif
Chris@101 3136 #endif //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
Chris@16 3137 };
Chris@16 3138
Chris@101 3139 }} //namespace boost::container
Chris@16 3140
Chris@101 3141 #ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
Chris@16 3142
Chris@16 3143 namespace boost {
Chris@16 3144
Chris@16 3145 //!has_trivial_destructor_after_move<> == true_type
Chris@16 3146 //!specialization for optimizations
Chris@16 3147 template <class T, class Allocator>
Chris@16 3148 struct has_trivial_destructor_after_move<boost::container::vector<T, Allocator> >
Chris@101 3149 {
Chris@101 3150 typedef typename ::boost::container::allocator_traits<Allocator>::pointer pointer;
Chris@101 3151 static const bool value = ::boost::has_trivial_destructor_after_move<Allocator>::value &&
Chris@101 3152 ::boost::has_trivial_destructor_after_move<pointer>::value;
Chris@101 3153 };
Chris@16 3154
Chris@16 3155 }
Chris@16 3156
Chris@101 3157 #endif //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
Chris@16 3158
Chris@16 3159 #include <boost/container/detail/config_end.hpp>
Chris@16 3160
Chris@16 3161 #endif // #ifndef BOOST_CONTAINER_CONTAINER_VECTOR_HPP