1 ////////////////////////////////////////////////////////////////////////////// 2 // 3 // (C) Copyright Ion Gaztanaga 2005-2015. Distributed under the Boost 4 // Software License, Version 1.0. (See accompanying file 5 // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) 6 // 7 // See http://www.boost.org/libs/container for documentation. 8 // 9 ////////////////////////////////////////////////////////////////////////////// 10 #ifndef BOOST_CONTAINER_DEQUE_HPP 11 #define BOOST_CONTAINER_DEQUE_HPP 12 13 #ifndef BOOST_CONFIG_HPP 14 # include <boost/config.hpp> 15 #endif 16 17 #if defined(BOOST_HAS_PRAGMA_ONCE) 18 # pragma once 19 #endif 20 21 #include <boost/container/detail/config_begin.hpp> 22 #include <boost/container/detail/workaround.hpp> 23 // container 24 #include <boost/container/allocator_traits.hpp> 25 #include <boost/container/container_fwd.hpp> 26 #include <boost/container/new_allocator.hpp> //new_allocator 27 #include <boost/container/throw_exception.hpp> 28 #include <boost/container/options.hpp> 29 // container/detail 30 #include <boost/container/detail/advanced_insert_int.hpp> 31 #include <boost/container/detail/algorithm.hpp> //algo_equal(), algo_lexicographical_compare 32 #include <boost/container/detail/alloc_helpers.hpp> 33 #include <boost/container/detail/copy_move_algo.hpp> 34 #include <boost/container/detail/iterator.hpp> 35 #include <boost/move/detail/iterator_to_raw_pointer.hpp> 36 #include <boost/container/detail/iterators.hpp> 37 #include <boost/container/detail/min_max.hpp> 38 #include <boost/container/detail/mpl.hpp> 39 #include <boost/move/detail/to_raw_pointer.hpp> 40 #include <boost/container/detail/type_traits.hpp> 41 // move 42 #include <boost/move/adl_move_swap.hpp> 43 #include <boost/move/iterator.hpp> 44 #include <boost/move/traits.hpp> 45 #include <boost/move/utility_core.hpp> 46 // move/detail 47 #if defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) 48 #include <boost/move/detail/fwd_macros.hpp> 49 #endif 50 #include <boost/move/detail/move_helpers.hpp> 51 // other 52 #include <boost/assert.hpp> 53 #include <boost/core/no_exceptions_support.hpp> 54 // std 55 #include <cstddef> 56 57 #if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST) 58 #include <initializer_list> 59 #endif 60 61 namespace boost { 62 namespace container { 63 64 #ifndef BOOST_CONTAINER_DOXYGEN_INVOKED 65 template <class T, class Allocator, class Options> 66 class deque; 67 68 template <class T> 69 struct deque_value_traits 70 { 71 typedef T value_type; 72 static const bool trivial_dctr = dtl::is_trivially_destructible<value_type>::value; 73 static const bool trivial_dctr_after_move = ::boost::has_trivial_destructor_after_move<value_type>::value; 74 }; 75 76 template<class T, std::size_t BlockBytes, std::size_t BlockSize> 77 struct deque_block_size 78 { 79 BOOST_STATIC_ASSERT_MSG(!(BlockBytes && BlockSize), "BlockBytes and BlockSize can't be specified at the same time"); 80 static const std::size_t block_bytes = BlockBytes ? BlockBytes : 512u; 81 static const std::size_t value = BlockSize ? BlockSize : (sizeof(T) < block_bytes ? (block_bytes/sizeof(T)) : std::size_t(1)); 82 }; 83 84 namespace dtl { 85 86 // Class invariants: 87 // For any nonsingular iterator i: 88 // i.node is the address of an element in the map array. The 89 // contents of i.node is a pointer to the beginning of a node. 90 // i.first == //(i.node) 91 // i.last == i.first + node_size 92 // i.cur is a pointer in the range [i.first, i.last). NOTE: 93 // the implication of this is that i.cur is always a dereferenceable 94 // pointer, even if i is a past-the-end iterator. 95 // Start and Finish are always nonsingular iterators. NOTE: this means 96 // that an empty deque must have one node, and that a deque 97 // with N elements, where N is the buffer size, must have two nodes. 98 // For every node other than start.node and finish.node, every element 99 // in the node is an initialized object. If start.node == finish.node, 100 // then [start.cur, finish.cur) are initialized objects, and 101 // the elements outside that range are uninitialized storage. Otherwise, 102 // [start.cur, start.last) and [finish.first, finish.cur) are initialized 103 // objects, and [start.first, start.cur) and [finish.cur, finish.last) 104 // are uninitialized storage. 105 // [map, map + map_size) is a valid, non-empty range. 106 // [start.node, finish.node] is a valid range contained within 107 // [map, map + map_size). 108 // A pointer in the range [map, map + map_size) points to an allocated node 109 // if and only if the pointer is in the range [start.node, finish.node]. 110 template<class Pointer, bool IsConst> 111 class deque_iterator 112 { 113 public: 114 typedef std::random_access_iterator_tag iterator_category; 115 typedef typename boost::intrusive::pointer_traits<Pointer>::element_type value_type; 116 typedef typename boost::intrusive::pointer_traits<Pointer>::difference_type difference_type; 117 typedef typename if_c 118 < IsConst 119 , typename boost::intrusive::pointer_traits<Pointer>::template 120 rebind_pointer<const value_type>::type 121 , Pointer 122 >::type pointer; 123 typedef typename if_c 124 < IsConst 125 , const value_type& 126 , value_type& 127 >::type reference; 128 129 class nat; 130 typedef typename dtl::if_c< IsConst 131 , deque_iterator<Pointer, false> 132 , nat>::type nonconst_iterator; 133 134 typedef Pointer val_alloc_ptr; 135 typedef typename boost::intrusive::pointer_traits<Pointer>:: 136 template rebind_pointer<Pointer>::type index_pointer; 137 138 Pointer m_cur; 139 Pointer m_first; 140 Pointer m_last; 141 index_pointer m_node; 142 143 public: 144 get_cur() const145 BOOST_CONTAINER_ATTRIBUTE_NODISCARD BOOST_CONTAINER_FORCEINLINE Pointer get_cur() const { return m_cur; } get_first() const146 BOOST_CONTAINER_ATTRIBUTE_NODISCARD BOOST_CONTAINER_FORCEINLINE Pointer get_first() const { return m_first; } get_last() const147 BOOST_CONTAINER_ATTRIBUTE_NODISCARD BOOST_CONTAINER_FORCEINLINE Pointer get_last() const { return m_last; } get_node() const148 BOOST_CONTAINER_ATTRIBUTE_NODISCARD BOOST_CONTAINER_FORCEINLINE index_pointer get_node() const { return m_node; } 149 deque_iterator(val_alloc_ptr x,index_pointer y,difference_type block_size)150 BOOST_CONTAINER_FORCEINLINE deque_iterator(val_alloc_ptr x, index_pointer y, difference_type block_size) BOOST_NOEXCEPT_OR_NOTHROW 151 : m_cur(x), m_first(*y), m_last(*y + block_size), m_node(y) 152 {} 153 deque_iterator()154 BOOST_CONTAINER_FORCEINLINE deque_iterator() BOOST_NOEXCEPT_OR_NOTHROW 155 : m_cur(), m_first(), m_last(), m_node() //Value initialization to achieve "null iterators" (N3644) 156 {} 157 deque_iterator(const deque_iterator & x)158 BOOST_CONTAINER_FORCEINLINE deque_iterator(const deque_iterator& x) BOOST_NOEXCEPT_OR_NOTHROW 159 : m_cur(x.get_cur()), m_first(x.get_first()), m_last(x.get_last()), m_node(x.get_node()) 160 {} 161 deque_iterator(const nonconst_iterator & x)162 BOOST_CONTAINER_FORCEINLINE deque_iterator(const nonconst_iterator& x) BOOST_NOEXCEPT_OR_NOTHROW 163 : m_cur(x.get_cur()), m_first(x.get_first()), m_last(x.get_last()), m_node(x.get_node()) 164 {} 165 deque_iterator(Pointer cur,Pointer first,Pointer last,index_pointer node)166 BOOST_CONTAINER_FORCEINLINE deque_iterator(Pointer cur, Pointer first, Pointer last, index_pointer node) BOOST_NOEXCEPT_OR_NOTHROW 167 : m_cur(cur), m_first(first), m_last(last), m_node(node) 168 {} 169 operator =(const deque_iterator & x)170 BOOST_CONTAINER_FORCEINLINE deque_iterator& operator=(const deque_iterator& x) BOOST_NOEXCEPT_OR_NOTHROW 171 { m_cur = x.get_cur(); m_first = x.get_first(); m_last = x.get_last(); m_node = x.get_node(); return *this; } 172 unconst() const173 BOOST_CONTAINER_FORCEINLINE deque_iterator<Pointer, false> unconst() const BOOST_NOEXCEPT_OR_NOTHROW 174 { 175 return deque_iterator<Pointer, false>(this->get_cur(), this->get_first(), this->get_last(), this->get_node()); 176 } 177 operator *() const178 BOOST_CONTAINER_FORCEINLINE reference operator*() const BOOST_NOEXCEPT_OR_NOTHROW 179 { return *this->m_cur; } 180 operator ->() const181 BOOST_CONTAINER_FORCEINLINE pointer operator->() const BOOST_NOEXCEPT_OR_NOTHROW 182 { return this->m_cur; } 183 operator -(const deque_iterator & x) const184 BOOST_CONTAINER_ATTRIBUTE_NODISCARD difference_type operator-(const deque_iterator& x) const BOOST_NOEXCEPT_OR_NOTHROW 185 { 186 if(!this->m_cur && !x.m_cur){ 187 return 0; 188 } 189 const difference_type block_size = this->m_last - this->m_first; 190 BOOST_ASSERT(block_size); 191 return block_size * (this->m_node - x.m_node - 1) + 192 (this->m_cur - this->m_first) + (x.m_last - x.m_cur); 193 } 194 operator ++()195 deque_iterator& operator++() BOOST_NOEXCEPT_OR_NOTHROW 196 { 197 BOOST_ASSERT(!!m_cur); 198 ++this->m_cur; 199 if (this->m_cur == this->m_last) { 200 const difference_type block_size = m_last - m_first; 201 BOOST_ASSERT(block_size); 202 this->priv_set_node(this->m_node + 1, block_size); 203 this->m_cur = this->m_first; 204 } 205 return *this; 206 } 207 operator ++(int)208 BOOST_CONTAINER_FORCEINLINE deque_iterator operator++(int) BOOST_NOEXCEPT_OR_NOTHROW 209 { 210 deque_iterator tmp(*this); 211 ++*this; 212 return tmp; 213 } 214 operator --()215 deque_iterator& operator--() BOOST_NOEXCEPT_OR_NOTHROW 216 { 217 BOOST_ASSERT(!!m_cur); 218 if (this->m_cur == this->m_first) { 219 const difference_type block_size = m_last - m_first; 220 BOOST_ASSERT(block_size); 221 this->priv_set_node(this->m_node - 1, block_size); 222 this->m_cur = this->m_last; 223 } 224 --this->m_cur; 225 return *this; 226 } 227 operator --(int)228 BOOST_CONTAINER_FORCEINLINE deque_iterator operator--(int) BOOST_NOEXCEPT_OR_NOTHROW 229 { 230 deque_iterator tmp(*this); 231 --*this; 232 return tmp; 233 } 234 operator +=(difference_type n)235 deque_iterator& operator+=(difference_type n) BOOST_NOEXCEPT_OR_NOTHROW 236 { 237 if (!n) 238 return *this; 239 BOOST_ASSERT(!!m_cur); 240 difference_type offset = n + (this->m_cur - this->m_first); 241 const difference_type block_size = this->m_last - this->m_first; 242 BOOST_ASSERT(block_size); 243 if (offset >= 0 && offset < block_size) 244 this->m_cur += n; 245 else { 246 difference_type node_offset = 247 offset > 0 ? (offset / block_size) 248 : (-difference_type((-offset - 1) / block_size) - 1); 249 this->priv_set_node(this->m_node + node_offset, block_size); 250 this->m_cur = this->m_first + 251 (offset - node_offset * block_size); 252 } 253 return *this; 254 } 255 256 BOOST_CONTAINER_ATTRIBUTE_NODISCARD BOOST_CONTAINER_FORCEINLINE operator +(difference_type n) const257 deque_iterator operator+(difference_type n) const BOOST_NOEXCEPT_OR_NOTHROW 258 { deque_iterator tmp(*this); return tmp += n; } 259 260 BOOST_CONTAINER_FORCEINLINE operator -=(difference_type n)261 deque_iterator& operator-=(difference_type n) BOOST_NOEXCEPT_OR_NOTHROW 262 { return *this += -n; } 263 264 BOOST_CONTAINER_ATTRIBUTE_NODISCARD BOOST_CONTAINER_FORCEINLINE operator -(difference_type n) const265 deque_iterator operator-(difference_type n) const BOOST_NOEXCEPT_OR_NOTHROW 266 { deque_iterator tmp(*this); return tmp -= n; } 267 268 BOOST_CONTAINER_ATTRIBUTE_NODISCARD BOOST_CONTAINER_FORCEINLINE operator [](difference_type n) const269 reference operator[](difference_type n) const BOOST_NOEXCEPT_OR_NOTHROW 270 { return *(*this + n); } 271 272 BOOST_CONTAINER_ATTRIBUTE_NODISCARD BOOST_CONTAINER_FORCEINLINE operator ==(const deque_iterator & l,const deque_iterator & r)273 friend bool operator==(const deque_iterator& l, const deque_iterator& r) BOOST_NOEXCEPT_OR_NOTHROW 274 { return l.m_cur == r.m_cur; } 275 276 BOOST_CONTAINER_ATTRIBUTE_NODISCARD BOOST_CONTAINER_FORCEINLINE operator !=(const deque_iterator & l,const deque_iterator & r)277 friend bool operator!=(const deque_iterator& l, const deque_iterator& r) BOOST_NOEXCEPT_OR_NOTHROW 278 { return l.m_cur != r.m_cur; } 279 280 BOOST_CONTAINER_ATTRIBUTE_NODISCARD BOOST_CONTAINER_FORCEINLINE operator <(const deque_iterator & l,const deque_iterator & r)281 friend bool operator<(const deque_iterator& l, const deque_iterator& r) BOOST_NOEXCEPT_OR_NOTHROW 282 { return (l.m_node == r.m_node) ? (l.m_cur < r.m_cur) : (l.m_node < r.m_node); } 283 284 BOOST_CONTAINER_ATTRIBUTE_NODISCARD BOOST_CONTAINER_FORCEINLINE operator >(const deque_iterator & l,const deque_iterator & r)285 friend bool operator>(const deque_iterator& l, const deque_iterator& r) BOOST_NOEXCEPT_OR_NOTHROW 286 { return r < l; } 287 288 BOOST_CONTAINER_ATTRIBUTE_NODISCARD BOOST_CONTAINER_FORCEINLINE operator <=(const deque_iterator & l,const deque_iterator & r)289 friend bool operator<=(const deque_iterator& l, const deque_iterator& r) BOOST_NOEXCEPT_OR_NOTHROW 290 { return !(r < l); } 291 292 BOOST_CONTAINER_ATTRIBUTE_NODISCARD BOOST_CONTAINER_FORCEINLINE operator >=(const deque_iterator & l,const deque_iterator & r)293 friend bool operator>=(const deque_iterator& l, const deque_iterator& r) BOOST_NOEXCEPT_OR_NOTHROW 294 { return !(l < r); } 295 296 BOOST_CONTAINER_ATTRIBUTE_NODISCARD BOOST_CONTAINER_FORCEINLINE operator +(difference_type n,deque_iterator x)297 friend deque_iterator operator+(difference_type n, deque_iterator x) BOOST_NOEXCEPT_OR_NOTHROW 298 { return x += n; } 299 priv_set_node(index_pointer new_node,difference_type block_size)300 BOOST_CONTAINER_FORCEINLINE void priv_set_node(index_pointer new_node, difference_type block_size) BOOST_NOEXCEPT_OR_NOTHROW 301 { 302 this->m_node = new_node; 303 this->m_first = *new_node; 304 this->m_last = this->m_first + block_size; 305 } 306 }; 307 308 } //namespace dtl { 309 310 template<class Options> 311 struct get_deque_opt 312 { 313 typedef Options type; 314 }; 315 316 template<> 317 struct get_deque_opt<void> 318 { 319 typedef deque_null_opt type; 320 }; 321 322 // Deque base class. It has two purposes. First, its constructor 323 // and destructor allocate (but don't initialize) storage. This makes 324 // exception safety easier. 325 template <class Allocator, class Options> 326 class deque_base 327 { 328 BOOST_COPYABLE_AND_MOVABLE(deque_base) 329 public: 330 typedef allocator_traits<Allocator> val_alloc_traits_type; 331 typedef typename val_alloc_traits_type::value_type val_alloc_val; 332 typedef typename val_alloc_traits_type::pointer val_alloc_ptr; 333 typedef typename val_alloc_traits_type::const_pointer val_alloc_cptr; 334 typedef typename val_alloc_traits_type::reference val_alloc_ref; 335 typedef typename val_alloc_traits_type::const_reference val_alloc_cref; 336 typedef typename val_alloc_traits_type::difference_type val_alloc_diff; 337 typedef typename val_alloc_traits_type::size_type val_alloc_size; 338 typedef typename val_alloc_traits_type::template 339 portable_rebind_alloc<val_alloc_ptr>::type ptr_alloc_t; 340 typedef allocator_traits<ptr_alloc_t> ptr_alloc_traits_type; 341 typedef typename ptr_alloc_traits_type::value_type ptr_alloc_val; 342 typedef typename ptr_alloc_traits_type::pointer ptr_alloc_ptr; 343 typedef typename ptr_alloc_traits_type::const_pointer ptr_alloc_cptr; 344 typedef typename ptr_alloc_traits_type::reference ptr_alloc_ref; 345 typedef typename ptr_alloc_traits_type::const_reference ptr_alloc_cref; 346 typedef Allocator allocator_type; 347 typedef allocator_type stored_allocator_type; 348 typedef val_alloc_size size_type; 349 350 private: 351 typedef typename get_deque_opt<Options>::type options_type; 352 353 protected: 354 typedef dtl::deque_iterator<val_alloc_ptr, false> iterator; 355 typedef dtl::deque_iterator<val_alloc_ptr, true > const_iterator; 356 get_block_size()357 BOOST_CONSTEXPR BOOST_CONTAINER_FORCEINLINE static size_type get_block_size() BOOST_NOEXCEPT_OR_NOTHROW 358 { return deque_block_size<val_alloc_val, options_type::block_bytes, options_type::block_size>::value; } 359 360 typedef deque_value_traits<val_alloc_val> traits_t; 361 typedef ptr_alloc_t map_allocator_type; 362 priv_allocate_node()363 BOOST_CONTAINER_FORCEINLINE val_alloc_ptr priv_allocate_node() 364 { return this->alloc().allocate(get_block_size()); } 365 priv_deallocate_node(val_alloc_ptr p)366 BOOST_CONTAINER_FORCEINLINE void priv_deallocate_node(val_alloc_ptr p) BOOST_NOEXCEPT_OR_NOTHROW 367 { this->alloc().deallocate(p, get_block_size()); } 368 priv_allocate_map(size_type n)369 BOOST_CONTAINER_FORCEINLINE ptr_alloc_ptr priv_allocate_map(size_type n) 370 { return this->ptr_alloc().allocate(n); } 371 priv_deallocate_map(ptr_alloc_ptr p,size_type n)372 BOOST_CONTAINER_FORCEINLINE void priv_deallocate_map(ptr_alloc_ptr p, size_type n) BOOST_NOEXCEPT_OR_NOTHROW 373 { this->ptr_alloc().deallocate(p, n); } 374 deque_base(size_type num_elements,const allocator_type & a)375 BOOST_CONTAINER_FORCEINLINE deque_base(size_type num_elements, const allocator_type& a) 376 : members_(a) 377 { this->priv_initialize_map(num_elements); } 378 deque_base(const allocator_type & a)379 BOOST_CONTAINER_FORCEINLINE explicit deque_base(const allocator_type& a) 380 : members_(a) 381 {} 382 deque_base()383 BOOST_CONTAINER_FORCEINLINE deque_base() 384 : members_() 385 {} 386 deque_base(BOOST_RV_REF (deque_base)x)387 BOOST_CONTAINER_FORCEINLINE explicit deque_base(BOOST_RV_REF(deque_base) x) 388 : members_( boost::move(x.ptr_alloc()) 389 , boost::move(x.alloc()) ) 390 {} 391 ~deque_base()392 ~deque_base() 393 { 394 if (this->members_.m_map) { 395 this->priv_destroy_nodes(this->members_.m_start.m_node, this->members_.m_finish.m_node + 1); 396 this->priv_deallocate_map(this->members_.m_map, this->members_.m_map_size); 397 } 398 } 399 400 private: 401 deque_base(const deque_base&); 402 403 protected: 404 swap_members(deque_base & x)405 void swap_members(deque_base &x) BOOST_NOEXCEPT_OR_NOTHROW 406 { 407 ::boost::adl_move_swap(this->members_.m_start, x.members_.m_start); 408 ::boost::adl_move_swap(this->members_.m_finish, x.members_.m_finish); 409 ::boost::adl_move_swap(this->members_.m_map, x.members_.m_map); 410 ::boost::adl_move_swap(this->members_.m_map_size, x.members_.m_map_size); 411 } 412 priv_initialize_map(size_type num_elements)413 void priv_initialize_map(size_type num_elements) 414 { 415 // if(num_elements){ 416 size_type num_nodes = num_elements / get_block_size() + 1; 417 418 this->members_.m_map_size = dtl::max_value((size_type) InitialMapSize, num_nodes + 2); 419 this->members_.m_map = this->priv_allocate_map(this->members_.m_map_size); 420 421 ptr_alloc_ptr nstart = this->members_.m_map + (this->members_.m_map_size - num_nodes) / 2; 422 ptr_alloc_ptr nfinish = nstart + num_nodes; 423 424 BOOST_TRY { 425 this->priv_create_nodes(nstart, nfinish); 426 } 427 BOOST_CATCH(...){ 428 this->priv_deallocate_map(this->members_.m_map, this->members_.m_map_size); 429 this->members_.m_map = 0; 430 this->members_.m_map_size = 0; 431 BOOST_RETHROW 432 } 433 BOOST_CATCH_END 434 435 this->members_.m_start.priv_set_node(nstart, get_block_size()); 436 this->members_.m_finish.priv_set_node(nfinish - 1, get_block_size()); 437 this->members_.m_start.m_cur = this->members_.m_start.m_first; 438 this->members_.m_finish.m_cur = this->members_.m_finish.m_first + 439 num_elements % get_block_size(); 440 // } 441 } 442 priv_create_nodes(ptr_alloc_ptr nstart,ptr_alloc_ptr nfinish)443 void priv_create_nodes(ptr_alloc_ptr nstart, ptr_alloc_ptr nfinish) 444 { 445 ptr_alloc_ptr cur = nstart; 446 BOOST_TRY { 447 for (; cur < nfinish; ++cur) 448 *cur = this->priv_allocate_node(); 449 } 450 BOOST_CATCH(...){ 451 this->priv_destroy_nodes(nstart, cur); 452 BOOST_RETHROW 453 } 454 BOOST_CATCH_END 455 } 456 priv_destroy_nodes(ptr_alloc_ptr nstart,ptr_alloc_ptr nfinish)457 void priv_destroy_nodes(ptr_alloc_ptr nstart, ptr_alloc_ptr nfinish) BOOST_NOEXCEPT_OR_NOTHROW 458 { 459 for (ptr_alloc_ptr n = nstart; n < nfinish; ++n) 460 this->priv_deallocate_node(*n); 461 } 462 priv_clear_map()463 void priv_clear_map() BOOST_NOEXCEPT_OR_NOTHROW 464 { 465 if (this->members_.m_map) { 466 this->priv_destroy_nodes(this->members_.m_start.m_node, this->members_.m_finish.m_node + 1); 467 this->priv_deallocate_map(this->members_.m_map, this->members_.m_map_size); 468 this->members_.m_map = 0; 469 this->members_.m_map_size = 0; 470 this->members_.m_start = iterator(); 471 this->members_.m_finish = this->members_.m_start; 472 } 473 } 474 475 enum { InitialMapSize = 8 }; 476 477 protected: 478 struct members_holder 479 : public ptr_alloc_t 480 , public allocator_type 481 { members_holderboost::container::deque_base::members_holder482 members_holder() 483 : map_allocator_type(), allocator_type() 484 , m_map(0), m_map_size(0) 485 , m_start(), m_finish(m_start) 486 {} 487 members_holderboost::container::deque_base::members_holder488 explicit members_holder(const allocator_type &a) 489 : map_allocator_type(a), allocator_type(a) 490 , m_map(0), m_map_size(0) 491 , m_start(), m_finish(m_start) 492 {} 493 494 template<class ValAllocConvertible, class PtrAllocConvertible> members_holderboost::container::deque_base::members_holder495 members_holder(BOOST_FWD_REF(PtrAllocConvertible) pa, BOOST_FWD_REF(ValAllocConvertible) va) 496 : map_allocator_type(boost::forward<PtrAllocConvertible>(pa)) 497 , allocator_type (boost::forward<ValAllocConvertible>(va)) 498 , m_map(0), m_map_size(0) 499 , m_start(), m_finish(m_start) 500 {} 501 502 ptr_alloc_ptr m_map; 503 val_alloc_size m_map_size; 504 iterator m_start; 505 iterator m_finish; 506 } members_; 507 ptr_alloc()508 BOOST_CONTAINER_FORCEINLINE ptr_alloc_t &ptr_alloc() BOOST_NOEXCEPT_OR_NOTHROW 509 { return members_; } 510 ptr_alloc() const511 BOOST_CONTAINER_FORCEINLINE const ptr_alloc_t &ptr_alloc() const BOOST_NOEXCEPT_OR_NOTHROW 512 { return members_; } 513 alloc()514 BOOST_CONTAINER_FORCEINLINE allocator_type &alloc() BOOST_NOEXCEPT_OR_NOTHROW 515 { return members_; } 516 alloc() const517 BOOST_CONTAINER_FORCEINLINE const allocator_type &alloc() const BOOST_NOEXCEPT_OR_NOTHROW 518 { return members_; } 519 }; 520 #endif //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED 521 522 #ifdef BOOST_CONTAINER_DOXYGEN_INVOKED 523 //! A double-ended queue is a sequence that supports random access to elements, constant time insertion 524 //! and removal of elements at the end of the sequence, and linear time insertion and removal of elements in the middle. 525 //! 526 //! \tparam T The type of object that is stored in the deque 527 //! \tparam A The allocator used for all internal memory management, use void 528 //! for the default allocator 529 //! \tparam Options A type produced from \c boost::container::deque_options. 530 template <class T, class Allocator = void, class Options = void> 531 #else 532 template <class T, class Allocator, class Options> 533 #endif 534 class deque : protected deque_base<typename real_allocator<T, Allocator>::type, Options> 535 { 536 #ifndef BOOST_CONTAINER_DOXYGEN_INVOKED 537 private: 538 typedef deque_base<typename real_allocator<T, Allocator>::type, Options> Base; 539 #endif //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED 540 typedef typename real_allocator<T, Allocator>::type ValAllocator; 541 542 public: 543 544 ////////////////////////////////////////////// 545 // 546 // types 547 // 548 ////////////////////////////////////////////// 549 550 typedef T value_type; 551 typedef ValAllocator allocator_type; 552 typedef typename ::boost::container::allocator_traits<ValAllocator>::pointer pointer; 553 typedef typename ::boost::container::allocator_traits<ValAllocator>::const_pointer const_pointer; 554 typedef typename ::boost::container::allocator_traits<ValAllocator>::reference reference; 555 typedef typename ::boost::container::allocator_traits<ValAllocator>::const_reference const_reference; 556 typedef typename ::boost::container::allocator_traits<ValAllocator>::size_type size_type; 557 typedef typename ::boost::container::allocator_traits<ValAllocator>::difference_type difference_type; 558 typedef BOOST_CONTAINER_IMPDEF(allocator_type) stored_allocator_type; 559 typedef BOOST_CONTAINER_IMPDEF(typename Base::iterator) iterator; 560 typedef BOOST_CONTAINER_IMPDEF(typename Base::const_iterator) const_iterator; 561 typedef BOOST_CONTAINER_IMPDEF(boost::container::reverse_iterator<iterator>) reverse_iterator; 562 typedef BOOST_CONTAINER_IMPDEF(boost::container::reverse_iterator<const_iterator>) const_reverse_iterator; 563 564 #ifndef BOOST_CONTAINER_DOXYGEN_INVOKED 565 566 private: // Internal typedefs 567 BOOST_COPYABLE_AND_MOVABLE(deque) 568 typedef typename Base::ptr_alloc_ptr index_pointer; 569 typedef allocator_traits<ValAllocator> allocator_traits_type; 570 571 #endif //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED 572 573 public: 574 get_block_size()575 BOOST_CONSTEXPR BOOST_CONTAINER_FORCEINLINE static size_type get_block_size() BOOST_NOEXCEPT_OR_NOTHROW 576 { return Base::get_block_size(); } 577 578 ////////////////////////////////////////////// 579 // 580 // construct/copy/destroy 581 // 582 ////////////////////////////////////////////// 583 584 //! <b>Effects</b>: Default constructors a deque. 585 //! 586 //! <b>Throws</b>: If allocator_type's default constructor throws. 587 //! 588 //! <b>Complexity</b>: Constant. deque()589 BOOST_CONTAINER_FORCEINLINE deque() 590 BOOST_NOEXCEPT_IF(dtl::is_nothrow_default_constructible<ValAllocator>::value) 591 : Base() 592 {} 593 594 //! <b>Effects</b>: Constructs a deque taking the allocator as parameter. 595 //! 596 //! <b>Throws</b>: Nothing 597 //! 598 //! <b>Complexity</b>: Constant. deque(const allocator_type & a)599 BOOST_CONTAINER_FORCEINLINE explicit deque(const allocator_type& a) BOOST_NOEXCEPT_OR_NOTHROW 600 : Base(a) 601 {} 602 603 //! <b>Effects</b>: Constructs a deque 604 //! and inserts n value initialized values. 605 //! 606 //! <b>Throws</b>: If allocator_type's default constructor 607 //! throws or T's value initialization throws. 608 //! 609 //! <b>Complexity</b>: Linear to n. deque(size_type n)610 BOOST_CONTAINER_FORCEINLINE explicit deque(size_type n) 611 : Base(n, allocator_type()) 612 { 613 dtl::insert_value_initialized_n_proxy<ValAllocator, iterator> proxy; 614 proxy.uninitialized_copy_n_and_update(this->alloc(), this->begin(), n); 615 //deque_base will deallocate in case of exception... 616 } 617 618 //! <b>Effects</b>: Constructs a deque 619 //! and inserts n default initialized values. 620 //! 621 //! <b>Throws</b>: If allocator_type's default constructor 622 //! throws or T's default initialization or copy constructor throws. 623 //! 624 //! <b>Complexity</b>: Linear to n. 625 //! 626 //! <b>Note</b>: Non-standard extension deque(size_type n,default_init_t)627 BOOST_CONTAINER_FORCEINLINE deque(size_type n, default_init_t) 628 : Base(n, allocator_type()) 629 { 630 dtl::insert_default_initialized_n_proxy<ValAllocator, iterator> proxy; 631 proxy.uninitialized_copy_n_and_update(this->alloc(), this->begin(), n); 632 //deque_base will deallocate in case of exception... 633 } 634 635 //! <b>Effects</b>: Constructs a deque that will use a copy of allocator a 636 //! and inserts n value initialized values. 637 //! 638 //! <b>Throws</b>: If allocator_type's default constructor 639 //! throws or T's value initialization throws. 640 //! 641 //! <b>Complexity</b>: Linear to n. deque(size_type n,const allocator_type & a)642 BOOST_CONTAINER_FORCEINLINE explicit deque(size_type n, const allocator_type &a) 643 : Base(n, a) 644 { 645 dtl::insert_value_initialized_n_proxy<ValAllocator, iterator> proxy; 646 proxy.uninitialized_copy_n_and_update(this->alloc(), this->begin(), n); 647 //deque_base will deallocate in case of exception... 648 } 649 650 //! <b>Effects</b>: Constructs a deque that will use a copy of allocator a 651 //! and inserts n default initialized values. 652 //! 653 //! <b>Throws</b>: If allocator_type's default constructor 654 //! throws or T's default initialization or copy constructor throws. 655 //! 656 //! <b>Complexity</b>: Linear to n. 657 //! 658 //! <b>Note</b>: Non-standard extension deque(size_type n,default_init_t,const allocator_type & a)659 BOOST_CONTAINER_FORCEINLINE deque(size_type n, default_init_t, const allocator_type &a) 660 : Base(n, a) 661 { 662 dtl::insert_default_initialized_n_proxy<ValAllocator, iterator> proxy; 663 proxy.uninitialized_copy_n_and_update(this->alloc(), this->begin(), n); 664 //deque_base will deallocate in case of exception... 665 } 666 667 //! <b>Effects</b>: Constructs a deque that will use a copy of allocator a 668 //! and inserts n copies of value. 669 //! 670 //! <b>Throws</b>: If allocator_type's default constructor 671 //! throws or T's copy constructor throws. 672 //! 673 //! <b>Complexity</b>: Linear to n. deque(size_type n,const value_type & value)674 BOOST_CONTAINER_FORCEINLINE deque(size_type n, const value_type& value) 675 : Base(n, allocator_type()) 676 { this->priv_fill_initialize(value); } 677 678 //! <b>Effects</b>: Constructs a deque that will use a copy of allocator a 679 //! and inserts n copies of value. 680 //! 681 //! <b>Throws</b>: If allocator_type's default constructor 682 //! throws or T's copy constructor throws. 683 //! 684 //! <b>Complexity</b>: Linear to n. deque(size_type n,const value_type & value,const allocator_type & a)685 BOOST_CONTAINER_FORCEINLINE deque(size_type n, const value_type& value, const allocator_type& a) 686 : Base(n, a) 687 { this->priv_fill_initialize(value); } 688 689 //! <b>Effects</b>: Constructs a deque that will use a copy of allocator a 690 //! and inserts a copy of the range [first, last) in the deque. 691 //! 692 //! <b>Throws</b>: If allocator_type's default constructor 693 //! throws or T's constructor taking a dereferenced InIt throws. 694 //! 695 //! <b>Complexity</b>: Linear to the range [first, last). 696 template <class InIt> deque(InIt first,InIt last,typename dtl::disable_if_convertible<InIt,size_type>::type * =0)697 BOOST_CONTAINER_FORCEINLINE deque(InIt first, InIt last 698 #if !defined(BOOST_CONTAINER_DOXYGEN_INVOKED) 699 , typename dtl::disable_if_convertible 700 <InIt, size_type>::type * = 0 701 #endif 702 ) 703 : Base(allocator_type()) 704 { 705 this->priv_range_initialize(first, last); 706 } 707 708 //! <b>Effects</b>: Constructs a deque that will use a copy of allocator a 709 //! and inserts a copy of the range [first, last) in the deque. 710 //! 711 //! <b>Throws</b>: If allocator_type's default constructor 712 //! throws or T's constructor taking a dereferenced InIt throws. 713 //! 714 //! <b>Complexity</b>: Linear to the range [first, last). 715 template <class InIt> deque(InIt first,InIt last,const allocator_type & a,typename dtl::disable_if_convertible<InIt,size_type>::type * =0)716 BOOST_CONTAINER_FORCEINLINE deque(InIt first, InIt last, const allocator_type& a 717 #if !defined(BOOST_CONTAINER_DOXYGEN_INVOKED) 718 , typename dtl::disable_if_convertible 719 <InIt, size_type>::type * = 0 720 #endif 721 ) 722 : Base(a) 723 { 724 this->priv_range_initialize(first, last); 725 } 726 727 #if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST) 728 //! <b>Effects</b>: Constructs a deque that will use a copy of allocator a 729 //! and inserts a copy of the range [il.begin(), il.end()) in the deque. 730 //! 731 //! <b>Throws</b>: If allocator_type's default constructor 732 //! throws or T's constructor taking a dereferenced std::initializer_list iterator throws. 733 //! 734 //! <b>Complexity</b>: Linear to the range [il.begin(), il.end()). deque(std::initializer_list<value_type> il,const allocator_type & a=allocator_type ())735 BOOST_CONTAINER_FORCEINLINE deque(std::initializer_list<value_type> il, const allocator_type& a = allocator_type()) 736 : Base(a) 737 { 738 this->priv_range_initialize(il.begin(), il.end()); 739 } 740 #endif 741 742 //! <b>Effects</b>: Copy constructs a deque. 743 //! 744 //! <b>Postcondition</b>: x == *this. 745 //! 746 //! <b>Complexity</b>: Linear to the elements x contains. deque(const deque & x)747 BOOST_CONTAINER_FORCEINLINE deque(const deque& x) 748 : Base(allocator_traits_type::select_on_container_copy_construction(x.alloc())) 749 { 750 if(x.size()){ 751 this->priv_initialize_map(x.size()); 752 boost::container::uninitialized_copy_alloc 753 (this->alloc(), x.begin(), x.end(), this->members_.m_start); 754 } 755 } 756 757 //! <b>Effects</b>: Move constructor. Moves x's resources to *this. 758 //! 759 //! <b>Throws</b>: If allocator_type's copy constructor throws. 760 //! 761 //! <b>Complexity</b>: Constant. deque(BOOST_RV_REF (deque)x)762 BOOST_CONTAINER_FORCEINLINE deque(BOOST_RV_REF(deque) x) BOOST_NOEXCEPT_OR_NOTHROW 763 : Base(BOOST_MOVE_BASE(Base, x)) 764 { this->swap_members(x); } 765 766 //! <b>Effects</b>: Copy constructs a vector using the specified allocator. 767 //! 768 //! <b>Postcondition</b>: x == *this. 769 //! 770 //! <b>Throws</b>: If allocation 771 //! throws or T's copy constructor throws. 772 //! 773 //! <b>Complexity</b>: Linear to the elements x contains. deque(const deque & x,const allocator_type & a)774 deque(const deque& x, const allocator_type &a) 775 : Base(a) 776 { 777 if(x.size()){ 778 this->priv_initialize_map(x.size()); 779 boost::container::uninitialized_copy_alloc 780 (this->alloc(), x.begin(), x.end(), this->members_.m_start); 781 } 782 } 783 784 //! <b>Effects</b>: Move constructor using the specified allocator. 785 //! Moves x's resources to *this if a == allocator_type(). 786 //! Otherwise copies values from x to *this. 787 //! 788 //! <b>Throws</b>: If allocation or T's copy constructor throws. 789 //! 790 //! <b>Complexity</b>: Constant if a == x.get_allocator(), linear otherwise. deque(BOOST_RV_REF (deque)x,const allocator_type & a)791 deque(BOOST_RV_REF(deque) x, const allocator_type &a) 792 : Base(a) 793 { 794 if(x.alloc() == a){ 795 this->swap_members(x); 796 } 797 else{ 798 if(x.size()){ 799 this->priv_initialize_map(x.size()); 800 boost::container::uninitialized_copy_alloc 801 ( this->alloc(), boost::make_move_iterator(x.begin()) 802 , boost::make_move_iterator(x.end()), this->members_.m_start); 803 } 804 } 805 } 806 807 //! <b>Effects</b>: Destroys the deque. All stored values are destroyed 808 //! and used memory is deallocated. 809 //! 810 //! <b>Throws</b>: Nothing. 811 //! 812 //! <b>Complexity</b>: Linear to the number of elements. ~deque()813 BOOST_CONTAINER_FORCEINLINE ~deque() BOOST_NOEXCEPT_OR_NOTHROW 814 { 815 this->priv_destroy_range(this->members_.m_start, this->members_.m_finish); 816 } 817 818 //! <b>Effects</b>: Makes *this contain the same elements as x. 819 //! 820 //! <b>Postcondition</b>: this->size() == x.size(). *this contains a copy 821 //! of each of x's elements. 822 //! 823 //! <b>Throws</b>: If memory allocation throws or T's copy constructor throws. 824 //! 825 //! <b>Complexity</b>: Linear to the number of elements in x. operator =(BOOST_COPY_ASSIGN_REF (deque)x)826 deque& operator= (BOOST_COPY_ASSIGN_REF(deque) x) 827 { 828 if (BOOST_LIKELY(&x != this)){ 829 allocator_type &this_alloc = this->alloc(); 830 const allocator_type &x_alloc = x.alloc(); 831 dtl::bool_<allocator_traits_type:: 832 propagate_on_container_copy_assignment::value> flag; 833 if(flag && this_alloc != x_alloc){ 834 this->clear(); 835 this->shrink_to_fit(); 836 } 837 dtl::assign_alloc(this->alloc(), x.alloc(), flag); 838 dtl::assign_alloc(this->ptr_alloc(), x.ptr_alloc(), flag); 839 this->assign(x.cbegin(), x.cend()); 840 } 841 return *this; 842 } 843 844 //! <b>Effects</b>: Move assignment. All x's values are transferred to *this. 845 //! 846 //! <b>Throws</b>: If allocator_traits_type::propagate_on_container_move_assignment 847 //! is false and (allocation throws or value_type's move constructor throws) 848 //! 849 //! <b>Complexity</b>: Constant if allocator_traits_type:: 850 //! propagate_on_container_move_assignment is true or 851 //! this->get>allocator() == x.get_allocator(). Linear otherwise. operator =(BOOST_RV_REF (deque)x)852 deque& operator= (BOOST_RV_REF(deque) x) 853 BOOST_NOEXCEPT_IF(allocator_traits_type::propagate_on_container_move_assignment::value 854 || allocator_traits_type::is_always_equal::value) 855 { 856 if (BOOST_LIKELY(this != &x)) { 857 allocator_type &this_alloc = this->alloc(); 858 allocator_type &x_alloc = x.alloc(); 859 const bool propagate_alloc = allocator_traits_type:: 860 propagate_on_container_move_assignment::value; 861 dtl::bool_<propagate_alloc> flag; 862 const bool allocators_equal = this_alloc == x_alloc; (void)allocators_equal; 863 //Resources can be transferred if both allocators are 864 //going to be equal after this function (either propagated or already equal) 865 if(propagate_alloc || allocators_equal){ 866 //Destroy objects but retain memory in case x reuses it in the future 867 this->clear(); 868 //Move allocator if needed 869 dtl::move_alloc(this_alloc, x_alloc, flag); 870 dtl::move_alloc(this->ptr_alloc(), x.ptr_alloc(), flag); 871 //Nothrow swap 872 this->swap_members(x); 873 } 874 //Else do a one by one move 875 else{ 876 this->assign( boost::make_move_iterator(x.begin()) 877 , boost::make_move_iterator(x.end())); 878 } 879 } 880 return *this; 881 } 882 883 #if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST) 884 //! <b>Effects</b>: Makes *this contain the same elements as il. 885 //! 886 //! <b>Postcondition</b>: this->size() == il.size(). *this contains a copy 887 //! of each of x's elements. 888 //! 889 //! <b>Throws</b>: If memory allocation throws or T's copy constructor throws. 890 //! 891 //! <b>Complexity</b>: Linear to the number of elements in il. operator =(std::initializer_list<value_type> il)892 BOOST_CONTAINER_FORCEINLINE deque& operator=(std::initializer_list<value_type> il) 893 { 894 this->assign(il.begin(), il.end()); 895 return *this; 896 } 897 #endif 898 899 //! <b>Effects</b>: Assigns the n copies of val to *this. 900 //! 901 //! <b>Throws</b>: If memory allocation throws or T's copy constructor throws. 902 //! 903 //! <b>Complexity</b>: Linear to n. assign(size_type n,const T & val)904 BOOST_CONTAINER_FORCEINLINE void assign(size_type n, const T& val) 905 { 906 typedef constant_iterator<value_type, difference_type> c_it; 907 this->assign(c_it(val, n), c_it()); 908 } 909 910 //! <b>Effects</b>: Assigns the the range [first, last) to *this. 911 //! 912 //! <b>Throws</b>: If memory allocation throws or 913 //! T's constructor from dereferencing InIt throws. 914 //! 915 //! <b>Complexity</b>: Linear to n. 916 template <class InIt> assign(InIt first,InIt last,typename dtl::disable_if_or<void,dtl::is_convertible<InIt,size_type>,dtl::is_not_input_iterator<InIt>>::type * =0)917 void assign(InIt first, InIt last 918 #if !defined(BOOST_CONTAINER_DOXYGEN_INVOKED) 919 , typename dtl::disable_if_or 920 < void 921 , dtl::is_convertible<InIt, size_type> 922 , dtl::is_not_input_iterator<InIt> 923 >::type * = 0 924 #endif 925 ) 926 { 927 iterator cur = this->begin(); 928 for ( ; first != last && cur != end(); ++cur, ++first){ 929 *cur = *first; 930 } 931 if (first == last){ 932 this->erase(cur, this->cend()); 933 } 934 else{ 935 this->insert(this->cend(), first, last); 936 } 937 } 938 939 #if !defined(BOOST_CONTAINER_DOXYGEN_INVOKED) 940 template <class FwdIt> assign(FwdIt first,FwdIt last,typename dtl::disable_if_or<void,dtl::is_convertible<FwdIt,size_type>,dtl::is_input_iterator<FwdIt>>::type * =0)941 void assign(FwdIt first, FwdIt last 942 , typename dtl::disable_if_or 943 < void 944 , dtl::is_convertible<FwdIt, size_type> 945 , dtl::is_input_iterator<FwdIt> 946 >::type * = 0 947 ) 948 { 949 const size_type len = boost::container::iterator_distance(first, last); 950 if (len > size()) { 951 FwdIt mid = first; 952 boost::container::iterator_advance(mid, this->size()); 953 boost::container::copy(first, mid, begin()); 954 this->insert(this->cend(), mid, last); 955 } 956 else{ 957 this->erase(boost::container::copy(first, last, this->begin()), cend()); 958 } 959 } 960 #endif 961 962 #if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST) 963 //! <b>Effects</b>: Assigns the the range [il.begin(), il.end()) to *this. 964 //! 965 //! <b>Throws</b>: If memory allocation throws or 966 //! T's constructor from dereferencing std::initializer_list iterator throws. 967 //! 968 //! <b>Complexity</b>: Linear to il.size(). assign(std::initializer_list<value_type> il)969 BOOST_CONTAINER_FORCEINLINE void assign(std::initializer_list<value_type> il) 970 { this->assign(il.begin(), il.end()); } 971 #endif 972 973 //! <b>Effects</b>: Returns a copy of the internal allocator. 974 //! 975 //! <b>Throws</b>: If allocator's copy constructor throws. 976 //! 977 //! <b>Complexity</b>: Constant. 978 BOOST_CONTAINER_ATTRIBUTE_NODISCARD BOOST_CONTAINER_FORCEINLINE get_allocator() const979 allocator_type get_allocator() const BOOST_NOEXCEPT_OR_NOTHROW 980 { return Base::alloc(); } 981 982 //! <b>Effects</b>: Returns a reference to the internal allocator. 983 //! 984 //! <b>Throws</b>: Nothing 985 //! 986 //! <b>Complexity</b>: Constant. 987 //! 988 //! <b>Note</b>: Non-standard extension. 989 BOOST_CONTAINER_ATTRIBUTE_NODISCARD BOOST_CONTAINER_FORCEINLINE get_stored_allocator() const990 const stored_allocator_type &get_stored_allocator() const BOOST_NOEXCEPT_OR_NOTHROW 991 { return Base::alloc(); } 992 993 ////////////////////////////////////////////// 994 // 995 // iterators 996 // 997 ////////////////////////////////////////////// 998 999 //! <b>Effects</b>: Returns a reference to the internal allocator. 1000 //! 1001 //! <b>Throws</b>: Nothing 1002 //! 1003 //! <b>Complexity</b>: Constant. 1004 //! 1005 //! <b>Note</b>: Non-standard extension. 1006 BOOST_CONTAINER_ATTRIBUTE_NODISCARD BOOST_CONTAINER_FORCEINLINE get_stored_allocator()1007 stored_allocator_type &get_stored_allocator() BOOST_NOEXCEPT_OR_NOTHROW 1008 { return Base::alloc(); } 1009 1010 //! <b>Effects</b>: Returns an iterator to the first element contained in the deque. 1011 //! 1012 //! <b>Throws</b>: Nothing. 1013 //! 1014 //! <b>Complexity</b>: Constant. 1015 BOOST_CONTAINER_ATTRIBUTE_NODISCARD BOOST_CONTAINER_FORCEINLINE begin()1016 iterator begin() BOOST_NOEXCEPT_OR_NOTHROW 1017 { return this->members_.m_start; } 1018 1019 //! <b>Effects</b>: Returns a const_iterator to the first element contained in the deque. 1020 //! 1021 //! <b>Throws</b>: Nothing. 1022 //! 1023 //! <b>Complexity</b>: Constant. 1024 BOOST_CONTAINER_ATTRIBUTE_NODISCARD BOOST_CONTAINER_FORCEINLINE begin() const1025 const_iterator begin() const BOOST_NOEXCEPT_OR_NOTHROW 1026 { return this->members_.m_start; } 1027 1028 //! <b>Effects</b>: Returns an iterator to the end of the deque. 1029 //! 1030 //! <b>Throws</b>: Nothing. 1031 //! 1032 //! <b>Complexity</b>: Constant. 1033 BOOST_CONTAINER_ATTRIBUTE_NODISCARD BOOST_CONTAINER_FORCEINLINE end()1034 iterator end() BOOST_NOEXCEPT_OR_NOTHROW 1035 { return this->members_.m_finish; } 1036 1037 //! <b>Effects</b>: Returns a const_iterator to the end of the deque. 1038 //! 1039 //! <b>Throws</b>: Nothing. 1040 //! 1041 //! <b>Complexity</b>: Constant. 1042 BOOST_CONTAINER_ATTRIBUTE_NODISCARD BOOST_CONTAINER_FORCEINLINE end() const1043 const_iterator end() const BOOST_NOEXCEPT_OR_NOTHROW 1044 { return this->members_.m_finish; } 1045 1046 //! <b>Effects</b>: Returns a reverse_iterator pointing to the beginning 1047 //! of the reversed deque. 1048 //! 1049 //! <b>Throws</b>: Nothing. 1050 //! 1051 //! <b>Complexity</b>: Constant. 1052 BOOST_CONTAINER_ATTRIBUTE_NODISCARD BOOST_CONTAINER_FORCEINLINE rbegin()1053 reverse_iterator rbegin() BOOST_NOEXCEPT_OR_NOTHROW 1054 { return reverse_iterator(this->members_.m_finish); } 1055 1056 //! <b>Effects</b>: Returns a const_reverse_iterator pointing to the beginning 1057 //! of the reversed deque. 1058 //! 1059 //! <b>Throws</b>: Nothing. 1060 //! 1061 //! <b>Complexity</b>: Constant. 1062 BOOST_CONTAINER_ATTRIBUTE_NODISCARD BOOST_CONTAINER_FORCEINLINE rbegin() const1063 const_reverse_iterator rbegin() const BOOST_NOEXCEPT_OR_NOTHROW 1064 { return const_reverse_iterator(this->members_.m_finish); } 1065 1066 //! <b>Effects</b>: Returns a reverse_iterator pointing to the end 1067 //! of the reversed deque. 1068 //! 1069 //! <b>Throws</b>: Nothing. 1070 //! 1071 //! <b>Complexity</b>: Constant. 1072 BOOST_CONTAINER_ATTRIBUTE_NODISCARD BOOST_CONTAINER_FORCEINLINE rend()1073 reverse_iterator rend() BOOST_NOEXCEPT_OR_NOTHROW 1074 { return reverse_iterator(this->members_.m_start); } 1075 1076 //! <b>Effects</b>: Returns a const_reverse_iterator pointing to the end 1077 //! of the reversed deque. 1078 //! 1079 //! <b>Throws</b>: Nothing. 1080 //! 1081 //! <b>Complexity</b>: Constant. 1082 BOOST_CONTAINER_ATTRIBUTE_NODISCARD BOOST_CONTAINER_FORCEINLINE rend() const1083 const_reverse_iterator rend() const BOOST_NOEXCEPT_OR_NOTHROW 1084 { return const_reverse_iterator(this->members_.m_start); } 1085 1086 //! <b>Effects</b>: Returns a const_iterator to the first element contained in the deque. 1087 //! 1088 //! <b>Throws</b>: Nothing. 1089 //! 1090 //! <b>Complexity</b>: Constant. 1091 BOOST_CONTAINER_ATTRIBUTE_NODISCARD BOOST_CONTAINER_FORCEINLINE cbegin() const1092 const_iterator cbegin() const BOOST_NOEXCEPT_OR_NOTHROW 1093 { return this->members_.m_start; } 1094 1095 //! <b>Effects</b>: Returns a const_iterator to the end of the deque. 1096 //! 1097 //! <b>Throws</b>: Nothing. 1098 //! 1099 //! <b>Complexity</b>: Constant. 1100 BOOST_CONTAINER_ATTRIBUTE_NODISCARD BOOST_CONTAINER_FORCEINLINE cend() const1101 const_iterator cend() const BOOST_NOEXCEPT_OR_NOTHROW 1102 { return this->members_.m_finish; } 1103 1104 //! <b>Effects</b>: Returns a const_reverse_iterator pointing to the beginning 1105 //! of the reversed deque. 1106 //! 1107 //! <b>Throws</b>: Nothing. 1108 //! 1109 //! <b>Complexity</b>: Constant. 1110 BOOST_CONTAINER_ATTRIBUTE_NODISCARD BOOST_CONTAINER_FORCEINLINE crbegin() const1111 const_reverse_iterator crbegin() const BOOST_NOEXCEPT_OR_NOTHROW 1112 { return const_reverse_iterator(this->members_.m_finish); } 1113 1114 //! <b>Effects</b>: Returns a const_reverse_iterator pointing to the end 1115 //! of the reversed deque. 1116 //! 1117 //! <b>Throws</b>: Nothing. 1118 //! 1119 //! <b>Complexity</b>: Constant. 1120 BOOST_CONTAINER_ATTRIBUTE_NODISCARD BOOST_CONTAINER_FORCEINLINE crend() const1121 const_reverse_iterator crend() const BOOST_NOEXCEPT_OR_NOTHROW 1122 { return const_reverse_iterator(this->members_.m_start); } 1123 1124 ////////////////////////////////////////////// 1125 // 1126 // capacity 1127 // 1128 ////////////////////////////////////////////// 1129 1130 //! <b>Effects</b>: Returns true if the deque contains no elements. 1131 //! 1132 //! <b>Throws</b>: Nothing. 1133 //! 1134 //! <b>Complexity</b>: Constant. 1135 BOOST_CONTAINER_ATTRIBUTE_NODISCARD BOOST_CONTAINER_FORCEINLINE empty() const1136 bool empty() const BOOST_NOEXCEPT_OR_NOTHROW 1137 { return this->members_.m_finish == this->members_.m_start; } 1138 1139 //! <b>Effects</b>: Returns the number of the elements contained in the deque. 1140 //! 1141 //! <b>Throws</b>: Nothing. 1142 //! 1143 //! <b>Complexity</b>: Constant. 1144 BOOST_CONTAINER_ATTRIBUTE_NODISCARD BOOST_CONTAINER_FORCEINLINE size() const1145 size_type size() const BOOST_NOEXCEPT_OR_NOTHROW 1146 { return this->members_.m_finish - this->members_.m_start; } 1147 1148 //! <b>Effects</b>: Returns the largest possible size of the deque. 1149 //! 1150 //! <b>Throws</b>: Nothing. 1151 //! 1152 //! <b>Complexity</b>: Constant. 1153 BOOST_CONTAINER_ATTRIBUTE_NODISCARD BOOST_CONTAINER_FORCEINLINE max_size() const1154 size_type max_size() const BOOST_NOEXCEPT_OR_NOTHROW 1155 { return allocator_traits_type::max_size(this->alloc()); } 1156 1157 //! <b>Effects</b>: Inserts or erases elements at the end such that 1158 //! the size becomes n. New elements are value initialized. 1159 //! 1160 //! <b>Throws</b>: If memory allocation throws, or T's constructor throws. 1161 //! 1162 //! <b>Complexity</b>: Linear to the difference between size() and new_size. resize(size_type new_size)1163 void resize(size_type new_size) 1164 { 1165 const size_type len = size(); 1166 if (new_size < len) 1167 this->priv_erase_last_n(len - new_size); 1168 else{ 1169 const size_type n = new_size - this->size(); 1170 dtl::insert_value_initialized_n_proxy<ValAllocator, iterator> proxy; 1171 priv_insert_back_aux_impl(n, proxy); 1172 } 1173 } 1174 1175 //! <b>Effects</b>: Inserts or erases elements at the end such that 1176 //! the size becomes n. New elements are default initialized. 1177 //! 1178 //! <b>Throws</b>: If memory allocation throws, or T's constructor throws. 1179 //! 1180 //! <b>Complexity</b>: Linear to the difference between size() and new_size. 1181 //! 1182 //! <b>Note</b>: Non-standard extension resize(size_type new_size,default_init_t)1183 void resize(size_type new_size, default_init_t) 1184 { 1185 const size_type len = size(); 1186 if (new_size < len) 1187 this->priv_erase_last_n(len - new_size); 1188 else{ 1189 const size_type n = new_size - this->size(); 1190 dtl::insert_default_initialized_n_proxy<ValAllocator, iterator> proxy; 1191 priv_insert_back_aux_impl(n, proxy); 1192 } 1193 } 1194 1195 //! <b>Effects</b>: Inserts or erases elements at the end such that 1196 //! the size becomes n. New elements are copy constructed from x. 1197 //! 1198 //! <b>Throws</b>: If memory allocation throws, or T's copy constructor throws. 1199 //! 1200 //! <b>Complexity</b>: Linear to the difference between size() and new_size. resize(size_type new_size,const value_type & x)1201 void resize(size_type new_size, const value_type& x) 1202 { 1203 const size_type len = size(); 1204 if (new_size < len) 1205 this->erase(this->members_.m_start + new_size, this->members_.m_finish); 1206 else 1207 this->insert(this->members_.m_finish, new_size - len, x); 1208 } 1209 1210 //! <b>Effects</b>: Tries to deallocate the excess of memory created 1211 //! with previous allocations. The size of the deque is unchanged 1212 //! 1213 //! <b>Throws</b>: If memory allocation throws. 1214 //! 1215 //! <b>Complexity</b>: Constant. shrink_to_fit()1216 void shrink_to_fit() 1217 { 1218 //This deque implementation already 1219 //deallocates excess nodes when erasing 1220 //so there is nothing to do except for 1221 //empty deque 1222 if(this->empty()){ 1223 this->priv_clear_map(); 1224 } 1225 } 1226 1227 ////////////////////////////////////////////// 1228 // 1229 // element access 1230 // 1231 ////////////////////////////////////////////// 1232 1233 //! <b>Requires</b>: !empty() 1234 //! 1235 //! <b>Effects</b>: Returns a reference to the first 1236 //! element of the container. 1237 //! 1238 //! <b>Throws</b>: Nothing. 1239 //! 1240 //! <b>Complexity</b>: Constant. 1241 BOOST_CONTAINER_ATTRIBUTE_NODISCARD BOOST_CONTAINER_FORCEINLINE front()1242 reference front() BOOST_NOEXCEPT_OR_NOTHROW 1243 { 1244 BOOST_ASSERT(!this->empty()); 1245 return *this->members_.m_start; 1246 } 1247 1248 //! <b>Requires</b>: !empty() 1249 //! 1250 //! <b>Effects</b>: Returns a const reference to the first element 1251 //! from the beginning of the container. 1252 //! 1253 //! <b>Throws</b>: Nothing. 1254 //! 1255 //! <b>Complexity</b>: Constant. 1256 BOOST_CONTAINER_ATTRIBUTE_NODISCARD BOOST_CONTAINER_FORCEINLINE front() const1257 const_reference front() const BOOST_NOEXCEPT_OR_NOTHROW 1258 { 1259 BOOST_ASSERT(!this->empty()); 1260 return *this->members_.m_start; 1261 } 1262 1263 //! <b>Requires</b>: !empty() 1264 //! 1265 //! <b>Effects</b>: Returns a reference to the last 1266 //! element of the container. 1267 //! 1268 //! <b>Throws</b>: Nothing. 1269 //! 1270 //! <b>Complexity</b>: Constant. 1271 BOOST_CONTAINER_ATTRIBUTE_NODISCARD BOOST_CONTAINER_FORCEINLINE back()1272 reference back() BOOST_NOEXCEPT_OR_NOTHROW 1273 { 1274 BOOST_ASSERT(!this->empty()); 1275 return *(end()-1); 1276 } 1277 1278 //! <b>Requires</b>: !empty() 1279 //! 1280 //! <b>Effects</b>: Returns a const reference to the last 1281 //! element of the container. 1282 //! 1283 //! <b>Throws</b>: Nothing. 1284 //! 1285 //! <b>Complexity</b>: Constant. 1286 BOOST_CONTAINER_ATTRIBUTE_NODISCARD BOOST_CONTAINER_FORCEINLINE back() const1287 const_reference back() const BOOST_NOEXCEPT_OR_NOTHROW 1288 { 1289 BOOST_ASSERT(!this->empty()); 1290 return *(cend()-1); 1291 } 1292 1293 //! <b>Requires</b>: size() > n. 1294 //! 1295 //! <b>Effects</b>: Returns a reference to the nth element 1296 //! from the beginning of the container. 1297 //! 1298 //! <b>Throws</b>: Nothing. 1299 //! 1300 //! <b>Complexity</b>: Constant. 1301 BOOST_CONTAINER_ATTRIBUTE_NODISCARD BOOST_CONTAINER_FORCEINLINE operator [](size_type n)1302 reference operator[](size_type n) BOOST_NOEXCEPT_OR_NOTHROW 1303 { 1304 BOOST_ASSERT(this->size() > n); 1305 return this->members_.m_start[difference_type(n)]; 1306 } 1307 1308 //! <b>Requires</b>: size() > n. 1309 //! 1310 //! <b>Effects</b>: Returns a const reference to the nth element 1311 //! from the beginning of the container. 1312 //! 1313 //! <b>Throws</b>: Nothing. 1314 //! 1315 //! <b>Complexity</b>: Constant. 1316 BOOST_CONTAINER_ATTRIBUTE_NODISCARD BOOST_CONTAINER_FORCEINLINE operator [](size_type n) const1317 const_reference operator[](size_type n) const BOOST_NOEXCEPT_OR_NOTHROW 1318 { 1319 BOOST_ASSERT(this->size() > n); 1320 return this->members_.m_start[difference_type(n)]; 1321 } 1322 1323 //! <b>Requires</b>: size() >= n. 1324 //! 1325 //! <b>Effects</b>: Returns an iterator to the nth element 1326 //! from the beginning of the container. Returns end() 1327 //! if n == size(). 1328 //! 1329 //! <b>Throws</b>: Nothing. 1330 //! 1331 //! <b>Complexity</b>: Constant. 1332 //! 1333 //! <b>Note</b>: Non-standard extension 1334 BOOST_CONTAINER_ATTRIBUTE_NODISCARD BOOST_CONTAINER_FORCEINLINE nth(size_type n)1335 iterator nth(size_type n) BOOST_NOEXCEPT_OR_NOTHROW 1336 { 1337 BOOST_ASSERT(this->size() >= n); 1338 return iterator(this->begin()+n); 1339 } 1340 1341 //! <b>Requires</b>: size() >= n. 1342 //! 1343 //! <b>Effects</b>: Returns a const_iterator to the nth element 1344 //! from the beginning of the container. Returns end() 1345 //! if n == size(). 1346 //! 1347 //! <b>Throws</b>: Nothing. 1348 //! 1349 //! <b>Complexity</b>: Constant. 1350 //! 1351 //! <b>Note</b>: Non-standard extension 1352 BOOST_CONTAINER_ATTRIBUTE_NODISCARD BOOST_CONTAINER_FORCEINLINE nth(size_type n) const1353 const_iterator nth(size_type n) const BOOST_NOEXCEPT_OR_NOTHROW 1354 { 1355 BOOST_ASSERT(this->size() >= n); 1356 return const_iterator(this->cbegin()+n); 1357 } 1358 1359 //! <b>Requires</b>: begin() <= p <= end(). 1360 //! 1361 //! <b>Effects</b>: Returns the index of the element pointed by p 1362 //! and size() if p == end(). 1363 //! 1364 //! <b>Throws</b>: Nothing. 1365 //! 1366 //! <b>Complexity</b>: Constant. 1367 //! 1368 //! <b>Note</b>: Non-standard extension 1369 BOOST_CONTAINER_ATTRIBUTE_NODISCARD BOOST_CONTAINER_FORCEINLINE index_of(iterator p)1370 size_type index_of(iterator p) BOOST_NOEXCEPT_OR_NOTHROW 1371 { 1372 //Range checked priv_index_of 1373 return this->priv_index_of(p); 1374 } 1375 1376 //! <b>Requires</b>: begin() <= p <= end(). 1377 //! 1378 //! <b>Effects</b>: Returns the index of the element pointed by p 1379 //! and size() if p == end(). 1380 //! 1381 //! <b>Throws</b>: Nothing. 1382 //! 1383 //! <b>Complexity</b>: Constant. 1384 //! 1385 //! <b>Note</b>: Non-standard extension 1386 BOOST_CONTAINER_ATTRIBUTE_NODISCARD BOOST_CONTAINER_FORCEINLINE index_of(const_iterator p) const1387 size_type index_of(const_iterator p) const BOOST_NOEXCEPT_OR_NOTHROW 1388 { 1389 //Range checked priv_index_of 1390 return this->priv_index_of(p); 1391 } 1392 1393 //! <b>Requires</b>: size() > n. 1394 //! 1395 //! <b>Effects</b>: Returns a reference to the nth element 1396 //! from the beginning of the container. 1397 //! 1398 //! <b>Throws</b>: range_error if n >= size() 1399 //! 1400 //! <b>Complexity</b>: Constant. 1401 BOOST_CONTAINER_ATTRIBUTE_NODISCARD BOOST_CONTAINER_FORCEINLINE at(size_type n)1402 reference at(size_type n) 1403 { 1404 this->priv_throw_if_out_of_range(n); 1405 return (*this)[n]; 1406 } 1407 1408 //! <b>Requires</b>: size() > n. 1409 //! 1410 //! <b>Effects</b>: Returns a const reference to the nth element 1411 //! from the beginning of the container. 1412 //! 1413 //! <b>Throws</b>: range_error if n >= size() 1414 //! 1415 //! <b>Complexity</b>: Constant. 1416 BOOST_CONTAINER_ATTRIBUTE_NODISCARD BOOST_CONTAINER_FORCEINLINE at(size_type n) const1417 const_reference at(size_type n) const 1418 { 1419 this->priv_throw_if_out_of_range(n); 1420 return (*this)[n]; 1421 } 1422 1423 ////////////////////////////////////////////// 1424 // 1425 // modifiers 1426 // 1427 ////////////////////////////////////////////// 1428 1429 #if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) || defined(BOOST_CONTAINER_DOXYGEN_INVOKED) 1430 1431 //! <b>Effects</b>: Inserts an object of type T constructed with 1432 //! std::forward<Args>(args)... in the beginning of the deque. 1433 //! 1434 //! <b>Returns</b>: A reference to the created object. 1435 //! 1436 //! <b>Throws</b>: If memory allocation throws or the in-place constructor throws. 1437 //! 1438 //! <b>Complexity</b>: Amortized constant time 1439 template <class... Args> emplace_front(BOOST_FWD_REF (Args)...args)1440 reference emplace_front(BOOST_FWD_REF(Args)... args) 1441 { 1442 if(this->priv_push_front_simple_available()){ 1443 reference r = *this->priv_push_front_simple_pos(); 1444 allocator_traits_type::construct 1445 ( this->alloc() 1446 , this->priv_push_front_simple_pos() 1447 , boost::forward<Args>(args)...); 1448 this->priv_push_front_simple_commit(); 1449 return r; 1450 } 1451 else{ 1452 typedef dtl::insert_nonmovable_emplace_proxy<ValAllocator, iterator, Args...> type; 1453 return *this->priv_insert_front_aux_impl(1, type(boost::forward<Args>(args)...)); 1454 } 1455 } 1456 1457 //! <b>Effects</b>: Inserts an object of type T constructed with 1458 //! std::forward<Args>(args)... in the end of the deque. 1459 //! 1460 //! <b>Returns</b>: A reference to the created object. 1461 //! 1462 //! <b>Throws</b>: If memory allocation throws or the in-place constructor throws. 1463 //! 1464 //! <b>Complexity</b>: Amortized constant time 1465 template <class... Args> emplace_back(BOOST_FWD_REF (Args)...args)1466 reference emplace_back(BOOST_FWD_REF(Args)... args) 1467 { 1468 if(this->priv_push_back_simple_available()){ 1469 reference r = *this->priv_push_back_simple_pos(); 1470 allocator_traits_type::construct 1471 ( this->alloc() 1472 , this->priv_push_back_simple_pos() 1473 , boost::forward<Args>(args)...); 1474 this->priv_push_back_simple_commit(); 1475 return r; 1476 } 1477 else{ 1478 typedef dtl::insert_nonmovable_emplace_proxy<ValAllocator, iterator, Args...> type; 1479 return *this->priv_insert_back_aux_impl(1, type(boost::forward<Args>(args)...)); 1480 } 1481 } 1482 1483 //! <b>Requires</b>: p must be a valid iterator of *this. 1484 //! 1485 //! <b>Effects</b>: Inserts an object of type T constructed with 1486 //! std::forward<Args>(args)... before p 1487 //! 1488 //! <b>Throws</b>: If memory allocation throws or the in-place constructor throws. 1489 //! 1490 //! <b>Complexity</b>: If p is end(), amortized constant time 1491 //! Linear time otherwise. 1492 template <class... Args> emplace(const_iterator p,BOOST_FWD_REF (Args)...args)1493 iterator emplace(const_iterator p, BOOST_FWD_REF(Args)... args) 1494 { 1495 BOOST_ASSERT(this->priv_in_range_or_end(p)); 1496 if(p == this->cbegin()){ 1497 this->emplace_front(boost::forward<Args>(args)...); 1498 return this->begin(); 1499 } 1500 else if(p == this->cend()){ 1501 this->emplace_back(boost::forward<Args>(args)...); 1502 return (this->end()-1); 1503 } 1504 else{ 1505 typedef dtl::insert_emplace_proxy<ValAllocator, iterator, Args...> type; 1506 return this->priv_insert_aux_impl(p, 1, type(boost::forward<Args>(args)...)); 1507 } 1508 } 1509 1510 #else //!defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) 1511 1512 #define BOOST_CONTAINER_DEQUE_EMPLACE_CODE(N) \ 1513 BOOST_MOVE_TMPL_LT##N BOOST_MOVE_CLASS##N BOOST_MOVE_GT##N\ 1514 reference emplace_front(BOOST_MOVE_UREF##N)\ 1515 {\ 1516 if(priv_push_front_simple_available()){\ 1517 reference r = *this->priv_push_front_simple_pos();\ 1518 allocator_traits_type::construct\ 1519 ( this->alloc(), this->priv_push_front_simple_pos() BOOST_MOVE_I##N BOOST_MOVE_FWD##N);\ 1520 priv_push_front_simple_commit();\ 1521 return r;\ 1522 }\ 1523 else{\ 1524 typedef dtl::insert_nonmovable_emplace_proxy##N\ 1525 <ValAllocator, iterator BOOST_MOVE_I##N BOOST_MOVE_TARG##N> type;\ 1526 return *priv_insert_front_aux_impl(1, type(BOOST_MOVE_FWD##N));\ 1527 }\ 1528 }\ 1529 \ 1530 BOOST_MOVE_TMPL_LT##N BOOST_MOVE_CLASS##N BOOST_MOVE_GT##N\ 1531 reference emplace_back(BOOST_MOVE_UREF##N)\ 1532 {\ 1533 if(priv_push_back_simple_available()){\ 1534 reference r = *this->priv_push_back_simple_pos();\ 1535 allocator_traits_type::construct\ 1536 ( this->alloc(), this->priv_push_back_simple_pos() BOOST_MOVE_I##N BOOST_MOVE_FWD##N);\ 1537 priv_push_back_simple_commit();\ 1538 return r;\ 1539 }\ 1540 else{\ 1541 typedef dtl::insert_nonmovable_emplace_proxy##N\ 1542 <ValAllocator, iterator BOOST_MOVE_I##N BOOST_MOVE_TARG##N> type;\ 1543 return *priv_insert_back_aux_impl(1, type(BOOST_MOVE_FWD##N));\ 1544 }\ 1545 }\ 1546 \ 1547 BOOST_MOVE_TMPL_LT##N BOOST_MOVE_CLASS##N BOOST_MOVE_GT##N\ 1548 iterator emplace(const_iterator p BOOST_MOVE_I##N BOOST_MOVE_UREF##N)\ 1549 {\ 1550 BOOST_ASSERT(this->priv_in_range_or_end(p));\ 1551 if(p == this->cbegin()){\ 1552 this->emplace_front(BOOST_MOVE_FWD##N);\ 1553 return this->begin();\ 1554 }\ 1555 else if(p == cend()){\ 1556 this->emplace_back(BOOST_MOVE_FWD##N);\ 1557 return (--this->end());\ 1558 }\ 1559 else{\ 1560 typedef dtl::insert_emplace_proxy_arg##N\ 1561 <ValAllocator, iterator BOOST_MOVE_I##N BOOST_MOVE_TARG##N> type;\ 1562 return this->priv_insert_aux_impl(p, 1, type(BOOST_MOVE_FWD##N));\ 1563 }\ 1564 } 1565 // 1566 BOOST_MOVE_ITERATE_0TO9(BOOST_CONTAINER_DEQUE_EMPLACE_CODE) 1567 #undef BOOST_CONTAINER_DEQUE_EMPLACE_CODE 1568 1569 #endif // !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) 1570 1571 #if defined(BOOST_CONTAINER_DOXYGEN_INVOKED) 1572 //! <b>Effects</b>: Inserts a copy of x at the front of the deque. 1573 //! 1574 //! <b>Throws</b>: If memory allocation throws or 1575 //! T's copy constructor throws. 1576 //! 1577 //! <b>Complexity</b>: Amortized constant time. 1578 void push_front(const T &x); 1579 1580 //! <b>Effects</b>: Constructs a new element in the front of the deque 1581 //! and moves the resources of x to this new element. 1582 //! 1583 //! <b>Throws</b>: If memory allocation throws. 1584 //! 1585 //! <b>Complexity</b>: Amortized constant time. 1586 void push_front(T &&x); 1587 #else 1588 BOOST_MOVE_CONVERSION_AWARE_CATCH(push_front, T, void, priv_push_front) 1589 #endif 1590 1591 #if defined(BOOST_CONTAINER_DOXYGEN_INVOKED) 1592 //! <b>Effects</b>: Inserts a copy of x at the end of the deque. 1593 //! 1594 //! <b>Throws</b>: If memory allocation throws or 1595 //! T's copy constructor throws. 1596 //! 1597 //! <b>Complexity</b>: Amortized constant time. 1598 void push_back(const T &x); 1599 1600 //! <b>Effects</b>: Constructs a new element in the end of the deque 1601 //! and moves the resources of x to this new element. 1602 //! 1603 //! <b>Throws</b>: If memory allocation throws. 1604 //! 1605 //! <b>Complexity</b>: Amortized constant time. 1606 void push_back(T &&x); 1607 #else 1608 BOOST_MOVE_CONVERSION_AWARE_CATCH(push_back, T, void, priv_push_back) 1609 #endif 1610 1611 #if defined(BOOST_CONTAINER_DOXYGEN_INVOKED) 1612 1613 //! <b>Requires</b>: p must be a valid iterator of *this. 1614 //! 1615 //! <b>Effects</b>: Insert a copy of x before p. 1616 //! 1617 //! <b>Returns</b>: an iterator to the inserted element. 1618 //! 1619 //! <b>Throws</b>: If memory allocation throws or x's copy constructor throws. 1620 //! 1621 //! <b>Complexity</b>: If p is end(), amortized constant time 1622 //! Linear time otherwise. 1623 iterator insert(const_iterator p, const T &x); 1624 1625 //! <b>Requires</b>: p must be a valid iterator of *this. 1626 //! 1627 //! <b>Effects</b>: Insert a new element before p with x's resources. 1628 //! 1629 //! <b>Returns</b>: an iterator to the inserted element. 1630 //! 1631 //! <b>Throws</b>: If memory allocation throws. 1632 //! 1633 //! <b>Complexity</b>: If p is end(), amortized constant time 1634 //! Linear time otherwise. 1635 iterator insert(const_iterator p, T &&x); 1636 #else 1637 BOOST_MOVE_CONVERSION_AWARE_CATCH_1ARG(insert, T, iterator, priv_insert, const_iterator, const_iterator) 1638 #endif 1639 1640 //! <b>Requires</b>: pos must be a valid iterator of *this. 1641 //! 1642 //! <b>Effects</b>: Insert n copies of x before pos. 1643 //! 1644 //! <b>Returns</b>: an iterator to the first inserted element or pos if n is 0. 1645 //! 1646 //! <b>Throws</b>: If memory allocation throws or T's copy constructor throws. 1647 //! 1648 //! <b>Complexity</b>: Linear to n. insert(const_iterator pos,size_type n,const value_type & x)1649 BOOST_CONTAINER_FORCEINLINE iterator insert(const_iterator pos, size_type n, const value_type& x) 1650 { 1651 //Range check of p is done by insert() 1652 typedef constant_iterator<value_type, difference_type> c_it; 1653 return this->insert(pos, c_it(x, n), c_it()); 1654 } 1655 1656 //! <b>Requires</b>: pos must be a valid iterator of *this. 1657 //! 1658 //! <b>Effects</b>: Insert a copy of the [first, last) range before pos. 1659 //! 1660 //! <b>Returns</b>: an iterator to the first inserted element or pos if first == last. 1661 //! 1662 //! <b>Throws</b>: If memory allocation throws, T's constructor from a 1663 //! dereferenced InIt throws or T's copy constructor throws. 1664 //! 1665 //! <b>Complexity</b>: Linear to distance [first, last). 1666 template <class InIt> insert(const_iterator pos,InIt first,InIt last,typename dtl::disable_if_or<void,dtl::is_convertible<InIt,size_type>,dtl::is_not_input_iterator<InIt>>::type * =0)1667 iterator insert(const_iterator pos, InIt first, InIt last 1668 #if !defined(BOOST_CONTAINER_DOXYGEN_INVOKED) 1669 , typename dtl::disable_if_or 1670 < void 1671 , dtl::is_convertible<InIt, size_type> 1672 , dtl::is_not_input_iterator<InIt> 1673 >::type * = 0 1674 #endif 1675 ) 1676 { 1677 BOOST_ASSERT(this->priv_in_range_or_end(pos)); 1678 size_type n = 0; 1679 iterator it(pos.unconst()); 1680 for(;first != last; ++first, ++n){ 1681 it = this->emplace(it, *first); 1682 ++it; 1683 } 1684 it -= n; 1685 return it; 1686 } 1687 1688 #if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST) 1689 //! <b>Requires</b>: pos must be a valid iterator of *this. 1690 //! 1691 //! <b>Effects</b>: Insert a copy of the [il.begin(), il.end()) range before pos. 1692 //! 1693 //! <b>Returns</b>: an iterator to the first inserted element or pos if il.begin() == il.end(). 1694 //! 1695 //! <b>Throws</b>: If memory allocation throws, T's constructor from a 1696 //! dereferenced std::initializer_list throws or T's copy constructor throws. 1697 //! 1698 //! <b>Complexity</b>: Linear to distance [il.begin(), il.end()). insert(const_iterator pos,std::initializer_list<value_type> il)1699 BOOST_CONTAINER_FORCEINLINE iterator insert(const_iterator pos, std::initializer_list<value_type> il) 1700 { 1701 //Range check os pos is done in insert() 1702 return insert(pos, il.begin(), il.end()); 1703 } 1704 #endif 1705 1706 #if !defined(BOOST_CONTAINER_DOXYGEN_INVOKED) 1707 template <class FwdIt> insert(const_iterator p,FwdIt first,FwdIt last,typename dtl::disable_if_or<void,dtl::is_convertible<FwdIt,size_type>,dtl::is_input_iterator<FwdIt>>::type * =0)1708 BOOST_CONTAINER_FORCEINLINE iterator insert(const_iterator p, FwdIt first, FwdIt last 1709 #if !defined(BOOST_CONTAINER_DOXYGEN_INVOKED) 1710 , typename dtl::disable_if_or 1711 < void 1712 , dtl::is_convertible<FwdIt, size_type> 1713 , dtl::is_input_iterator<FwdIt> 1714 >::type * = 0 1715 #endif 1716 ) 1717 { 1718 BOOST_ASSERT(this->priv_in_range_or_end(p)); 1719 dtl::insert_range_proxy<ValAllocator, FwdIt, iterator> proxy(first); 1720 return priv_insert_aux_impl(p, boost::container::iterator_distance(first, last), proxy); 1721 } 1722 #endif 1723 1724 //! <b>Effects</b>: Removes the first element from the deque. 1725 //! 1726 //! <b>Throws</b>: Nothing. 1727 //! 1728 //! <b>Complexity</b>: Constant time. pop_front()1729 void pop_front() BOOST_NOEXCEPT_OR_NOTHROW 1730 { 1731 BOOST_ASSERT(!this->empty()); 1732 if (this->members_.m_start.m_cur != this->members_.m_start.m_last - 1) { 1733 allocator_traits_type::destroy 1734 ( this->alloc() 1735 , boost::movelib::to_raw_pointer(this->members_.m_start.m_cur) 1736 ); 1737 ++this->members_.m_start.m_cur; 1738 } 1739 else 1740 this->priv_pop_front_aux(); 1741 } 1742 1743 //! <b>Effects</b>: Removes the last element from the deque. 1744 //! 1745 //! <b>Throws</b>: Nothing. 1746 //! 1747 //! <b>Complexity</b>: Constant time. pop_back()1748 void pop_back() BOOST_NOEXCEPT_OR_NOTHROW 1749 { 1750 BOOST_ASSERT(!this->empty()); 1751 if (this->members_.m_finish.m_cur != this->members_.m_finish.m_first) { 1752 --this->members_.m_finish.m_cur; 1753 allocator_traits_type::destroy 1754 ( this->alloc() 1755 , boost::movelib::to_raw_pointer(this->members_.m_finish.m_cur) 1756 ); 1757 } 1758 else 1759 this->priv_pop_back_aux(); 1760 } 1761 1762 //! <b>Effects</b>: Erases the element at p. 1763 //! 1764 //! <b>Throws</b>: Nothing. 1765 //! 1766 //! <b>Complexity</b>: Linear to the elements between pos and the 1767 //! last element (if pos is near the end) or the first element 1768 //! if(pos is near the beginning). 1769 //! Constant if pos is the first or the last element. erase(const_iterator pos)1770 iterator erase(const_iterator pos) BOOST_NOEXCEPT_OR_NOTHROW 1771 { 1772 BOOST_ASSERT(this->priv_in_range(pos)); 1773 iterator next = pos.unconst(); 1774 ++next; 1775 size_type index = pos - this->members_.m_start; 1776 if (index < (this->size()/2)) { 1777 boost::container::move_backward(this->begin(), pos.unconst(), next); 1778 pop_front(); 1779 } 1780 else { 1781 boost::container::move(next, this->end(), pos.unconst()); 1782 pop_back(); 1783 } 1784 return this->members_.m_start + index; 1785 } 1786 1787 //! <b>Effects</b>: Erases the elements pointed by [first, last). 1788 //! 1789 //! <b>Throws</b>: Nothing. 1790 //! 1791 //! <b>Complexity</b>: Linear to the distance between first and 1792 //! last plus the elements between pos and the 1793 //! last element (if pos is near the end) or the first element 1794 //! if(pos is near the beginning). erase(const_iterator first,const_iterator last)1795 iterator erase(const_iterator first, const_iterator last) BOOST_NOEXCEPT_OR_NOTHROW 1796 { 1797 BOOST_ASSERT(first == last || 1798 (first < last && this->priv_in_range(first) && this->priv_in_range_or_end(last))); 1799 if (first == this->members_.m_start && last == this->members_.m_finish) { 1800 this->clear(); 1801 return this->members_.m_finish; 1802 } 1803 else { 1804 const size_type n = static_cast<size_type>(last - first); 1805 const size_type elems_before = static_cast<size_type>(first - this->members_.m_start); 1806 if (elems_before < (this->size() - n) - elems_before) { 1807 boost::container::move_backward(begin(), first.unconst(), last.unconst()); 1808 iterator new_start = this->members_.m_start + n; 1809 this->priv_destroy_range(this->members_.m_start, new_start); 1810 this->priv_destroy_nodes(this->members_.m_start.m_node, new_start.m_node); 1811 this->members_.m_start = new_start; 1812 } 1813 else { 1814 boost::container::move(last.unconst(), end(), first.unconst()); 1815 iterator new_finish = this->members_.m_finish - n; 1816 this->priv_destroy_range(new_finish, this->members_.m_finish); 1817 this->priv_destroy_nodes(new_finish.m_node + 1, this->members_.m_finish.m_node + 1); 1818 this->members_.m_finish = new_finish; 1819 } 1820 return this->members_.m_start + elems_before; 1821 } 1822 } 1823 1824 //! <b>Effects</b>: Swaps the contents of *this and x. 1825 //! 1826 //! <b>Throws</b>: Nothing. 1827 //! 1828 //! <b>Complexity</b>: Constant. swap(deque & x)1829 BOOST_CONTAINER_FORCEINLINE void swap(deque &x) 1830 BOOST_NOEXCEPT_IF(allocator_traits_type::propagate_on_container_swap::value 1831 || allocator_traits_type::is_always_equal::value) 1832 { 1833 this->swap_members(x); 1834 dtl::bool_<allocator_traits_type::propagate_on_container_swap::value> flag; 1835 dtl::swap_alloc(this->alloc(), x.alloc(), flag); 1836 dtl::swap_alloc(this->ptr_alloc(), x.ptr_alloc(), flag); 1837 } 1838 1839 //! <b>Effects</b>: Erases all the elements of the deque. 1840 //! 1841 //! <b>Throws</b>: Nothing. 1842 //! 1843 //! <b>Complexity</b>: Linear to the number of elements in the deque. clear()1844 void clear() BOOST_NOEXCEPT_OR_NOTHROW 1845 { 1846 if (this->members_.m_finish != this->members_.m_start) { 1847 1848 for (index_pointer node = this->members_.m_start.m_node + 1; 1849 node < this->members_.m_finish.m_node; 1850 ++node) { 1851 this->priv_destroy_range(*node, *node + get_block_size()); 1852 this->priv_deallocate_node(*node); 1853 } 1854 1855 if (this->members_.m_start.m_node != this->members_.m_finish.m_node) { 1856 this->priv_destroy_range(this->members_.m_start.m_cur, this->members_.m_start.m_last); 1857 this->priv_destroy_range(this->members_.m_finish.m_first, this->members_.m_finish.m_cur); 1858 this->priv_deallocate_node(this->members_.m_finish.m_first); 1859 } 1860 else 1861 this->priv_destroy_range(this->members_.m_start.m_cur, this->members_.m_finish.m_cur); 1862 1863 this->members_.m_finish = this->members_.m_start; 1864 } 1865 } 1866 1867 //! <b>Effects</b>: Returns true if x and y are equal 1868 //! 1869 //! <b>Complexity</b>: Linear to the number of elements in the container. 1870 BOOST_CONTAINER_ATTRIBUTE_NODISCARD BOOST_CONTAINER_FORCEINLINE operator ==(const deque & x,const deque & y)1871 friend bool operator==(const deque& x, const deque& y) 1872 { return x.size() == y.size() && ::boost::container::algo_equal(x.begin(), x.end(), y.begin()); } 1873 1874 //! <b>Effects</b>: Returns true if x and y are unequal 1875 //! 1876 //! <b>Complexity</b>: Linear to the number of elements in the container. 1877 BOOST_CONTAINER_ATTRIBUTE_NODISCARD BOOST_CONTAINER_FORCEINLINE operator !=(const deque & x,const deque & y)1878 friend bool operator!=(const deque& x, const deque& y) 1879 { return !(x == y); } 1880 1881 //! <b>Effects</b>: Returns true if x is less than y 1882 //! 1883 //! <b>Complexity</b>: Linear to the number of elements in the container. 1884 BOOST_CONTAINER_ATTRIBUTE_NODISCARD BOOST_CONTAINER_FORCEINLINE operator <(const deque & x,const deque & y)1885 friend bool operator<(const deque& x, const deque& y) 1886 { return ::boost::container::algo_lexicographical_compare(x.begin(), x.end(), y.begin(), y.end()); } 1887 1888 //! <b>Effects</b>: Returns true if x is greater than y 1889 //! 1890 //! <b>Complexity</b>: Linear to the number of elements in the container. 1891 BOOST_CONTAINER_ATTRIBUTE_NODISCARD BOOST_CONTAINER_FORCEINLINE operator >(const deque & x,const deque & y)1892 friend bool operator>(const deque& x, const deque& y) 1893 { return y < x; } 1894 1895 //! <b>Effects</b>: Returns true if x is equal or less than y 1896 //! 1897 //! <b>Complexity</b>: Linear to the number of elements in the container. 1898 BOOST_CONTAINER_ATTRIBUTE_NODISCARD BOOST_CONTAINER_FORCEINLINE operator <=(const deque & x,const deque & y)1899 friend bool operator<=(const deque& x, const deque& y) 1900 { return !(y < x); } 1901 1902 //! <b>Effects</b>: Returns true if x is equal or greater than y 1903 //! 1904 //! <b>Complexity</b>: Linear to the number of elements in the container. 1905 BOOST_CONTAINER_ATTRIBUTE_NODISCARD BOOST_CONTAINER_FORCEINLINE operator >=(const deque & x,const deque & y)1906 friend bool operator>=(const deque& x, const deque& y) 1907 { return !(x < y); } 1908 1909 //! <b>Effects</b>: x.swap(y) 1910 //! 1911 //! <b>Complexity</b>: Constant. swap(deque & x,deque & y)1912 BOOST_CONTAINER_FORCEINLINE friend void swap(deque& x, deque& y) 1913 BOOST_NOEXCEPT_IF(BOOST_NOEXCEPT(x.swap(y))) 1914 { x.swap(y); } 1915 1916 #ifndef BOOST_CONTAINER_DOXYGEN_INVOKED 1917 private: 1918 priv_index_of(const_iterator p) const1919 BOOST_CONTAINER_FORCEINLINE size_type priv_index_of(const_iterator p) const 1920 { 1921 BOOST_ASSERT(this->cbegin() <= p); 1922 BOOST_ASSERT(p <= this->cend()); 1923 return static_cast<size_type>(p - this->cbegin()); 1924 } 1925 priv_erase_last_n(size_type n)1926 void priv_erase_last_n(size_type n) 1927 { 1928 if(n == this->size()) { 1929 this->clear(); 1930 } 1931 else { 1932 iterator new_finish = this->members_.m_finish - n; 1933 this->priv_destroy_range(new_finish, this->members_.m_finish); 1934 this->priv_destroy_nodes(new_finish.m_node + 1, this->members_.m_finish.m_node + 1); 1935 this->members_.m_finish = new_finish; 1936 } 1937 } 1938 priv_throw_if_out_of_range(size_type n) const1939 void priv_throw_if_out_of_range(size_type n) const 1940 { 1941 if (n >= this->size()) 1942 throw_out_of_range("deque::at out of range"); 1943 } 1944 priv_in_range(const_iterator pos) const1945 BOOST_CONTAINER_FORCEINLINE bool priv_in_range(const_iterator pos) const 1946 { 1947 return (this->begin() <= pos) && (pos < this->end()); 1948 } 1949 priv_in_range_or_end(const_iterator pos) const1950 BOOST_CONTAINER_FORCEINLINE bool priv_in_range_or_end(const_iterator pos) const 1951 { 1952 return (this->begin() <= pos) && (pos <= this->end()); 1953 } 1954 1955 template <class U> priv_insert(const_iterator p,BOOST_FWD_REF (U)x)1956 iterator priv_insert(const_iterator p, BOOST_FWD_REF(U) x) 1957 { 1958 BOOST_ASSERT(this->priv_in_range_or_end(p)); 1959 if (p == cbegin()){ 1960 this->push_front(::boost::forward<U>(x)); 1961 return begin(); 1962 } 1963 else if (p == cend()){ 1964 this->push_back(::boost::forward<U>(x)); 1965 return --end(); 1966 } 1967 else { 1968 return priv_insert_aux_impl 1969 ( p, (size_type)1 1970 , dtl::get_insert_value_proxy<iterator, ValAllocator>(::boost::forward<U>(x))); 1971 } 1972 } 1973 1974 template <class U> priv_push_front(BOOST_FWD_REF (U)x)1975 void priv_push_front(BOOST_FWD_REF(U) x) 1976 { 1977 if(this->priv_push_front_simple_available()){ 1978 allocator_traits_type::construct 1979 ( this->alloc(), this->priv_push_front_simple_pos(), ::boost::forward<U>(x)); 1980 this->priv_push_front_simple_commit(); 1981 } 1982 else{ 1983 priv_insert_aux_impl 1984 ( this->cbegin(), (size_type)1 1985 , dtl::get_insert_value_proxy<iterator, ValAllocator>(::boost::forward<U>(x))); 1986 } 1987 } 1988 1989 template <class U> priv_push_back(BOOST_FWD_REF (U)x)1990 void priv_push_back(BOOST_FWD_REF(U) x) 1991 { 1992 if(this->priv_push_back_simple_available()){ 1993 allocator_traits_type::construct 1994 ( this->alloc(), this->priv_push_back_simple_pos(), ::boost::forward<U>(x)); 1995 this->priv_push_back_simple_commit(); 1996 } 1997 else{ 1998 priv_insert_aux_impl 1999 ( this->cend(), (size_type)1 2000 , dtl::get_insert_value_proxy<iterator, ValAllocator>(::boost::forward<U>(x))); 2001 } 2002 } 2003 priv_push_back_simple_available() const2004 BOOST_CONTAINER_FORCEINLINE bool priv_push_back_simple_available() const 2005 { 2006 return this->members_.m_map && 2007 (this->members_.m_finish.m_cur != (this->members_.m_finish.m_last - 1)); 2008 } 2009 priv_push_back_simple_pos() const2010 BOOST_CONTAINER_FORCEINLINE T *priv_push_back_simple_pos() const 2011 { 2012 return boost::movelib::to_raw_pointer(this->members_.m_finish.m_cur); 2013 } 2014 priv_push_back_simple_commit()2015 BOOST_CONTAINER_FORCEINLINE void priv_push_back_simple_commit() 2016 { 2017 ++this->members_.m_finish.m_cur; 2018 } 2019 priv_push_front_simple_available() const2020 BOOST_CONTAINER_FORCEINLINE bool priv_push_front_simple_available() const 2021 { 2022 return this->members_.m_map && 2023 (this->members_.m_start.m_cur != this->members_.m_start.m_first); 2024 } 2025 priv_push_front_simple_pos() const2026 BOOST_CONTAINER_FORCEINLINE T *priv_push_front_simple_pos() const 2027 { return boost::movelib::to_raw_pointer(this->members_.m_start.m_cur) - 1; } 2028 priv_push_front_simple_commit()2029 BOOST_CONTAINER_FORCEINLINE void priv_push_front_simple_commit() 2030 { --this->members_.m_start.m_cur; } 2031 priv_destroy_range(iterator p,iterator p2)2032 void priv_destroy_range(iterator p, iterator p2) 2033 { 2034 if(!Base::traits_t::trivial_dctr){ 2035 for(;p != p2; ++p){ 2036 allocator_traits_type::destroy(this->alloc(), boost::movelib::iterator_to_raw_pointer(p)); 2037 } 2038 } 2039 } 2040 priv_destroy_range(pointer p,pointer p2)2041 void priv_destroy_range(pointer p, pointer p2) 2042 { 2043 if(!Base::traits_t::trivial_dctr){ 2044 for(;p != p2; ++p){ 2045 allocator_traits_type::destroy(this->alloc(), boost::movelib::iterator_to_raw_pointer(p)); 2046 } 2047 } 2048 } 2049 2050 template<class InsertProxy> priv_insert_aux_impl(const_iterator p,size_type n,InsertProxy proxy)2051 iterator priv_insert_aux_impl(const_iterator p, size_type n, InsertProxy proxy) 2052 { 2053 iterator pos(p.unconst()); 2054 const size_type pos_n = p - this->cbegin(); 2055 if(!this->members_.m_map){ 2056 this->priv_initialize_map(0); 2057 pos = this->begin(); 2058 } 2059 2060 const size_type elemsbefore = static_cast<size_type>(pos - this->members_.m_start); 2061 const size_type length = this->size(); 2062 if (elemsbefore < length / 2) { 2063 const iterator new_start = this->priv_reserve_elements_at_front(n); 2064 const iterator old_start = this->members_.m_start; 2065 if(!elemsbefore){ 2066 proxy.uninitialized_copy_n_and_update(this->alloc(), new_start, n); 2067 this->members_.m_start = new_start; 2068 } 2069 else{ 2070 pos = this->members_.m_start + elemsbefore; 2071 if (elemsbefore >= n) { 2072 const iterator start_n = this->members_.m_start + n; 2073 ::boost::container::uninitialized_move_alloc 2074 (this->alloc(), this->members_.m_start, start_n, new_start); 2075 this->members_.m_start = new_start; 2076 boost::container::move(start_n, pos, old_start); 2077 proxy.copy_n_and_update(this->alloc(), pos - n, n); 2078 } 2079 else { 2080 const size_type mid_count = n - elemsbefore; 2081 const iterator mid_start = old_start - mid_count; 2082 proxy.uninitialized_copy_n_and_update(this->alloc(), mid_start, mid_count); 2083 this->members_.m_start = mid_start; 2084 ::boost::container::uninitialized_move_alloc 2085 (this->alloc(), old_start, pos, new_start); 2086 this->members_.m_start = new_start; 2087 proxy.copy_n_and_update(this->alloc(), old_start, elemsbefore); 2088 } 2089 } 2090 } 2091 else { 2092 const iterator new_finish = this->priv_reserve_elements_at_back(n); 2093 const iterator old_finish = this->members_.m_finish; 2094 const size_type elemsafter = length - elemsbefore; 2095 if(!elemsafter){ 2096 proxy.uninitialized_copy_n_and_update(this->alloc(), old_finish, n); 2097 this->members_.m_finish = new_finish; 2098 } 2099 else{ 2100 pos = old_finish - elemsafter; 2101 if (elemsafter >= n) { 2102 iterator finish_n = old_finish - difference_type(n); 2103 ::boost::container::uninitialized_move_alloc 2104 (this->alloc(), finish_n, old_finish, old_finish); 2105 this->members_.m_finish = new_finish; 2106 boost::container::move_backward(pos, finish_n, old_finish); 2107 proxy.copy_n_and_update(this->alloc(), pos, n); 2108 } 2109 else { 2110 const size_type raw_gap = n - elemsafter; 2111 ::boost::container::uninitialized_move_alloc 2112 (this->alloc(), pos, old_finish, old_finish + raw_gap); 2113 BOOST_TRY{ 2114 proxy.copy_n_and_update(this->alloc(), pos, elemsafter); 2115 proxy.uninitialized_copy_n_and_update(this->alloc(), old_finish, raw_gap); 2116 } 2117 BOOST_CATCH(...){ 2118 this->priv_destroy_range(old_finish, old_finish + elemsafter); 2119 BOOST_RETHROW 2120 } 2121 BOOST_CATCH_END 2122 this->members_.m_finish = new_finish; 2123 } 2124 } 2125 } 2126 return this->begin() + pos_n; 2127 } 2128 2129 template <class InsertProxy> priv_insert_back_aux_impl(size_type n,InsertProxy proxy)2130 iterator priv_insert_back_aux_impl(size_type n, InsertProxy proxy) 2131 { 2132 if(!this->members_.m_map){ 2133 this->priv_initialize_map(0); 2134 } 2135 2136 iterator new_finish = this->priv_reserve_elements_at_back(n); 2137 iterator old_finish = this->members_.m_finish; 2138 proxy.uninitialized_copy_n_and_update(this->alloc(), old_finish, n); 2139 this->members_.m_finish = new_finish; 2140 return iterator(this->members_.m_finish - n); 2141 } 2142 2143 template <class InsertProxy> priv_insert_front_aux_impl(size_type n,InsertProxy proxy)2144 iterator priv_insert_front_aux_impl(size_type n, InsertProxy proxy) 2145 { 2146 if(!this->members_.m_map){ 2147 this->priv_initialize_map(0); 2148 } 2149 2150 iterator new_start = this->priv_reserve_elements_at_front(n); 2151 proxy.uninitialized_copy_n_and_update(this->alloc(), new_start, n); 2152 this->members_.m_start = new_start; 2153 return new_start; 2154 } 2155 priv_fill_insert(const_iterator pos,size_type n,const value_type & x)2156 BOOST_CONTAINER_FORCEINLINE iterator priv_fill_insert(const_iterator pos, size_type n, const value_type& x) 2157 { 2158 typedef constant_iterator<value_type, difference_type> c_it; 2159 return this->insert(pos, c_it(x, n), c_it()); 2160 } 2161 2162 // Precondition: this->members_.m_start and this->members_.m_finish have already been initialized, 2163 // but none of the deque's elements have yet been constructed. priv_fill_initialize(const value_type & value)2164 void priv_fill_initialize(const value_type& value) 2165 { 2166 index_pointer cur = this->members_.m_start.m_node; 2167 BOOST_TRY { 2168 for ( ; cur < this->members_.m_finish.m_node; ++cur){ 2169 boost::container::uninitialized_fill_alloc 2170 (this->alloc(), *cur, *cur + get_block_size(), value); 2171 } 2172 boost::container::uninitialized_fill_alloc 2173 (this->alloc(), this->members_.m_finish.m_first, this->members_.m_finish.m_cur, value); 2174 } 2175 BOOST_CATCH(...){ 2176 this->priv_destroy_range(this->members_.m_start, iterator(*cur, cur, get_block_size())); 2177 BOOST_RETHROW 2178 } 2179 BOOST_CATCH_END 2180 } 2181 2182 template <class InIt> priv_range_initialize(InIt first,InIt last,typename iterator_enable_if_tag<InIt,std::input_iterator_tag>::type * =0)2183 void priv_range_initialize(InIt first, InIt last, typename iterator_enable_if_tag<InIt, std::input_iterator_tag>::type* =0) 2184 { 2185 this->priv_initialize_map(0); 2186 BOOST_TRY { 2187 for ( ; first != last; ++first) 2188 this->emplace_back(*first); 2189 } 2190 BOOST_CATCH(...){ 2191 this->clear(); 2192 BOOST_RETHROW 2193 } 2194 BOOST_CATCH_END 2195 } 2196 2197 template <class FwdIt> priv_range_initialize(FwdIt first,FwdIt last,typename iterator_disable_if_tag<FwdIt,std::input_iterator_tag>::type * =0)2198 void priv_range_initialize(FwdIt first, FwdIt last, typename iterator_disable_if_tag<FwdIt, std::input_iterator_tag>::type* =0) 2199 { 2200 size_type n = 0; 2201 n = boost::container::iterator_distance(first, last); 2202 this->priv_initialize_map(n); 2203 2204 index_pointer cur_node = this->members_.m_start.m_node; 2205 BOOST_TRY { 2206 for (; cur_node < this->members_.m_finish.m_node; ++cur_node) { 2207 FwdIt mid = first; 2208 boost::container::iterator_advance(mid, get_block_size()); 2209 ::boost::container::uninitialized_copy_alloc(this->alloc(), first, mid, *cur_node); 2210 first = mid; 2211 } 2212 ::boost::container::uninitialized_copy_alloc(this->alloc(), first, last, this->members_.m_finish.m_first); 2213 } 2214 BOOST_CATCH(...){ 2215 this->priv_destroy_range(this->members_.m_start, iterator(*cur_node, cur_node, get_block_size())); 2216 BOOST_RETHROW 2217 } 2218 BOOST_CATCH_END 2219 } 2220 2221 // Called only if this->members_.m_finish.m_cur == this->members_.m_finish.m_first. priv_pop_back_aux()2222 void priv_pop_back_aux() BOOST_NOEXCEPT_OR_NOTHROW 2223 { 2224 this->priv_deallocate_node(this->members_.m_finish.m_first); 2225 this->members_.m_finish.priv_set_node(this->members_.m_finish.m_node - 1, get_block_size()); 2226 this->members_.m_finish.m_cur = this->members_.m_finish.m_last - 1; 2227 allocator_traits_type::destroy 2228 ( this->alloc() 2229 , boost::movelib::to_raw_pointer(this->members_.m_finish.m_cur) 2230 ); 2231 } 2232 2233 // Called only if this->members_.m_start.m_cur == this->members_.m_start.m_last - 1. Note that 2234 // if the deque has at least one element (a precondition for this member 2235 // function), and if this->members_.m_start.m_cur == this->members_.m_start.m_last, then the deque 2236 // must have at least two nodes. priv_pop_front_aux()2237 void priv_pop_front_aux() BOOST_NOEXCEPT_OR_NOTHROW 2238 { 2239 allocator_traits_type::destroy 2240 ( this->alloc() 2241 , boost::movelib::to_raw_pointer(this->members_.m_start.m_cur) 2242 ); 2243 this->priv_deallocate_node(this->members_.m_start.m_first); 2244 this->members_.m_start.priv_set_node(this->members_.m_start.m_node + 1, get_block_size()); 2245 this->members_.m_start.m_cur = this->members_.m_start.m_first; 2246 } 2247 priv_reserve_elements_at_front(size_type n)2248 iterator priv_reserve_elements_at_front(size_type n) 2249 { 2250 size_type vacancies = this->members_.m_start.m_cur - this->members_.m_start.m_first; 2251 if (n > vacancies){ 2252 size_type new_elems = n-vacancies; 2253 size_type new_nodes = (new_elems + get_block_size() - 1) / 2254 get_block_size(); 2255 size_type s = (size_type)(this->members_.m_start.m_node - this->members_.m_map); 2256 if (new_nodes > s){ 2257 this->priv_reallocate_map(new_nodes, true); 2258 } 2259 size_type i = 1; 2260 BOOST_TRY { 2261 for (; i <= new_nodes; ++i) 2262 *(this->members_.m_start.m_node - i) = this->priv_allocate_node(); 2263 } 2264 BOOST_CATCH(...) { 2265 for (size_type j = 1; j < i; ++j) 2266 this->priv_deallocate_node(*(this->members_.m_start.m_node - j)); 2267 BOOST_RETHROW 2268 } 2269 BOOST_CATCH_END 2270 } 2271 return this->members_.m_start - difference_type(n); 2272 } 2273 priv_reserve_elements_at_back(size_type n)2274 iterator priv_reserve_elements_at_back(size_type n) 2275 { 2276 size_type vacancies = (this->members_.m_finish.m_last - this->members_.m_finish.m_cur) - 1; 2277 if (n > vacancies){ 2278 size_type new_elems = n - vacancies; 2279 size_type new_nodes = (new_elems + get_block_size() - 1)/get_block_size(); 2280 size_type s = (size_type)(this->members_.m_map_size - (this->members_.m_finish.m_node - this->members_.m_map)); 2281 if (new_nodes + 1 > s){ 2282 this->priv_reallocate_map(new_nodes, false); 2283 } 2284 size_type i = 1; 2285 BOOST_TRY { 2286 for (; i <= new_nodes; ++i) 2287 *(this->members_.m_finish.m_node + i) = this->priv_allocate_node(); 2288 } 2289 BOOST_CATCH(...) { 2290 for (size_type j = 1; j < i; ++j) 2291 this->priv_deallocate_node(*(this->members_.m_finish.m_node + j)); 2292 BOOST_RETHROW 2293 } 2294 BOOST_CATCH_END 2295 } 2296 return this->members_.m_finish + difference_type(n); 2297 } 2298 priv_reallocate_map(size_type nodes_to_add,bool add_at_front)2299 void priv_reallocate_map(size_type nodes_to_add, bool add_at_front) 2300 { 2301 size_type old_num_nodes = this->members_.m_finish.m_node - this->members_.m_start.m_node + 1; 2302 size_type new_num_nodes = old_num_nodes + nodes_to_add; 2303 2304 index_pointer new_nstart; 2305 if (this->members_.m_map_size > 2 * new_num_nodes) { 2306 new_nstart = this->members_.m_map + (this->members_.m_map_size - new_num_nodes) / 2 2307 + (add_at_front ? nodes_to_add : 0); 2308 if (new_nstart < this->members_.m_start.m_node) 2309 boost::container::move(this->members_.m_start.m_node, this->members_.m_finish.m_node + 1, new_nstart); 2310 else 2311 boost::container::move_backward 2312 (this->members_.m_start.m_node, this->members_.m_finish.m_node + 1, new_nstart + old_num_nodes); 2313 } 2314 else { 2315 size_type new_map_size = 2316 this->members_.m_map_size + dtl::max_value(this->members_.m_map_size, nodes_to_add) + 2; 2317 2318 index_pointer new_map = this->priv_allocate_map(new_map_size); 2319 new_nstart = new_map + (new_map_size - new_num_nodes) / 2 2320 + (add_at_front ? nodes_to_add : 0); 2321 boost::container::move(this->members_.m_start.m_node, this->members_.m_finish.m_node + 1, new_nstart); 2322 this->priv_deallocate_map(this->members_.m_map, this->members_.m_map_size); 2323 2324 this->members_.m_map = new_map; 2325 this->members_.m_map_size = new_map_size; 2326 } 2327 2328 this->members_.m_start.priv_set_node(new_nstart, get_block_size()); 2329 this->members_.m_finish.priv_set_node(new_nstart + old_num_nodes - 1, get_block_size()); 2330 } 2331 #endif //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED 2332 }; 2333 2334 #ifndef BOOST_CONTAINER_NO_CXX17_CTAD 2335 template <typename InputIterator> 2336 deque(InputIterator, InputIterator) -> deque<typename iterator_traits<InputIterator>::value_type>; 2337 template <typename InputIterator, typename Allocator> 2338 deque(InputIterator, InputIterator, Allocator const&) -> deque<typename iterator_traits<InputIterator>::value_type, Allocator>; 2339 #endif 2340 2341 }} 2342 2343 #ifndef BOOST_CONTAINER_DOXYGEN_INVOKED 2344 2345 namespace boost { 2346 2347 //!has_trivial_destructor_after_move<> == true_type 2348 //!specialization for optimizations 2349 template <class T, class Allocator, class Options> 2350 struct has_trivial_destructor_after_move<boost::container::deque<T, Allocator, Options> > 2351 { 2352 typedef typename boost::container::deque<T, Allocator, Options>::allocator_type allocator_type; 2353 typedef typename ::boost::container::allocator_traits<allocator_type>::pointer pointer; 2354 static const bool value = ::boost::has_trivial_destructor_after_move<allocator_type>::value && 2355 ::boost::has_trivial_destructor_after_move<pointer>::value; 2356 }; 2357 2358 } 2359 2360 #endif //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED 2361 2362 #include <boost/container/detail/config_end.hpp> 2363 2364 #endif // #ifndef BOOST_CONTAINER_DEQUE_HPP 2365