Documentation fix. Ticket 6499
[boost:cmake.git] / boost / container / deque.hpp
1 //////////////////////////////////////////////////////////////////////////////
2 //
3 // (C) Copyright Ion Gaztanaga 2005-2011. 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 // Copyright (c) 1996,1997
11 // Silicon Graphics Computer Systems, Inc.
12 //
13 // Permission to use, copy, modify, distribute and sell this software
14 // and its documentation for any purpose is hereby granted without fee,
15 // provided that the above copyright notice appear in all copies and
16 // that both that copyright notice and this permission notice appear
17 // in supporting documentation.  Silicon Graphics makes no
18 // representations about the suitability of this software for any
19 // purpose.  It is provided "as is" without express or implied warranty.
20 //
21 //
22 // Copyright (c) 1994
23 // Hewlett-Packard Company
24 //
25 // Permission to use, copy, modify, distribute and sell this software
26 // and its documentation for any purpose is hereby granted without fee,
27 // provided that the above copyright notice appear in all copies and
28 // that both that copyright notice and this permission notice appear
29 // in supporting documentation.  Hewlett-Packard Company makes no
30 // representations about the suitability of this software for any
31 // purpose.  It is provided "as is" without express or implied warranty.
32
33 #ifndef BOOST_CONTAINER_DEQUE_HPP
34 #define BOOST_CONTAINER_DEQUE_HPP
35
36 #if (defined _MSC_VER) && (_MSC_VER >= 1200)
37 #  pragma once
38 #endif
39
40 #include <boost/container/detail/config_begin.hpp>
41 #include <boost/container/detail/workaround.hpp>
42
43 #include <boost/container/detail/utilities.hpp>
44 #include <boost/container/detail/iterators.hpp>
45 #include <boost/container/detail/algorithms.hpp>
46 #include <boost/container/detail/mpl.hpp>
47 #include <boost/container/allocator/allocator_traits.hpp>
48 #include <boost/container/container_fwd.hpp>
49 #include <cstddef>
50 #include <iterator>
51 #include <boost/assert.hpp>
52 #include <memory>
53 #include <algorithm>
54 #include <stdexcept>
55 #include <boost/detail/no_exceptions_support.hpp>
56 #include <boost/type_traits/has_trivial_destructor.hpp>
57 #include <boost/type_traits/has_trivial_copy.hpp>
58 #include <boost/type_traits/has_trivial_assign.hpp>
59 #include <boost/type_traits/has_nothrow_copy.hpp>
60 #include <boost/type_traits/has_nothrow_assign.hpp>
61 #include <boost/move/move.hpp>
62 #include <boost/move/move_helpers.hpp>
63 #include <boost/container/detail/advanced_insert_int.hpp>
64
65 namespace boost {
66 namespace container {
67
68 /// @cond
69 #ifdef BOOST_CONTAINER_DOXYGEN_INVOKED
70 template <class T, class A = std::allocator<T> >
71 #else
72 template <class T, class A>
73 #endif
74 class deque;
75
76 template <class T, class A>
77 struct deque_value_traits
78 {
79    typedef T value_type;
80    typedef A allocator_type;
81    static const bool trivial_dctr = boost::has_trivial_destructor<value_type>::value;
82    static const bool trivial_dctr_after_move = false;
83       //::boost::has_trivial_destructor_after_move<value_type>::value || trivial_dctr;
84    static const bool trivial_copy = has_trivial_copy<value_type>::value;
85    static const bool nothrow_copy = has_nothrow_copy<value_type>::value;
86    static const bool trivial_assign = has_trivial_assign<value_type>::value;
87    //static const bool nothrow_assign = has_nothrow_assign<value_type>::value;
88    static const bool nothrow_assign = false;
89 };
90
91 // Note: this function is simply a kludge to work around several compilers'
92 //  bugs in handling constant expressions.
93 inline std::size_t deque_buf_size(std::size_t size) 
94    {  return size < 512 ? std::size_t(512 / size) : std::size_t(1);  }
95
96 // Deque base class.  It has two purposes.  First, its constructor
97 //  and destructor allocate (but don't initialize) storage.  This makes
98 //  exception safety easier.
99 template <class T, class A>
100 class deque_base
101 {
102    BOOST_COPYABLE_AND_MOVABLE(deque_base)
103    public:
104    typedef allocator_traits<A>                                     val_alloc_traits_type;
105    typedef typename val_alloc_traits_type::value_type              val_alloc_val;
106    typedef typename val_alloc_traits_type::pointer                 val_alloc_ptr;
107    typedef typename val_alloc_traits_type::const_pointer           val_alloc_cptr;
108    typedef typename val_alloc_traits_type::reference               val_alloc_ref;
109    typedef typename val_alloc_traits_type::const_reference         val_alloc_cref;
110    typedef typename val_alloc_traits_type::difference_type         val_alloc_diff;
111    typedef typename val_alloc_traits_type::size_type               val_alloc_size;
112    typedef typename val_alloc_traits_type::template
113       portable_rebind_alloc<val_alloc_ptr>::type                   ptr_alloc_t;
114    typedef allocator_traits<ptr_alloc_t>                           ptr_alloc_traits_type;
115    typedef typename ptr_alloc_traits_type::value_type             ptr_alloc_val;
116    typedef typename ptr_alloc_traits_type::pointer                ptr_alloc_ptr;
117    typedef typename ptr_alloc_traits_type::const_pointer          ptr_alloc_cptr;
118    typedef typename ptr_alloc_traits_type::reference              ptr_alloc_ref;
119    typedef typename ptr_alloc_traits_type::const_reference        ptr_alloc_cref;
120    typedef A                                                      allocator_type;
121    typedef allocator_type                                         stored_allocator_type;
122    typedef val_alloc_size                                         size_type;
123
124    protected:
125
126    typedef deque_value_traits<T, A>             traits_t;
127    typedef ptr_alloc_t                          map_allocator_type;
128
129    static size_type s_buffer_size() { return deque_buf_size(sizeof(T)); }
130
131    val_alloc_ptr priv_allocate_node() 
132       {  return this->alloc().allocate(s_buffer_size());  }
133
134    void priv_deallocate_node(val_alloc_ptr p) 
135       {  this->alloc().deallocate(p, s_buffer_size());  }
136
137    ptr_alloc_ptr priv_allocate_map(size_type n) 
138       { return this->ptr_alloc().allocate(n); }
139
140    void priv_deallocate_map(ptr_alloc_ptr p, size_type n) 
141       { this->ptr_alloc().deallocate(p, n); }
142
143  public:
144    // Class invariants:
145    //  For any nonsingular iterator i:
146    //    i.node is the address of an element in the map array.  The
147    //      contents of i.node is a pointer to the beginning of a node.
148    //    i.first == //(i.node) 
149    //    i.last  == i.first + node_size
150    //    i.cur is a pointer in the range [i.first, i.last).  NOTE:
151    //      the implication of this is that i.cur is always a dereferenceable
152    //      pointer, even if i is a past-the-end iterator.
153    //  Start and Finish are always nonsingular iterators.  NOTE: this means
154    //    that an empty deque must have one node, and that a deque
155    //    with N elements, where N is the buffer size, must have two nodes.
156    //  For every node other than start.node and finish.node, every element
157    //    in the node is an initialized object.  If start.node == finish.node,
158    //    then [start.cur, finish.cur) are initialized objects, and
159    //    the elements outside that range are uninitialized storage.  Otherwise,
160    //    [start.cur, start.last) and [finish.first, finish.cur) are initialized
161    //    objects, and [start.first, start.cur) and [finish.cur, finish.last)
162    //    are uninitialized storage.
163    //  [map, map + map_size) is a valid, non-empty range.  
164    //  [start.node, finish.node] is a valid range contained within 
165    //    [map, map + map_size).  
166    //  A pointer in the range [map, map + map_size) points to an allocated node
167    //    if and only if the pointer is in the range [start.node, finish.node].
168    class const_iterator 
169       : public std::iterator<std::random_access_iterator_tag, 
170                               val_alloc_val,  val_alloc_diff, 
171                               val_alloc_cptr, val_alloc_cref>
172    {
173       public:
174       static size_type s_buffer_size() { return deque_base<T, A>::s_buffer_size(); }
175
176       typedef std::random_access_iterator_tag   iterator_category;
177       typedef val_alloc_val                     value_type;
178       typedef val_alloc_cptr                    pointer;
179       typedef val_alloc_cref                    reference;
180       typedef val_alloc_diff                    difference_type;
181
182       typedef ptr_alloc_ptr                     index_pointer;
183       typedef const_iterator                    self_t;
184
185       friend class deque<T, A>;
186       friend class deque_base<T, A>;
187
188       protected: 
189       val_alloc_ptr  m_cur;
190       val_alloc_ptr  m_first;
191       val_alloc_ptr  m_last;
192       index_pointer  m_node;
193
194       public: 
195       const_iterator(val_alloc_ptr x, index_pointer y) 
196          : m_cur(x), m_first(*y),
197            m_last(*y + s_buffer_size()), m_node(y) {}
198
199       const_iterator() : m_cur(0), m_first(0), m_last(0), m_node(0) {}
200
201       const_iterator(const const_iterator& x)
202          : m_cur(x.m_cur),   m_first(x.m_first), 
203            m_last(x.m_last), m_node(x.m_node) {}
204
205       reference operator*() const 
206          { return *this->m_cur; }
207
208       pointer operator->() const 
209          { return this->m_cur; }
210
211       difference_type operator-(const self_t& x) const 
212       {
213          if(!this->m_cur && !x.m_cur){
214             return 0;
215          }
216          return difference_type(this->s_buffer_size()) * (this->m_node - x.m_node - 1) +
217             (this->m_cur - this->m_first) + (x.m_last - x.m_cur);
218       }
219
220       self_t& operator++() 
221       {
222          ++this->m_cur;
223          if (this->m_cur == this->m_last) {
224             this->priv_set_node(this->m_node + 1);
225             this->m_cur = this->m_first;
226          }
227          return *this; 
228       }
229
230       self_t operator++(int)  
231       {
232          self_t tmp = *this;
233          ++*this;
234          return tmp;
235       }
236
237       self_t& operator--() 
238       {
239          if (this->m_cur == this->m_first) {
240             this->priv_set_node(this->m_node - 1);
241             this->m_cur = this->m_last;
242          }
243          --this->m_cur;
244          return *this;
245       }
246
247       self_t operator--(int) 
248       {
249          self_t tmp = *this;
250          --*this;
251          return tmp;
252       }
253
254       self_t& operator+=(difference_type n)
255       {
256          difference_type offset = n + (this->m_cur - this->m_first);
257          if (offset >= 0 && offset < difference_type(this->s_buffer_size()))
258             this->m_cur += n;
259          else {
260             difference_type node_offset =
261             offset > 0 ? offset / difference_type(this->s_buffer_size())
262                         : -difference_type((-offset - 1) / this->s_buffer_size()) - 1;
263             this->priv_set_node(this->m_node + node_offset);
264             this->m_cur = this->m_first + 
265             (offset - node_offset * difference_type(this->s_buffer_size()));
266          }
267          return *this;
268       }
269
270       self_t operator+(difference_type n) const
271          {  self_t tmp = *this; return tmp += n;  }
272
273       self_t& operator-=(difference_type n) 
274          { return *this += -n; }
275        
276       self_t operator-(difference_type n) const 
277          {  self_t tmp = *this; return tmp -= n;  }
278
279       reference operator[](difference_type n) const 
280          { return *(*this + n); }
281
282       bool operator==(const self_t& x) const 
283          { return this->m_cur == x.m_cur; }
284
285       bool operator!=(const self_t& x) const 
286          { return !(*this == x); }
287
288       bool operator<(const self_t& x) const 
289       {
290          return (this->m_node == x.m_node) ? 
291             (this->m_cur < x.m_cur) : (this->m_node < x.m_node);
292       }
293
294       bool operator>(const self_t& x) const  
295          { return x < *this; }
296
297       bool operator<=(const self_t& x) const 
298          { return !(x < *this); }
299
300       bool operator>=(const self_t& x) const 
301          { return !(*this < x); }
302
303       void priv_set_node(index_pointer new_node) 
304       {
305          this->m_node = new_node;
306          this->m_first = *new_node;
307          this->m_last = this->m_first + difference_type(this->s_buffer_size());
308       }
309
310       friend const_iterator operator+(difference_type n, const const_iterator& x)
311          {  return x + n;  }
312    };
313
314    //Deque iterator
315    class iterator : public const_iterator
316    {
317       public:
318       typedef std::random_access_iterator_tag   iterator_category;
319       typedef val_alloc_val                     value_type;
320       typedef val_alloc_ptr                     pointer;
321       typedef val_alloc_ref                     reference;
322       typedef val_alloc_diff                    difference_type;
323       typedef ptr_alloc_ptr                     index_pointer;
324       typedef const_iterator                    self_t;
325
326       friend class deque<T, A>;
327       friend class deque_base<T, A>;
328
329       private:
330       explicit iterator(const const_iterator& x) : const_iterator(x){}
331
332       public:
333       //Constructors
334       iterator(val_alloc_ptr x, index_pointer y) : const_iterator(x, y){}
335       iterator() : const_iterator(){}
336       //iterator(const const_iterator &cit) : const_iterator(cit){}
337       iterator(const iterator& x) : const_iterator(x){}
338
339       //Pointer like operators
340       reference operator*() const { return *this->m_cur; }
341       pointer operator->() const { return this->m_cur; }
342
343       reference operator[](difference_type n) const { return *(*this + n); }
344
345       //Increment / Decrement
346       iterator& operator++()  
347          { this->const_iterator::operator++(); return *this;  }
348
349       iterator operator++(int)
350          { iterator tmp = *this; ++*this; return tmp; }
351       
352       iterator& operator--()
353          {  this->const_iterator::operator--(); return *this;  }
354
355       iterator operator--(int)
356          {  iterator tmp = *this; --*this; return tmp; }
357
358       // Arithmetic
359       iterator& operator+=(difference_type off)
360          {  this->const_iterator::operator+=(off); return *this;  }
361
362       iterator operator+(difference_type off) const
363          {  return iterator(this->const_iterator::operator+(off));  }
364
365       friend iterator operator+(difference_type off, const iterator& right)
366          {  return iterator(off+static_cast<const const_iterator &>(right)); }
367
368       iterator& operator-=(difference_type off)
369          {  this->const_iterator::operator-=(off); return *this;   }
370
371       iterator operator-(difference_type off) const
372          {  return iterator(this->const_iterator::operator-(off));  }
373
374       difference_type operator-(const const_iterator& right) const
375          {  return static_cast<const const_iterator&>(*this) - right;   }
376    };
377
378    deque_base(size_type num_elements, const allocator_type& a)
379       :  members_(a)
380    { this->priv_initialize_map(num_elements); }
381
382    explicit deque_base(const allocator_type& a) 
383       :  members_(a)
384    {}
385
386    deque_base()
387       :  members_()
388    {}
389
390    explicit deque_base(BOOST_RV_REF(deque_base) x)
391       :  members_( boost::move(x.ptr_alloc())
392                  , boost::move(x.alloc()) )
393    {}
394
395    ~deque_base()
396    {
397       if (this->members_.m_map) {
398          this->priv_destroy_nodes(this->members_.m_start.m_node, this->members_.m_finish.m_node + 1);
399          this->priv_deallocate_map(this->members_.m_map, this->members_.m_map_size);
400       }
401    }
402
403    private:
404    deque_base(const deque_base&);
405   
406    protected:
407
408    void swap_members(deque_base &x)
409    {
410       std::swap(this->members_.m_start, x.members_.m_start);
411       std::swap(this->members_.m_finish, x.members_.m_finish);
412       std::swap(this->members_.m_map, x.members_.m_map);
413       std::swap(this->members_.m_map_size, x.members_.m_map_size);
414    }
415
416    void priv_initialize_map(size_type num_elements)
417    {
418 //      if(num_elements){
419          size_type num_nodes = num_elements / s_buffer_size() + 1;
420
421          this->members_.m_map_size = container_detail::max_value((size_type) InitialMapSize, num_nodes + 2);
422          this->members_.m_map = this->priv_allocate_map(this->members_.m_map_size);
423
424          ptr_alloc_ptr nstart = this->members_.m_map + (this->members_.m_map_size - num_nodes) / 2;
425          ptr_alloc_ptr nfinish = nstart + num_nodes;
426              
427          BOOST_TRY {
428             this->priv_create_nodes(nstart, nfinish);
429          }
430          BOOST_CATCH(...){
431             this->priv_deallocate_map(this->members_.m_map, this->members_.m_map_size);
432             this->members_.m_map = 0;
433             this->members_.m_map_size = 0;
434             BOOST_RETHROW
435          }
436          BOOST_CATCH_END
437
438          this->members_.m_start.priv_set_node(nstart);
439          this->members_.m_finish.priv_set_node(nfinish - 1);
440          this->members_.m_start.m_cur = this->members_.m_start.m_first;
441          this->members_.m_finish.m_cur = this->members_.m_finish.m_first +
442                         num_elements % s_buffer_size();
443 //      }
444    }
445
446    void priv_create_nodes(ptr_alloc_ptr nstart, ptr_alloc_ptr nfinish)
447    {
448       ptr_alloc_ptr cur;
449       BOOST_TRY {
450          for (cur = nstart; cur < nfinish; ++cur)
451             *cur = this->priv_allocate_node();
452       }
453       BOOST_CATCH(...){
454          this->priv_destroy_nodes(nstart, cur);
455          BOOST_RETHROW
456       }
457       BOOST_CATCH_END
458    }
459
460    void priv_destroy_nodes(ptr_alloc_ptr nstart, ptr_alloc_ptr nfinish)
461    {
462       for (ptr_alloc_ptr n = nstart; n < nfinish; ++n)
463          this->priv_deallocate_node(*n);
464    }
465
466    void priv_clear_map()
467    {
468       if (this->members_.m_map) {
469          this->priv_destroy_nodes(this->members_.m_start.m_node, this->members_.m_finish.m_node + 1);
470          this->priv_deallocate_map(this->members_.m_map, this->members_.m_map_size);
471          this->members_.m_map = 0;
472          this->members_.m_map_size = 0;
473          this->members_.m_start = iterator();
474          this->members_.m_finish = this->members_.m_start;
475       }
476    }
477
478    enum { InitialMapSize = 8 };
479
480    protected:
481    struct members_holder
482       :  public ptr_alloc_t
483       ,  public allocator_type
484    {
485       members_holder()
486          :  map_allocator_type(), allocator_type()
487          ,  m_map(0), m_map_size(0)
488          ,  m_start(), m_finish(m_start)
489       {}
490
491       explicit members_holder(const allocator_type &a)
492          :  map_allocator_type(a), allocator_type(a)
493          ,  m_map(0), m_map_size(0)
494          ,  m_start(), m_finish(m_start)
495       {}
496
497       template<class ValAllocConvertible, class PtrAllocConvertible>
498       members_holder(BOOST_FWD_REF(PtrAllocConvertible) pa, BOOST_FWD_REF(ValAllocConvertible) va)
499          : map_allocator_type(boost::forward<PtrAllocConvertible>(pa))
500          , allocator_type    (boost::forward<ValAllocConvertible>(va))
501          , m_map(0), m_map_size(0)
502          , m_start(), m_finish(m_start)
503       {}
504
505       ptr_alloc_ptr   m_map;
506       val_alloc_size  m_map_size;
507       iterator        m_start;
508       iterator        m_finish;
509    } members_;
510
511    ptr_alloc_t &ptr_alloc() 
512    {  return members_;  }
513    
514    const ptr_alloc_t &ptr_alloc() const 
515    {  return members_;  }
516
517    allocator_type &alloc() 
518    {  return members_;  }
519    
520    const allocator_type &alloc() const 
521    {  return members_;  }
522 };
523 /// @endcond
524
525 //! Deque class
526 //!
527 #ifdef BOOST_CONTAINER_DOXYGEN_INVOKED
528 template <class T, class A = std::allocator<T> >
529 #else
530 template <class T, class A>
531 #endif
532 class deque : protected deque_base<T, A>
533 {
534    /// @cond
535    private:
536    typedef deque_base<T, A> Base;
537    typedef typename Base::val_alloc_val            val_alloc_val;
538    typedef typename Base::val_alloc_ptr            val_alloc_ptr;
539    typedef typename Base::val_alloc_cptr           val_alloc_cptr;
540    typedef typename Base::val_alloc_ref            val_alloc_ref;
541    typedef typename Base::val_alloc_cref           val_alloc_cref;
542    typedef typename Base::val_alloc_size           val_alloc_size;
543    typedef typename Base::val_alloc_diff           val_alloc_diff;
544
545    typedef typename Base::ptr_alloc_t              ptr_alloc_t;
546    typedef typename Base::ptr_alloc_val            ptr_alloc_val;
547    typedef typename Base::ptr_alloc_ptr            ptr_alloc_ptr;
548    typedef typename Base::ptr_alloc_cptr           ptr_alloc_cptr;
549    typedef typename Base::ptr_alloc_ref            ptr_alloc_ref;
550    typedef typename Base::ptr_alloc_cref           ptr_alloc_cref;
551    /// @endcond
552
553    public:                         // Basic types
554    typedef T                                    value_type;
555    typedef val_alloc_ptr                        pointer;
556    typedef val_alloc_cptr                       const_pointer;
557    typedef val_alloc_ref                        reference;
558    typedef val_alloc_cref                       const_reference;
559    typedef val_alloc_size                       size_type;
560    typedef val_alloc_diff                       difference_type;
561    typedef typename Base::allocator_type        allocator_type;
562
563    public:                                // Iterators
564    typedef typename Base::iterator              iterator;
565    typedef typename Base::const_iterator        const_iterator;
566
567    typedef std::reverse_iterator<const_iterator> const_reverse_iterator;
568    typedef std::reverse_iterator<iterator>      reverse_iterator;
569
570    typedef allocator_type                       stored_allocator_type;
571
572    /// @cond
573
574    private:                      // Internal typedefs
575    BOOST_COPYABLE_AND_MOVABLE(deque)
576    typedef ptr_alloc_ptr index_pointer;
577    static size_type s_buffer_size() 
578       { return Base::s_buffer_size(); }
579    typedef container_detail::advanced_insert_aux_int<iterator> advanced_insert_aux_int_t;
580    typedef repeat_iterator<T, difference_type>  r_iterator;
581    typedef boost::move_iterator<r_iterator>     move_it;
582    typedef allocator_traits<A>                  allocator_traits_type;
583
584    /// @endcond
585
586    public:
587
588    //! <b>Effects</b>: Returns a copy of the internal allocator.
589    //! 
590    //! <b>Throws</b>: If allocator's copy constructor throws.
591    //! 
592    //! <b>Complexity</b>: Constant.
593    allocator_type get_allocator() const BOOST_CONTAINER_NOEXCEPT
594    { return Base::alloc(); }
595
596    //! <b>Effects</b>: Returns a reference to the internal allocator.
597    //! 
598    //! <b>Throws</b>: Nothing
599    //! 
600    //! <b>Complexity</b>: Constant.
601    //! 
602    //! <b>Note</b>: Non-standard extension.
603    const stored_allocator_type &get_stored_allocator() const BOOST_CONTAINER_NOEXCEPT
604    {  return Base::alloc(); }
605
606    //! <b>Effects</b>: Returns a reference to the internal allocator.
607    //! 
608    //! <b>Throws</b>: Nothing
609    //! 
610    //! <b>Complexity</b>: Constant.
611    //! 
612    //! <b>Note</b>: Non-standard extension.
613    stored_allocator_type &get_stored_allocator() BOOST_CONTAINER_NOEXCEPT
614    {  return Base::alloc(); }
615
616    //! <b>Effects</b>: Returns an iterator to the first element contained in the deque.
617    //! 
618    //! <b>Throws</b>: Nothing.
619    //! 
620    //! <b>Complexity</b>: Constant.
621    iterator begin() BOOST_CONTAINER_NOEXCEPT
622       { return this->members_.m_start; }
623
624    //! <b>Effects</b>: Returns an iterator to the end of the deque.
625    //! 
626    //! <b>Throws</b>: Nothing.
627    //! 
628    //! <b>Complexity</b>: Constant.
629    iterator end() BOOST_CONTAINER_NOEXCEPT
630       { return this->members_.m_finish; }
631
632    //! <b>Effects</b>: Returns a const_iterator to the first element contained in the deque.
633    //! 
634    //! <b>Throws</b>: Nothing.
635    //! 
636    //! <b>Complexity</b>: Constant.
637    const_iterator begin() const BOOST_CONTAINER_NOEXCEPT
638       { return this->members_.m_start; }
639
640    //! <b>Effects</b>: Returns a const_iterator to the end of the deque.
641    //! 
642    //! <b>Throws</b>: Nothing.
643    //! 
644    //! <b>Complexity</b>: Constant.
645    const_iterator end() const BOOST_CONTAINER_NOEXCEPT
646       { return this->members_.m_finish; }
647
648    //! <b>Effects</b>: Returns a reverse_iterator pointing to the beginning 
649    //! of the reversed deque. 
650    //! 
651    //! <b>Throws</b>: Nothing.
652    //! 
653    //! <b>Complexity</b>: Constant.
654    reverse_iterator rbegin() BOOST_CONTAINER_NOEXCEPT
655       { return reverse_iterator(this->members_.m_finish); }
656
657    //! <b>Effects</b>: Returns a reverse_iterator pointing to the end
658    //! of the reversed deque. 
659    //! 
660    //! <b>Throws</b>: Nothing.
661    //! 
662    //! <b>Complexity</b>: Constant.
663    reverse_iterator rend() BOOST_CONTAINER_NOEXCEPT
664       { return reverse_iterator(this->members_.m_start); }
665
666    //! <b>Effects</b>: Returns a const_reverse_iterator pointing to the beginning 
667    //! of the reversed deque. 
668    //! 
669    //! <b>Throws</b>: Nothing.
670    //! 
671    //! <b>Complexity</b>: Constant.
672    const_reverse_iterator rbegin() const BOOST_CONTAINER_NOEXCEPT
673       { return const_reverse_iterator(this->members_.m_finish); }
674
675    //! <b>Effects</b>: Returns a const_reverse_iterator pointing to the end
676    //! of the reversed deque. 
677    //! 
678    //! <b>Throws</b>: Nothing.
679    //! 
680    //! <b>Complexity</b>: Constant.
681    const_reverse_iterator rend() const BOOST_CONTAINER_NOEXCEPT
682       { return const_reverse_iterator(this->members_.m_start); }
683
684    //! <b>Effects</b>: Returns a const_iterator to the first element contained in the deque.
685    //! 
686    //! <b>Throws</b>: Nothing.
687    //! 
688    //! <b>Complexity</b>: Constant.
689    const_iterator cbegin() const BOOST_CONTAINER_NOEXCEPT
690       { return this->members_.m_start; }
691
692    //! <b>Effects</b>: Returns a const_iterator to the end of the deque.
693    //! 
694    //! <b>Throws</b>: Nothing.
695    //! 
696    //! <b>Complexity</b>: Constant.
697    const_iterator cend() const BOOST_CONTAINER_NOEXCEPT
698       { return this->members_.m_finish; }
699
700    //! <b>Effects</b>: Returns a const_reverse_iterator pointing to the beginning 
701    //! of the reversed deque. 
702    //! 
703    //! <b>Throws</b>: Nothing.
704    //! 
705    //! <b>Complexity</b>: Constant.
706    const_reverse_iterator crbegin() const BOOST_CONTAINER_NOEXCEPT
707       { return const_reverse_iterator(this->members_.m_finish); }
708
709    //! <b>Effects</b>: Returns a const_reverse_iterator pointing to the end
710    //! of the reversed deque. 
711    //! 
712    //! <b>Throws</b>: Nothing.
713    //! 
714    //! <b>Complexity</b>: Constant.
715    const_reverse_iterator crend() const BOOST_CONTAINER_NOEXCEPT
716       { return const_reverse_iterator(this->members_.m_start); }
717
718    //! <b>Requires</b>: size() > n.
719    //!
720    //! <b>Effects</b>: Returns a reference to the nth element 
721    //!   from the beginning of the container.
722    //! 
723    //! <b>Throws</b>: Nothing.
724    //! 
725    //! <b>Complexity</b>: Constant.
726    reference operator[](size_type n) BOOST_CONTAINER_NOEXCEPT
727       { return this->members_.m_start[difference_type(n)]; }
728
729    //! <b>Requires</b>: size() > n.
730    //!
731    //! <b>Effects</b>: Returns a const reference to the nth element 
732    //!   from the beginning of the container.
733    //! 
734    //! <b>Throws</b>: Nothing.
735    //! 
736    //! <b>Complexity</b>: Constant.
737    const_reference operator[](size_type n) const BOOST_CONTAINER_NOEXCEPT
738       { return this->members_.m_start[difference_type(n)]; }
739
740    //! <b>Requires</b>: size() > n.
741    //!
742    //! <b>Effects</b>: Returns a reference to the nth element 
743    //!   from the beginning of the container.
744    //! 
745    //! <b>Throws</b>: std::range_error if n >= size()
746    //! 
747    //! <b>Complexity</b>: Constant.
748    reference at(size_type n)
749       { this->priv_range_check(n); return (*this)[n]; }
750
751    //! <b>Requires</b>: size() > n.
752    //!
753    //! <b>Effects</b>: Returns a const reference to the nth element 
754    //!   from the beginning of the container.
755    //! 
756    //! <b>Throws</b>: std::range_error if n >= size()
757    //! 
758    //! <b>Complexity</b>: Constant.
759    const_reference at(size_type n) const
760       { this->priv_range_check(n); return (*this)[n]; }
761
762    //! <b>Requires</b>: !empty()
763    //!
764    //! <b>Effects</b>: Returns a reference to the first
765    //!   element of the container.
766    //! 
767    //! <b>Throws</b>: Nothing.
768    //! 
769    //! <b>Complexity</b>: Constant.
770    reference front() BOOST_CONTAINER_NOEXCEPT
771       { return *this->members_.m_start; }
772
773    //! <b>Requires</b>: !empty()
774    //!
775    //! <b>Effects</b>: Returns a const reference to the first element 
776    //!   from the beginning of the container.
777    //! 
778    //! <b>Throws</b>: Nothing.
779    //! 
780    //! <b>Complexity</b>: Constant.
781    const_reference front() const BOOST_CONTAINER_NOEXCEPT
782       { return *this->members_.m_start; }
783
784    //! <b>Requires</b>: !empty()
785    //!
786    //! <b>Effects</b>: Returns a reference to the last
787    //!   element of the container.
788    //! 
789    //! <b>Throws</b>: Nothing.
790    //! 
791    //! <b>Complexity</b>: Constant.
792    reference back() BOOST_CONTAINER_NOEXCEPT
793       {  return *(end()-1); }
794
795    //! <b>Requires</b>: !empty()
796    //!
797    //! <b>Effects</b>: Returns a const reference to the last
798    //!   element of the container.
799    //! 
800    //! <b>Throws</b>: Nothing.
801    //! 
802    //! <b>Complexity</b>: Constant.
803    const_reference back() const BOOST_CONTAINER_NOEXCEPT
804       {  return *(cend()-1);  }
805
806    //! <b>Effects</b>: Returns the number of the elements contained in the deque.
807    //! 
808    //! <b>Throws</b>: Nothing.
809    //! 
810    //! <b>Complexity</b>: Constant.
811    size_type size() const BOOST_CONTAINER_NOEXCEPT
812       { return this->members_.m_finish - this->members_.m_start; }
813
814    //! <b>Effects</b>: Returns the largest possible size of the deque.
815    //! 
816    //! <b>Throws</b>: Nothing.
817    //! 
818    //! <b>Complexity</b>: Constant.
819    size_type max_size() const BOOST_CONTAINER_NOEXCEPT
820       { return allocator_traits_type::max_size(this->alloc()); }
821
822    //! <b>Effects</b>: Returns true if the deque contains no elements.
823    //! 
824    //! <b>Throws</b>: Nothing.
825    //! 
826    //! <b>Complexity</b>: Constant.
827    bool empty() const BOOST_CONTAINER_NOEXCEPT
828    { return this->members_.m_finish == this->members_.m_start; }
829
830    //! <b>Effects</b>: Default constructors a deque.
831    //! 
832    //! <b>Throws</b>: If allocator_type's default constructor throws.
833    //! 
834    //! <b>Complexity</b>: Constant.
835    deque() 
836       : Base()
837    {}
838
839    //! <b>Effects</b>: Constructs a deque taking the allocator as parameter.
840    //! 
841    //! <b>Throws</b>: If allocator_type's copy constructor throws.
842    //! 
843    //! <b>Complexity</b>: Constant.
844    explicit deque(const allocator_type& a) 
845       : Base(a)
846    {}
847
848    //! <b>Effects</b>: Constructs a deque that will use a copy of allocator a
849    //!   and inserts n default contructed values.
850    //!
851    //! <b>Throws</b>: If allocator_type's default constructor or copy constructor
852    //!   throws or T's default or copy constructor throws.
853    //! 
854    //! <b>Complexity</b>: Linear to n.
855    explicit deque(size_type n)
856       : Base(n, allocator_type())
857    {
858       container_detail::default_construct_aux_proxy<A, iterator> proxy(this->alloc(), n);
859       proxy.uninitialized_copy_remaining_to(this->begin());
860       //deque_base will deallocate in case of exception...
861    }
862
863    //! <b>Effects</b>: Constructs a deque that will use a copy of allocator a
864    //!   and inserts n copies of value.
865    //!
866    //! <b>Throws</b>: If allocator_type's default constructor or copy constructor
867    //!   throws or T's default or copy constructor throws.
868    //! 
869    //! <b>Complexity</b>: Linear to n.
870    deque(size_type n, const value_type& value,
871          const allocator_type& a = allocator_type())
872       : Base(n, a)
873    { this->priv_fill_initialize(value); }
874
875    //! <b>Effects</b>: Copy constructs a deque.
876    //!
877    //! <b>Postcondition</b>: x == *this.
878    //! 
879    //! <b>Complexity</b>: Linear to the elements x contains.
880    deque(const deque& x)
881       :  Base(allocator_traits_type::select_on_container_copy_construction(x.alloc()))
882    {
883       if(x.size()){
884          this->priv_initialize_map(x.size());
885          boost::container::uninitialized_copy_alloc
886             (this->alloc(), x.begin(), x.end(), this->members_.m_start);
887       }
888    }
889
890    //! <b>Effects</b>: Move constructor. Moves mx's resources to *this.
891    //!
892    //! <b>Throws</b>: If allocator_type's copy constructor throws.
893    //! 
894    //! <b>Complexity</b>: Constant.
895    deque(BOOST_RV_REF(deque) x) 
896       :  Base(boost::move(static_cast<Base&>(x)))
897    {  this->swap_members(x);   }
898
899    //! <b>Effects</b>: Constructs a deque that will use a copy of allocator a
900    //!   and inserts a copy of the range [first, last) in the deque.
901    //!
902    //! <b>Throws</b>: If allocator_type's default constructor or copy constructor
903    //!   throws or T's constructor taking an dereferenced InIt throws.
904    //!
905    //! <b>Complexity</b>: Linear to the range [first, last).
906    template <class InpIt>
907    deque(InpIt first, InpIt last, const allocator_type& a = allocator_type())
908       : Base(a) 
909    {
910       //Dispatch depending on integer/iterator
911       const bool aux_boolean = container_detail::is_convertible<InpIt, size_type>::value;
912       typedef container_detail::bool_<aux_boolean> Result;
913       this->priv_initialize_dispatch(first, last, Result());
914    }
915
916    //! <b>Effects</b>: Destroys the deque. All stored values are destroyed
917    //!   and used memory is deallocated.
918    //!
919    //! <b>Throws</b>: Nothing.
920    //!
921    //! <b>Complexity</b>: Linear to the number of elements.
922    ~deque() BOOST_CONTAINER_NOEXCEPT
923    {
924       priv_destroy_range(this->members_.m_start, this->members_.m_finish);
925    }
926
927    //! <b>Effects</b>: Makes *this contain the same elements as x.
928    //!
929    //! <b>Postcondition</b>: this->size() == x.size(). *this contains a copy 
930    //! of each of x's elements. 
931    //!
932    //! <b>Throws</b>: If memory allocation throws or T's copy constructor throws.
933    //!
934    //! <b>Complexity</b>: Linear to the number of elements in x.
935    deque& operator= (BOOST_COPY_ASSIGN_REF(deque) x) 
936    {
937       if (&x != this){
938          allocator_type &this_alloc     = this->alloc();
939          const allocator_type &x_alloc  = x.alloc();
940          container_detail::bool_<allocator_traits_type::
941             propagate_on_container_copy_assignment::value> flag;
942          if(flag && this_alloc != x_alloc){
943             this->clear();
944             this->shrink_to_fit();
945          }
946          container_detail::assign_alloc(this->alloc(), x.alloc(), flag);
947          container_detail::assign_alloc(this->ptr_alloc(), x.ptr_alloc(), flag);
948          this->assign(x.cbegin(), x.cend());
949       }
950       return *this;
951    }
952
953    //! <b>Effects</b>: Move assignment. All mx's values are transferred to *this.
954    //!
955    //! <b>Postcondition</b>: x.empty(). *this contains a the elements x had
956    //!   before the function.
957    //!
958    //! <b>Throws</b>: If allocator_type's copy constructor throws.
959    //!
960    //! <b>Complexity</b>: Linear.
961    deque& operator= (BOOST_RV_REF(deque) x)
962    {
963       if (&x != this){
964          allocator_type &this_alloc = this->alloc();
965          allocator_type &x_alloc    = x.alloc();
966          //If allocators are equal we can just swap pointers
967          if(this_alloc == x_alloc){
968             //Destroy objects but retain memory in case x reuses it in the future
969             this->clear();
970             this->swap_members(x);
971             //Move allocator if needed
972             container_detail::bool_<allocator_traits_type::
973                propagate_on_container_move_assignment::value> flag;
974             container_detail::move_alloc(this_alloc, x_alloc, flag);
975             container_detail::move_alloc(this->ptr_alloc(), x.ptr_alloc(), flag);
976          }
977          //If unequal allocators, then do a one by one move
978          else{
979             typedef typename std::iterator_traits<iterator>::iterator_category ItCat;
980             this->assign( boost::make_move_iterator(x.begin())
981                         , boost::make_move_iterator(x.end()));
982          }
983       }
984       return *this;
985    }
986
987    //! <b>Effects</b>: Swaps the contents of *this and x.
988    //!
989    //! <b>Throws</b>: Nothing.
990    //!
991    //! <b>Complexity</b>: Constant.
992    void swap(deque &x)
993    {
994       this->swap_members(x);
995       container_detail::bool_<allocator_traits_type::propagate_on_container_swap::value> flag;
996       container_detail::swap_alloc(this->alloc(), x.alloc(), flag);
997       container_detail::swap_alloc(this->ptr_alloc(), x.ptr_alloc(), flag);
998    }
999
1000    //! <b>Effects</b>: Assigns the n copies of val to *this.
1001    //!
1002    //! <b>Throws</b>: If memory allocation throws or T's copy constructor throws.
1003    //!
1004    //! <b>Complexity</b>: Linear to n.
1005    void assign(size_type n, const T& val)
1006    {  this->priv_fill_assign(n, val);  }
1007
1008    //! <b>Effects</b>: Assigns the the range [first, last) to *this.
1009    //!
1010    //! <b>Throws</b>: If memory allocation throws or
1011    //!   T's constructor from dereferencing InpIt throws.
1012    //!
1013    //! <b>Complexity</b>: Linear to n.
1014    template <class InpIt>
1015    void assign(InpIt first, InpIt last)
1016    {
1017       //Dispatch depending on integer/iterator
1018       const bool aux_boolean = container_detail::is_convertible<InpIt, size_type>::value;
1019       typedef container_detail::bool_<aux_boolean> Result;
1020       this->priv_assign_dispatch(first, last, Result());
1021    }
1022
1023    #if defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
1024    //! <b>Effects</b>: Inserts a copy of x at the end of the deque.
1025    //!
1026    //! <b>Throws</b>: If memory allocation throws or
1027    //!   T's copy constructor throws.
1028    //!
1029    //! <b>Complexity</b>: Amortized constant time.
1030    void push_back(const T &x);
1031
1032    //! <b>Effects</b>: Constructs a new element in the end of the deque
1033    //!   and moves the resources of mx to this new element.
1034    //!
1035    //! <b>Throws</b>: If memory allocation throws.
1036    //!
1037    //! <b>Complexity</b>: Amortized constant time.
1038    void push_back(T &&x);
1039    #else
1040    BOOST_MOVE_CONVERSION_AWARE_CATCH(push_back, T, void, priv_push_back)
1041    #endif
1042
1043    #if defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
1044    //! <b>Effects</b>: Inserts a copy of x at the front of the deque.
1045    //!
1046    //! <b>Throws</b>: If memory allocation throws or
1047    //!   T's copy constructor throws.
1048    //!
1049    //! <b>Complexity</b>: Amortized constant time.
1050    void push_front(const T &x);
1051
1052    //! <b>Effects</b>: Constructs a new element in the front of the deque
1053    //!   and moves the resources of mx to this new element.
1054    //!
1055    //! <b>Throws</b>: If memory allocation throws.
1056    //!
1057    //! <b>Complexity</b>: Amortized constant time.
1058    void push_front(T &&x);
1059    #else
1060    BOOST_MOVE_CONVERSION_AWARE_CATCH(push_front, T, void, priv_push_front)
1061    #endif
1062
1063    //! <b>Effects</b>: Removes the last element from the deque.
1064    //!
1065    //! <b>Throws</b>: Nothing.
1066    //!
1067    //! <b>Complexity</b>: Constant time.
1068    void pop_back() BOOST_CONTAINER_NOEXCEPT
1069    {
1070       if (this->members_.m_finish.m_cur != this->members_.m_finish.m_first) {
1071          --this->members_.m_finish.m_cur;
1072          allocator_traits_type::destroy
1073             ( this->alloc()
1074             , container_detail::to_raw_pointer(this->members_.m_finish.m_cur)
1075             );
1076       }
1077       else
1078          this->priv_pop_back_aux();
1079    }
1080
1081    //! <b>Effects</b>: Removes the first element from the deque.
1082    //!
1083    //! <b>Throws</b>: Nothing.
1084    //!
1085    //! <b>Complexity</b>: Constant time.
1086    void pop_front() BOOST_CONTAINER_NOEXCEPT
1087    {
1088       if (this->members_.m_start.m_cur != this->members_.m_start.m_last - 1) {
1089          allocator_traits_type::destroy
1090             ( this->alloc()
1091             , container_detail::to_raw_pointer(this->members_.m_start.m_cur)
1092             );
1093          ++this->members_.m_start.m_cur;
1094       }
1095       else 
1096          this->priv_pop_front_aux();
1097    }
1098
1099    #if defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
1100
1101    //! <b>Requires</b>: position must be a valid iterator of *this.
1102    //!
1103    //! <b>Effects</b>: Insert a copy of x before position.
1104    //!
1105    //! <b>Throws</b>: If memory allocation throws or x's copy constructor throws.
1106    //!
1107    //! <b>Complexity</b>: If position is end(), amortized constant time
1108    //!   Linear time otherwise.
1109    iterator insert(const_iterator position, const T &x);
1110
1111    //! <b>Requires</b>: position must be a valid iterator of *this.
1112    //!
1113    //! <b>Effects</b>: Insert a new element before position with mx's resources.
1114    //!
1115    //! <b>Throws</b>: If memory allocation throws.
1116    //!
1117    //! <b>Complexity</b>: If position is end(), amortized constant time
1118    //!   Linear time otherwise.
1119    iterator insert(const_iterator position, T &&x);
1120    #else
1121    BOOST_MOVE_CONVERSION_AWARE_CATCH_1ARG(insert, T, iterator, priv_insert, const_iterator)
1122    #endif
1123
1124    //! <b>Requires</b>: pos must be a valid iterator of *this.
1125    //!
1126    //! <b>Effects</b>: Insert n copies of x before pos.
1127    //!
1128    //! <b>Throws</b>: If memory allocation throws or T's copy constructor throws.
1129    //!
1130    //! <b>Complexity</b>: Linear to n.
1131    void insert(const_iterator pos, size_type n, const value_type& x)
1132    { this->priv_fill_insert(pos, n, x); }
1133
1134    //! <b>Requires</b>: pos must be a valid iterator of *this.
1135    //!
1136    //! <b>Effects</b>: Insert a copy of the [first, last) range before pos.
1137    //!
1138    //! <b>Throws</b>: If memory allocation throws, T's constructor from a
1139    //!   dereferenced InpIt throws or T's copy constructor throws.
1140    //!
1141    //! <b>Complexity</b>: Linear to std::distance [first, last).
1142    template <class InpIt>
1143    void insert(const_iterator pos, InpIt first, InpIt last) 
1144    {
1145       //Dispatch depending on integer/iterator
1146       const bool aux_boolean = container_detail::is_convertible<InpIt, size_type>::value;
1147       typedef container_detail::bool_<aux_boolean> Result;
1148       this->priv_insert_dispatch(pos, first, last, Result());
1149    }
1150
1151    #if defined(BOOST_CONTAINER_PERFECT_FORWARDING) || defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
1152
1153    //! <b>Effects</b>: Inserts an object of type T constructed with
1154    //!   std::forward<Args>(args)... in the end of the deque.
1155    //!
1156    //! <b>Throws</b>: If memory allocation throws or the in-place constructor throws.
1157    //!
1158    //! <b>Complexity</b>: Amortized constant time
1159    template <class... Args>
1160    void emplace_back(Args&&... args)
1161    {
1162       if(this->priv_push_back_simple_available()){
1163          allocator_traits_type::construct
1164             ( this->alloc()
1165             , this->priv_push_back_simple_pos()
1166             , boost::forward<Args>(args)...);
1167          this->priv_push_back_simple_commit();
1168       }
1169       else{
1170          typedef container_detail::advanced_insert_aux_non_movable_emplace<A, iterator, Args...> type;
1171          type &&proxy = type(this->alloc(), boost::forward<Args>(args)...);
1172          this->priv_insert_back_aux_impl(1, proxy);
1173       }
1174    }
1175
1176    //! <b>Effects</b>: Inserts an object of type T constructed with
1177    //!   std::forward<Args>(args)... in the beginning of the deque.
1178    //!
1179    //! <b>Throws</b>: If memory allocation throws or the in-place constructor throws.
1180    //!
1181    //! <b>Complexity</b>: Amortized constant time
1182    template <class... Args>
1183    void emplace_front(Args&&... args)
1184    {
1185       if(this->priv_push_front_simple_available()){
1186          allocator_traits_type::construct
1187             ( this->alloc()
1188             , this->priv_push_front_simple_pos()
1189             , boost::forward<Args>(args)...);
1190          this->priv_push_front_simple_commit();
1191       }
1192       else{
1193          typedef container_detail::advanced_insert_aux_non_movable_emplace<A, iterator, Args...> type;
1194          type &&proxy = type(this->alloc(), boost::forward<Args>(args)...);
1195          this->priv_insert_front_aux_impl(1, proxy);
1196       }
1197    }
1198
1199    //! <b>Requires</b>: position must be a valid iterator of *this.
1200    //!
1201    //! <b>Effects</b>: Inserts an object of type T constructed with
1202    //!   std::forward<Args>(args)... before position
1203    //!
1204    //! <b>Throws</b>: If memory allocation throws or the in-place constructor throws.
1205    //!
1206    //! <b>Complexity</b>: If position is end(), amortized constant time
1207    //!   Linear time otherwise.
1208    template <class... Args>
1209    iterator emplace(const_iterator p, Args&&... args)
1210    {
1211       if(p == this->cbegin()){
1212          this->emplace_front(boost::forward<Args>(args)...);
1213          return this->begin();
1214       }
1215       else if(p == this->cend()){
1216          this->emplace_back(boost::forward<Args>(args)...);
1217          return (this->end()-1);
1218       }
1219       else{
1220          size_type n = p - this->cbegin();
1221          typedef container_detail::advanced_insert_aux_emplace<A, iterator, Args...> type;
1222          type &&proxy = type(this->alloc(), boost::forward<Args>(args)...);
1223          this->priv_insert_aux_impl(p, 1, proxy);
1224          return iterator(this->begin() + n);
1225       }
1226    }
1227
1228    #else //#ifdef BOOST_CONTAINER_PERFECT_FORWARDING
1229
1230    //advanced_insert_int.hpp includes all necessary preprocessor machinery...
1231    #define BOOST_PP_LOCAL_MACRO(n)                                                           \
1232    BOOST_PP_EXPR_IF(n, template<) BOOST_PP_ENUM_PARAMS(n, class P) BOOST_PP_EXPR_IF(n, >)    \
1233    void emplace_back(BOOST_PP_ENUM(n, BOOST_CONTAINER_PP_PARAM_LIST, _))                     \
1234    {                                                                                         \
1235       if(priv_push_back_simple_available()){                                                 \
1236          allocator_traits_type::construct                                                    \
1237             ( this->alloc()                                                                  \
1238             , this->priv_push_back_simple_pos()                                              \
1239               BOOST_PP_ENUM_TRAILING(n, BOOST_CONTAINER_PP_PARAM_FORWARD, _));               \
1240          priv_push_back_simple_commit();                                                     \
1241       }                                                                                      \
1242       else{                                                                                  \
1243          container_detail::BOOST_PP_CAT(BOOST_PP_CAT(                                        \
1244             advanced_insert_aux_non_movable_emplace, n), arg)                                \
1245                <A, iterator BOOST_PP_ENUM_TRAILING_PARAMS(n, P)> proxy                       \
1246             (this->alloc() BOOST_PP_ENUM_TRAILING(n, BOOST_CONTAINER_PP_PARAM_FORWARD, _));  \
1247          priv_insert_back_aux_impl(1, proxy);                                                \
1248       }                                                                                      \
1249    }                                                                                         \
1250                                                                                              \
1251    BOOST_PP_EXPR_IF(n, template<) BOOST_PP_ENUM_PARAMS(n, class P) BOOST_PP_EXPR_IF(n, >  )  \
1252    void emplace_front(BOOST_PP_ENUM(n, BOOST_CONTAINER_PP_PARAM_LIST, _))                    \
1253    {                                                                                         \
1254       if(priv_push_front_simple_available()){                                                \
1255          allocator_traits_type::construct                                                    \
1256             ( this->alloc()                                                                  \
1257             , this->priv_push_front_simple_pos()                                             \
1258               BOOST_PP_ENUM_TRAILING(n, BOOST_CONTAINER_PP_PARAM_FORWARD, _));               \
1259          priv_push_front_simple_commit();                                                    \
1260       }                                                                                      \
1261       else{                                                                                  \
1262          container_detail::BOOST_PP_CAT(BOOST_PP_CAT                                         \
1263             (advanced_insert_aux_non_movable_emplace, n), arg)                               \
1264                <A, iterator BOOST_PP_ENUM_TRAILING_PARAMS(n, P)> proxy                       \
1265             (this->alloc() BOOST_PP_ENUM_TRAILING(n, BOOST_CONTAINER_PP_PARAM_FORWARD, _));  \
1266          priv_insert_front_aux_impl(1, proxy);                                               \
1267       }                                                                                      \
1268    }                                                                                         \
1269                                                                                              \
1270    BOOST_PP_EXPR_IF(n, template<) BOOST_PP_ENUM_PARAMS(n, class P) BOOST_PP_EXPR_IF(n, >)    \
1271    iterator emplace(const_iterator p                                                         \
1272                     BOOST_PP_ENUM_TRAILING(n, BOOST_CONTAINER_PP_PARAM_LIST, _))             \
1273    {                                                                                         \
1274       if(p == this->cbegin()){                                                               \
1275          this->emplace_front(BOOST_PP_ENUM(n, BOOST_CONTAINER_PP_PARAM_FORWARD, _));         \
1276          return this->begin();                                                               \
1277       }                                                                                      \
1278       else if(p == cend()){                                                                  \
1279          this->emplace_back(BOOST_PP_ENUM(n, BOOST_CONTAINER_PP_PARAM_FORWARD, _));          \
1280          return (this->end()-1);                                                             \
1281       }                                                                                      \
1282       else{                                                                                  \
1283          size_type pos_num = p - this->cbegin();                                             \
1284          container_detail::BOOST_PP_CAT(BOOST_PP_CAT(advanced_insert_aux_emplace, n), arg)   \
1285             <A, iterator BOOST_PP_ENUM_TRAILING_PARAMS(n, P)> proxy                          \
1286             (this->alloc() BOOST_PP_ENUM_TRAILING(n, BOOST_CONTAINER_PP_PARAM_FORWARD, _));  \
1287          this->priv_insert_aux_impl(p, 1, proxy);                                            \
1288          return iterator(this->begin() + pos_num);                                           \
1289       }                                                                                      \
1290    }                                                                                         \
1291    //!
1292    #define BOOST_PP_LOCAL_LIMITS (0, BOOST_CONTAINER_MAX_CONSTRUCTOR_PARAMETERS)
1293    #include BOOST_PP_LOCAL_ITERATE()
1294
1295    #endif   //#ifdef BOOST_CONTAINER_PERFECT_FORWARDING
1296
1297    //! <b>Effects</b>: Inserts or erases elements at the end such that
1298    //!   the size becomes n. New elements are copy constructed from x.
1299    //!
1300    //! <b>Throws</b>: If memory allocation throws, or T's copy constructor throws.
1301    //!
1302    //! <b>Complexity</b>: Linear to the difference between size() and new_size.
1303    void resize(size_type new_size, const value_type& x) 
1304    {
1305       const size_type len = size();
1306       if (new_size < len) 
1307          this->erase(this->members_.m_start + new_size, this->members_.m_finish);
1308       else
1309          this->insert(this->members_.m_finish, new_size - len, x);
1310    }
1311
1312    //! <b>Effects</b>: Inserts or erases elements at the end such that
1313    //!   the size becomes n. New elements are default constructed.
1314    //!
1315    //! <b>Throws</b>: If memory allocation throws, or T's copy constructor throws.
1316    //!
1317    //! <b>Complexity</b>: Linear to the difference between size() and new_size.
1318    void resize(size_type new_size) 
1319    {
1320       const size_type len = size();
1321       if (new_size < len) 
1322          this->priv_erase_last_n(len - new_size);
1323       else{
1324          size_type n = new_size - this->size();
1325          container_detail::default_construct_aux_proxy<A, iterator> proxy(this->alloc(), n);
1326          priv_insert_back_aux_impl(n, proxy);
1327       }
1328    }
1329
1330    //! <b>Effects</b>: Erases the element at position pos.
1331    //!
1332    //! <b>Throws</b>: Nothing.
1333    //!
1334    //! <b>Complexity</b>: Linear to the elements between pos and the 
1335    //!   last element (if pos is near the end) or the first element
1336    //!   if(pos is near the beginning).
1337    //!   Constant if pos is the first or the last element.
1338    iterator erase(const_iterator pos) BOOST_CONTAINER_NOEXCEPT
1339    {
1340       const_iterator next = pos;
1341       ++next;
1342       difference_type index = pos - this->members_.m_start;
1343       if (size_type(index) < (this->size() >> 1)) {
1344          boost::move_backward(begin(), iterator(pos), iterator(next));
1345          pop_front();
1346       }
1347       else {
1348          boost::move(iterator(next), end(), iterator(pos));
1349          pop_back();
1350       }
1351       return this->members_.m_start + index;
1352    }
1353
1354    //! <b>Effects</b>: Erases the elements pointed by [first, last).
1355    //!
1356    //! <b>Throws</b>: Nothing.
1357    //!
1358    //! <b>Complexity</b>: Linear to the distance between first and
1359    //!   last plus the elements between pos and the 
1360    //!   last element (if pos is near the end) or the first element
1361    //!   if(pos is near the beginning).
1362    iterator erase(const_iterator first, const_iterator last) BOOST_CONTAINER_NOEXCEPT
1363    {
1364       if (first == this->members_.m_start && last == this->members_.m_finish) {
1365          this->clear();
1366          return this->members_.m_finish;
1367       }
1368       else {
1369          difference_type n = last - first;
1370          difference_type elems_before = first - this->members_.m_start;
1371          if (elems_before < static_cast<difference_type>(this->size() - n) - elems_before) {
1372             boost::move_backward(begin(), iterator(first), iterator(last));
1373             iterator new_start = this->members_.m_start + n;
1374             if(!Base::traits_t::trivial_dctr_after_move)
1375                this->priv_destroy_range(this->members_.m_start, new_start);
1376             this->priv_destroy_nodes(this->members_.m_start.m_node, new_start.m_node);
1377             this->members_.m_start = new_start;
1378          }
1379          else {
1380             boost::move(iterator(last), end(), iterator(first));
1381             iterator new_finish = this->members_.m_finish - n;
1382             if(!Base::traits_t::trivial_dctr_after_move)
1383                this->priv_destroy_range(new_finish, this->members_.m_finish);
1384             this->priv_destroy_nodes(new_finish.m_node + 1, this->members_.m_finish.m_node + 1);
1385             this->members_.m_finish = new_finish;
1386          }
1387          return this->members_.m_start + elems_before;
1388       }
1389    }
1390
1391    void priv_erase_last_n(size_type n)
1392    {
1393       if(n == this->size()) {
1394          this->clear();
1395       }
1396       else {
1397          iterator new_finish = this->members_.m_finish - n;
1398          if(!Base::traits_t::trivial_dctr_after_move)
1399             this->priv_destroy_range(new_finish, this->members_.m_finish);
1400          this->priv_destroy_nodes(new_finish.m_node + 1, this->members_.m_finish.m_node + 1);
1401          this->members_.m_finish = new_finish;
1402       }
1403    }
1404
1405    //! <b>Effects</b>: Erases all the elements of the deque.
1406    //!
1407    //! <b>Throws</b>: Nothing.
1408    //!
1409    //! <b>Complexity</b>: Linear to the number of elements in the deque.
1410    void clear() BOOST_CONTAINER_NOEXCEPT
1411    {
1412       for (index_pointer node = this->members_.m_start.m_node + 1;
1413             node < this->members_.m_finish.m_node;
1414             ++node) {
1415          this->priv_destroy_range(*node, *node + this->s_buffer_size());
1416          this->priv_deallocate_node(*node);
1417       }
1418
1419       if (this->members_.m_start.m_node != this->members_.m_finish.m_node) {
1420          this->priv_destroy_range(this->members_.m_start.m_cur, this->members_.m_start.m_last);
1421          this->priv_destroy_range(this->members_.m_finish.m_first, this->members_.m_finish.m_cur);
1422          this->priv_deallocate_node(this->members_.m_finish.m_first);
1423       }
1424       else
1425          this->priv_destroy_range(this->members_.m_start.m_cur, this->members_.m_finish.m_cur);
1426
1427       this->members_.m_finish = this->members_.m_start;
1428    }
1429
1430    //! <b>Effects</b>: Tries to deallocate the excess of memory created
1431    //!   with previous allocations. The size of the deque is unchanged
1432    //!
1433    //! <b>Throws</b>: If memory allocation throws.
1434    //!
1435    //! <b>Complexity</b>: Constant.
1436    void shrink_to_fit()
1437    {
1438       //This deque implementation already
1439       //deallocates excess nodes when erasing
1440       //so there is nothing to do except for
1441       //empty deque
1442       if(this->empty()){
1443          this->priv_clear_map();
1444       }
1445    }
1446
1447    /// @cond
1448    private:
1449    void priv_range_check(size_type n) const 
1450       {  if (n >= this->size())  BOOST_RETHROW std::out_of_range("deque");   }
1451
1452    iterator priv_insert(const_iterator position, const value_type &x) 
1453    {
1454       if (position == cbegin()){
1455          this->push_front(x);
1456          return begin();
1457       }
1458       else if (position == cend()){
1459          this->push_back(x);
1460          return (end()-1);
1461       }
1462       else {
1463          size_type n = position - cbegin();
1464          this->priv_insert_aux(position, size_type(1), x);
1465          return iterator(this->begin() + n);
1466       }
1467    }
1468
1469    iterator priv_insert(const_iterator position, BOOST_RV_REF(value_type) mx) 
1470    {
1471       if (position == cbegin()) {
1472          this->push_front(boost::move(mx));
1473          return begin();
1474       }
1475       else if (position == cend()) {
1476          this->push_back(boost::move(mx));
1477          return(end()-1);
1478       }
1479       else {
1480          //Just call more general insert(pos, size, value) and return iterator
1481          size_type n = position - begin();
1482          this->priv_insert_aux(position, move_it(r_iterator(mx, 1)), move_it(r_iterator()));
1483          return iterator(this->begin() + n);
1484       }
1485    }
1486
1487    void priv_push_front(const value_type &t)
1488    {
1489       if(this->priv_push_front_simple_available()){
1490          allocator_traits_type::construct
1491             ( this->alloc(), this->priv_push_front_simple_pos(), t);
1492          this->priv_push_front_simple_commit();
1493       }
1494       else{
1495          this->priv_insert_aux(cbegin(), size_type(1), t);
1496       }
1497    }
1498
1499    void priv_push_front(BOOST_RV_REF(value_type) t)
1500    {
1501       if(this->priv_push_front_simple_available()){
1502          allocator_traits_type::construct
1503             ( this->alloc(), this->priv_push_front_simple_pos(), boost::move(t));
1504          this->priv_push_front_simple_commit();
1505       }
1506       else{
1507          this->priv_insert_aux(cbegin(), move_it(r_iterator(t, 1)), move_it(r_iterator()));
1508       }
1509    }
1510
1511    void priv_push_back(const value_type &t)
1512    {
1513       if(this->priv_push_back_simple_available()){
1514          allocator_traits_type::construct
1515             ( this->alloc(), this->priv_push_back_simple_pos(), t);
1516          this->priv_push_back_simple_commit();
1517       }
1518       else{
1519          this->priv_insert_aux(cend(), size_type(1), t);
1520       }
1521    }
1522
1523    void priv_push_back(BOOST_RV_REF(T) t)
1524    {
1525       if(this->priv_push_back_simple_available()){
1526          allocator_traits_type::construct
1527             ( this->alloc(), this->priv_push_back_simple_pos(), boost::move(t));
1528          this->priv_push_back_simple_commit();
1529       }
1530       else{
1531          this->priv_insert_aux(cend(), move_it(r_iterator(t, 1)), move_it(r_iterator()));
1532       }
1533    }
1534
1535    bool priv_push_back_simple_available() const
1536    {
1537       return this->members_.m_map &&
1538          (this->members_.m_finish.m_cur != (this->members_.m_finish.m_last - 1));
1539    }
1540
1541    T *priv_push_back_simple_pos() const
1542    {
1543       return container_detail::to_raw_pointer(this->members_.m_finish.m_cur);
1544    }
1545
1546    void priv_push_back_simple_commit()
1547    {
1548       ++this->members_.m_finish.m_cur;
1549    }
1550
1551    bool priv_push_front_simple_available() const
1552    {
1553       return this->members_.m_map &&
1554          (this->members_.m_start.m_cur != this->members_.m_start.m_first);
1555    }
1556
1557    T *priv_push_front_simple_pos() const
1558    {  return container_detail::to_raw_pointer(this->members_.m_start.m_cur) - 1;  }
1559
1560    void priv_push_front_simple_commit()
1561    {  --this->members_.m_start.m_cur;   }
1562
1563    template <class InpIt>
1564    void priv_insert_aux(const_iterator pos, InpIt first, InpIt last, std::input_iterator_tag)
1565    {
1566       for(;first != last; ++first){
1567          this->insert(pos, boost::move(value_type(*first)));
1568       }
1569    }
1570
1571    template <class FwdIt>
1572    void priv_insert_aux(const_iterator pos, FwdIt first, FwdIt last, std::forward_iterator_tag) 
1573    {  this->priv_insert_aux(pos, first, last);  }
1574
1575   // assign(), a generalized assignment member function.  Two
1576   // versions: one that takes a count, and one that takes a range.
1577   // The range version is a member template, so we dispatch on whether
1578   // or not the type is an integer.
1579    void priv_fill_assign(size_type n, const T& val)
1580    {
1581       if (n > size()) {
1582          std::fill(begin(), end(), val);
1583          this->insert(cend(), n - size(), val);
1584       }
1585       else {
1586          this->erase(cbegin() + n, cend());
1587          std::fill(begin(), end(), val);
1588       }
1589    }
1590
1591    template <class Integer>
1592    void priv_initialize_dispatch(Integer n, Integer x, container_detail::true_) 
1593    {
1594       this->priv_initialize_map(n);
1595       this->priv_fill_initialize(x);
1596    }
1597
1598    template <class InpIt>
1599    void priv_initialize_dispatch(InpIt first, InpIt last, container_detail::false_) 
1600    {
1601       typedef typename std::iterator_traits<InpIt>::iterator_category ItCat;
1602       this->priv_range_initialize(first, last, ItCat());
1603    }
1604
1605    void priv_destroy_range(iterator p, iterator p2)
1606    {
1607       for(;p != p2; ++p){
1608          allocator_traits_type::destroy
1609             ( this->alloc()
1610             , container_detail::to_raw_pointer(&*p)
1611             );
1612       }
1613    }
1614
1615    void priv_destroy_range(pointer p, pointer p2)
1616    {
1617       for(;p != p2; ++p){
1618          allocator_traits_type::destroy
1619             ( this->alloc()
1620             , container_detail::to_raw_pointer(&*p)
1621             );
1622       }
1623    }
1624
1625    template <class Integer>
1626    void priv_assign_dispatch(Integer n, Integer val, container_detail::true_)
1627       { this->priv_fill_assign((size_type) n, (value_type)val); }
1628
1629    template <class InpIt>
1630    void priv_assign_dispatch(InpIt first, InpIt last, container_detail::false_) 
1631    {
1632       typedef typename std::iterator_traits<InpIt>::iterator_category ItCat;
1633       this->priv_assign_aux(first, last, ItCat());
1634    }
1635
1636    template <class InpIt>
1637    void priv_assign_aux(InpIt first, InpIt last, std::input_iterator_tag)
1638    {
1639       iterator cur = begin();
1640       for ( ; first != last && cur != end(); ++cur, ++first)
1641          *cur = *first;
1642       if (first == last)
1643          this->erase(cur, cend());
1644       else
1645          this->insert(cend(), first, last);
1646    }
1647
1648    template <class FwdIt>
1649    void priv_assign_aux(FwdIt first, FwdIt last, std::forward_iterator_tag)
1650    {
1651       size_type len = std::distance(first, last);
1652       if (len > size()) {
1653          FwdIt mid = first;
1654          std::advance(mid, size());
1655          boost::copy_or_move(first, mid, begin());
1656          this->insert(cend(), mid, last);
1657       }
1658       else
1659          this->erase(boost::copy_or_move(first, last, begin()), cend());
1660    }
1661
1662    template <class Integer>
1663    void priv_insert_dispatch(const_iterator pos, Integer n, Integer x, container_detail::true_) 
1664    {  this->priv_fill_insert(pos, (size_type) n, (value_type)x); }
1665
1666    template <class InpIt>
1667    void priv_insert_dispatch(const_iterator pos,InpIt first, InpIt last, container_detail::false_) 
1668    {
1669       typedef typename std::iterator_traits<InpIt>::iterator_category ItCat;
1670       this->priv_insert_aux(pos, first, last, ItCat());
1671    }
1672
1673    void priv_insert_aux(const_iterator pos, size_type n, const value_type& x)
1674    {
1675       typedef constant_iterator<value_type, difference_type> c_it;
1676       this->priv_insert_aux(pos, c_it(x, n), c_it());
1677    }
1678
1679    //Just forward all operations to priv_insert_aux_impl
1680    template <class FwdIt>
1681    void priv_insert_aux(const_iterator p, FwdIt first, FwdIt last)
1682    {
1683       container_detail::advanced_insert_aux_proxy<A, FwdIt, iterator> proxy(this->alloc(), first, last);
1684       priv_insert_aux_impl(p, (size_type)std::distance(first, last), proxy);
1685    }
1686
1687    void priv_insert_aux_impl(const_iterator p, size_type n, advanced_insert_aux_int_t &interf)
1688    {
1689       iterator pos(p);
1690       if(!this->members_.m_map){
1691          this->priv_initialize_map(0);
1692          pos = this->begin();
1693       }
1694
1695       const difference_type elemsbefore = pos - this->members_.m_start;
1696       size_type length = this->size();
1697       if (elemsbefore < static_cast<difference_type>(length / 2)) {
1698          iterator new_start = this->priv_reserve_elements_at_front(n);
1699          iterator old_start = this->members_.m_start;
1700          pos = this->members_.m_start + elemsbefore;
1701          if (elemsbefore >= difference_type(n)) {
1702             iterator start_n = this->members_.m_start + difference_type(n); 
1703             ::boost::container::uninitialized_move_alloc
1704                (this->alloc(), this->members_.m_start, start_n, new_start);
1705             this->members_.m_start = new_start;
1706             boost::move(start_n, pos, old_start);
1707             interf.copy_remaining_to(pos - difference_type(n));
1708          }
1709          else {
1710             difference_type mid_count = (difference_type(n) - elemsbefore);
1711             iterator mid_start = old_start - mid_count;
1712             interf.uninitialized_copy_some_and_update(mid_start, mid_count, true);
1713             this->members_.m_start = mid_start;
1714             ::boost::container::uninitialized_move_alloc
1715                (this->alloc(), old_start, pos, new_start);
1716             this->members_.m_start = new_start;
1717             interf.copy_remaining_to(old_start);
1718          }
1719       }
1720       else {
1721          iterator new_finish = this->priv_reserve_elements_at_back(n);
1722          iterator old_finish = this->members_.m_finish;
1723          const difference_type elemsafter = 
1724             difference_type(length) - elemsbefore;
1725          pos = this->members_.m_finish - elemsafter;
1726          if (elemsafter >= difference_type(n)) {
1727             iterator finish_n = this->members_.m_finish - difference_type(n);
1728             ::boost::container::uninitialized_move_alloc
1729                (this->alloc(), finish_n, this->members_.m_finish, this->members_.m_finish);
1730             this->members_.m_finish = new_finish;
1731             boost::move_backward(pos, finish_n, old_finish);
1732             interf.copy_remaining_to(pos);
1733          }
1734          else {
1735             interf.uninitialized_copy_some_and_update(old_finish, elemsafter, false);
1736             this->members_.m_finish += n-elemsafter;
1737             ::boost::container::uninitialized_move_alloc
1738                (this->alloc(), pos, old_finish, this->members_.m_finish);
1739             this->members_.m_finish = new_finish;
1740             interf.copy_remaining_to(pos);
1741          }
1742       }
1743    }
1744
1745    void priv_insert_back_aux_impl(size_type n, advanced_insert_aux_int_t &interf)
1746    {
1747       if(!this->members_.m_map){
1748          this->priv_initialize_map(0);
1749       }
1750
1751       iterator new_finish = this->priv_reserve_elements_at_back(n);
1752       iterator old_finish = this->members_.m_finish;
1753       interf.uninitialized_copy_some_and_update(old_finish, n, true);
1754       this->members_.m_finish = new_finish;
1755    }
1756
1757    void priv_insert_front_aux_impl(size_type n, advanced_insert_aux_int_t &interf)
1758    {
1759       if(!this->members_.m_map){
1760          this->priv_initialize_map(0);
1761       }
1762
1763       iterator new_start = this->priv_reserve_elements_at_front(n);
1764       interf.uninitialized_copy_some_and_update(new_start, difference_type(n), true);
1765       this->members_.m_start = new_start;
1766    }
1767
1768
1769    void priv_fill_insert(const_iterator pos, size_type n, const value_type& x)
1770    {
1771       typedef constant_iterator<value_type, difference_type> c_it;
1772       this->insert(pos, c_it(x, n), c_it());
1773    }
1774
1775    // Precondition: this->members_.m_start and this->members_.m_finish have already been initialized,
1776    // but none of the deque's elements have yet been constructed.
1777    void priv_fill_initialize(const value_type& value) 
1778    {
1779       index_pointer cur;
1780       BOOST_TRY {
1781          for (cur = this->members_.m_start.m_node; cur < this->members_.m_finish.m_node; ++cur){
1782             boost::container::uninitialized_fill_alloc
1783                (this->alloc(), *cur, *cur + this->s_buffer_size(), value);
1784          }
1785          boost::container::uninitialized_fill_alloc
1786             (this->alloc(), this->members_.m_finish.m_first, this->members_.m_finish.m_cur, value);
1787       }
1788       BOOST_CATCH(...){
1789          this->priv_destroy_range(this->members_.m_start, iterator(*cur, cur));
1790          BOOST_RETHROW
1791       }
1792       BOOST_CATCH_END
1793    }
1794
1795    template <class InpIt>
1796    void priv_range_initialize(InpIt first, InpIt last, std::input_iterator_tag)
1797    {
1798       this->priv_initialize_map(0);
1799       BOOST_TRY {
1800          for ( ; first != last; ++first)
1801             this->push_back(*first);
1802       }
1803       BOOST_CATCH(...){
1804          this->clear();
1805          BOOST_RETHROW
1806       }
1807       BOOST_CATCH_END
1808    }
1809
1810    template <class FwdIt>
1811    void priv_range_initialize(FwdIt first, FwdIt last, std::forward_iterator_tag)
1812    {
1813       size_type n = 0;
1814       n = std::distance(first, last);
1815       this->priv_initialize_map(n);
1816
1817       index_pointer cur_node;
1818       BOOST_TRY {
1819          for (cur_node = this->members_.m_start.m_node; 
1820                cur_node < this->members_.m_finish.m_node; 
1821                ++cur_node) {
1822             FwdIt mid = first;
1823             std::advance(mid, this->s_buffer_size());
1824             ::boost::container::uninitialized_copy_or_move_alloc
1825                (this->alloc(), first, mid, *cur_node);
1826             first = mid;
1827          }
1828          ::boost::container::uninitialized_copy_or_move_alloc
1829             (this->alloc(), first, last, this->members_.m_finish.m_first);
1830       }
1831       BOOST_CATCH(...){
1832          this->priv_destroy_range(this->members_.m_start, iterator(*cur_node, cur_node));
1833          BOOST_RETHROW
1834       }
1835       BOOST_CATCH_END
1836    }
1837
1838    // Called only if this->members_.m_finish.m_cur == this->members_.m_finish.m_first.
1839    void priv_pop_back_aux()
1840    {
1841       this->priv_deallocate_node(this->members_.m_finish.m_first);
1842       this->members_.m_finish.priv_set_node(this->members_.m_finish.m_node - 1);
1843       this->members_.m_finish.m_cur = this->members_.m_finish.m_last - 1;
1844       allocator_traits_type::destroy
1845          ( this->alloc()
1846          , container_detail::to_raw_pointer(this->members_.m_finish.m_cur)
1847          );
1848    }
1849
1850    // Called only if this->members_.m_start.m_cur == this->members_.m_start.m_last - 1.  Note that 
1851    // if the deque has at least one element (a precondition for this member 
1852    // function), and if this->members_.m_start.m_cur == this->members_.m_start.m_last, then the deque 
1853    // must have at least two nodes.
1854    void priv_pop_front_aux()
1855    {
1856       allocator_traits_type::destroy
1857          ( this->alloc()
1858          , container_detail::to_raw_pointer(this->members_.m_start.m_cur)
1859          );
1860       this->priv_deallocate_node(this->members_.m_start.m_first);
1861       this->members_.m_start.priv_set_node(this->members_.m_start.m_node + 1);
1862       this->members_.m_start.m_cur = this->members_.m_start.m_first;
1863    }      
1864
1865    iterator priv_reserve_elements_at_front(size_type n) 
1866    {
1867       size_type vacancies = this->members_.m_start.m_cur - this->members_.m_start.m_first;
1868       if (n > vacancies){
1869          size_type new_elems = n-vacancies;
1870          size_type new_nodes = (new_elems + this->s_buffer_size() - 1) / 
1871             this->s_buffer_size();
1872          size_type s = (size_type)(this->members_.m_start.m_node - this->members_.m_map);
1873          if (new_nodes > s){
1874             this->priv_reallocate_map(new_nodes, true);
1875          }
1876          size_type i = 1;
1877          BOOST_TRY {
1878             for (; i <= new_nodes; ++i)
1879                *(this->members_.m_start.m_node - i) = this->priv_allocate_node();
1880          }
1881          BOOST_CATCH(...) {
1882             for (size_type j = 1; j < i; ++j)
1883                this->priv_deallocate_node(*(this->members_.m_start.m_node - j));      
1884             BOOST_RETHROW
1885          }
1886          BOOST_CATCH_END
1887       }
1888       return this->members_.m_start - difference_type(n);
1889    }
1890
1891    iterator priv_reserve_elements_at_back(size_type n) 
1892    {
1893       size_type vacancies = (this->members_.m_finish.m_last - this->members_.m_finish.m_cur) - 1;
1894       if (n > vacancies){
1895          size_type new_elems = n - vacancies;
1896          size_type new_nodes = (new_elems + this->s_buffer_size() - 1)/s_buffer_size();
1897          size_type s = (size_type)(this->members_.m_map_size - (this->members_.m_finish.m_node - this->members_.m_map));
1898          if (new_nodes + 1 > s){
1899             this->priv_reallocate_map(new_nodes, false);
1900          }
1901          size_type i;
1902          BOOST_TRY {
1903             for (i = 1; i <= new_nodes; ++i)
1904                *(this->members_.m_finish.m_node + i) = this->priv_allocate_node();
1905          }
1906          BOOST_CATCH(...) {
1907             for (size_type j = 1; j < i; ++j)
1908                this->priv_deallocate_node(*(this->members_.m_finish.m_node + j));      
1909             BOOST_RETHROW
1910          }
1911          BOOST_CATCH_END
1912       }
1913       return this->members_.m_finish + difference_type(n);
1914    }
1915
1916    void priv_reallocate_map(size_type nodes_to_add, bool add_at_front)
1917    {
1918       size_type old_num_nodes = this->members_.m_finish.m_node - this->members_.m_start.m_node + 1;
1919       size_type new_num_nodes = old_num_nodes + nodes_to_add;
1920
1921       index_pointer new_nstart;
1922       if (this->members_.m_map_size > 2 * new_num_nodes) {
1923          new_nstart = this->members_.m_map + (this->members_.m_map_size - new_num_nodes) / 2 
1924                            + (add_at_front ? nodes_to_add : 0);
1925          if (new_nstart < this->members_.m_start.m_node)
1926             boost::move(this->members_.m_start.m_node, this->members_.m_finish.m_node + 1, new_nstart);
1927          else
1928             boost::move_backward
1929                (this->members_.m_start.m_node, this->members_.m_finish.m_node + 1, new_nstart + old_num_nodes);
1930       }
1931       else {
1932          size_type new_map_size = 
1933             this->members_.m_map_size + container_detail::max_value(this->members_.m_map_size, nodes_to_add) + 2;
1934
1935          index_pointer new_map = this->priv_allocate_map(new_map_size);
1936          new_nstart = new_map + (new_map_size - new_num_nodes) / 2
1937                               + (add_at_front ? nodes_to_add : 0);
1938          boost::move(this->members_.m_start.m_node, this->members_.m_finish.m_node + 1, new_nstart);
1939          this->priv_deallocate_map(this->members_.m_map, this->members_.m_map_size);
1940
1941          this->members_.m_map = new_map;
1942          this->members_.m_map_size = new_map_size;
1943       }
1944
1945       this->members_.m_start.priv_set_node(new_nstart);
1946       this->members_.m_finish.priv_set_node(new_nstart + old_num_nodes - 1);
1947    }
1948    /// @endcond
1949 };
1950
1951 // Nonmember functions.
1952 template <class T, class A>
1953 inline bool operator==(const deque<T, A>& x,
1954                        const deque<T, A>& y)
1955 {
1956    return x.size() == y.size() && equal(x.begin(), x.end(), y.begin());
1957 }
1958
1959 template <class T, class A>
1960 inline bool operator<(const deque<T, A>& x,
1961                       const deque<T, A>& y) 
1962 {
1963    return lexicographical_compare(x.begin(), x.end(), y.begin(), y.end());
1964 }
1965
1966 template <class T, class A>
1967 inline bool operator!=(const deque<T, A>& x,
1968                        const deque<T, A>& y) 
1969    {  return !(x == y);   }
1970
1971 template <class T, class A>
1972 inline bool operator>(const deque<T, A>& x,
1973                       const deque<T, A>& y) 
1974    {  return y < x; }
1975
1976 template <class T, class A>
1977 inline bool operator<=(const deque<T, A>& x,
1978                        const deque<T, A>& y) 
1979    {  return !(y < x); }
1980
1981 template <class T, class A>
1982 inline bool operator>=(const deque<T, A>& x,
1983                        const deque<T, A>& y) 
1984    {  return !(x < y); }
1985
1986
1987 template <class T, class A>
1988 inline void swap(deque<T, A>& x, deque<T, A>& y)
1989 {  x.swap(y);  }
1990
1991 }}
1992
1993 /// @cond
1994
1995 namespace boost {
1996 /*
1997 //!has_trivial_destructor_after_move<> == true_type
1998 //!specialization for optimizations
1999 template <class T, class A>
2000 struct has_trivial_destructor_after_move<boost::container::deque<T, A> >
2001 {
2002    enum {   value = has_trivial_destructor<A>::value  };
2003 };
2004 */
2005 }
2006
2007 /// @endcond
2008
2009 #include <boost/container/detail/config_end.hpp>
2010
2011 #endif //   #ifndef  BOOST_CONTAINER_DEQUE_HPP