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