Home | History | Annotate | Download | only in bits
      1 // Deque implementation (out of line) -*- C++ -*-
      2 
      3 // Copyright (C) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008,
      4 // 2009, 2010, 2011, 2012
      5 // Free Software Foundation, Inc.
      6 //
      7 // This file is part of the GNU ISO C++ Library.  This library is free
      8 // software; you can redistribute it and/or modify it under the
      9 // terms of the GNU General Public License as published by the
     10 // Free Software Foundation; either version 3, or (at your option)
     11 // any later version.
     12 
     13 // This library is distributed in the hope that it will be useful,
     14 // but WITHOUT ANY WARRANTY; without even the implied warranty of
     15 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     16 // GNU General Public License for more details.
     17 
     18 // Under Section 7 of GPL version 3, you are granted additional
     19 // permissions described in the GCC Runtime Library Exception, version
     20 // 3.1, as published by the Free Software Foundation.
     21 
     22 // You should have received a copy of the GNU General Public License and
     23 // a copy of the GCC Runtime Library Exception along with this program;
     24 // see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
     25 // <http://www.gnu.org/licenses/>.
     26 
     27 /*
     28  *
     29  * Copyright (c) 1994
     30  * Hewlett-Packard Company
     31  *
     32  * Permission to use, copy, modify, distribute and sell this software
     33  * and its documentation for any purpose is hereby granted without fee,
     34  * provided that the above copyright notice appear in all copies and
     35  * that both that copyright notice and this permission notice appear
     36  * in supporting documentation.  Hewlett-Packard Company makes no
     37  * representations about the suitability of this software for any
     38  * purpose.  It is provided "as is" without express or implied warranty.
     39  *
     40  *
     41  * Copyright (c) 1997
     42  * Silicon Graphics Computer Systems, Inc.
     43  *
     44  * Permission to use, copy, modify, distribute and sell this software
     45  * and its documentation for any purpose is hereby granted without fee,
     46  * provided that the above copyright notice appear in all copies and
     47  * that both that copyright notice and this permission notice appear
     48  * in supporting documentation.  Silicon Graphics makes no
     49  * representations about the suitability of this software for any
     50  * purpose.  It is provided "as is" without express or implied warranty.
     51  */
     52 
     53 /** @file bits/deque.tcc
     54  *  This is an internal header file, included by other library headers.
     55  *  Do not attempt to use it directly. @headername{deque}
     56  */
     57 
     58 #ifndef _DEQUE_TCC
     59 #define _DEQUE_TCC 1
     60 
     61 namespace std _GLIBCXX_VISIBILITY(default)
     62 {
     63 _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
     64 
     65 #ifdef __GXX_EXPERIMENTAL_CXX0X__
     66   template <typename _Tp, typename _Alloc>
     67     void
     68     deque<_Tp, _Alloc>::
     69     _M_default_initialize()
     70     {
     71       _Map_pointer __cur;
     72       __try
     73         {
     74           for (__cur = this->_M_impl._M_start._M_node;
     75 	       __cur < this->_M_impl._M_finish._M_node;
     76 	       ++__cur)
     77             std::__uninitialized_default_a(*__cur, *__cur + _S_buffer_size(),
     78 					   _M_get_Tp_allocator());
     79           std::__uninitialized_default_a(this->_M_impl._M_finish._M_first,
     80 					 this->_M_impl._M_finish._M_cur,
     81 					 _M_get_Tp_allocator());
     82         }
     83       __catch(...)
     84         {
     85           std::_Destroy(this->_M_impl._M_start, iterator(*__cur, __cur),
     86 			_M_get_Tp_allocator());
     87           __throw_exception_again;
     88         }
     89     }
     90 #endif
     91 
     92   template <typename _Tp, typename _Alloc>
     93     deque<_Tp, _Alloc>&
     94     deque<_Tp, _Alloc>::
     95     operator=(const deque& __x)
     96     {
     97       const size_type __len = size();
     98       if (&__x != this)
     99 	{
    100 	  if (__len >= __x.size())
    101 	    _M_erase_at_end(std::copy(__x.begin(), __x.end(),
    102 				      this->_M_impl._M_start));
    103 	  else
    104 	    {
    105 	      const_iterator __mid = __x.begin() + difference_type(__len);
    106 	      std::copy(__x.begin(), __mid, this->_M_impl._M_start);
    107 	      insert(this->_M_impl._M_finish, __mid, __x.end());
    108 	    }
    109 	}
    110       return *this;
    111     }
    112 
    113 #ifdef __GXX_EXPERIMENTAL_CXX0X__
    114   template<typename _Tp, typename _Alloc>
    115     template<typename... _Args>
    116       void
    117       deque<_Tp, _Alloc>::
    118       emplace_front(_Args&&... __args)
    119       {
    120 	if (this->_M_impl._M_start._M_cur != this->_M_impl._M_start._M_first)
    121 	  {
    122 	    this->_M_impl.construct(this->_M_impl._M_start._M_cur - 1,
    123 				    std::forward<_Args>(__args)...);
    124 	    --this->_M_impl._M_start._M_cur;
    125 	  }
    126 	else
    127 	  _M_push_front_aux(std::forward<_Args>(__args)...);
    128       }
    129 
    130   template<typename _Tp, typename _Alloc>
    131     template<typename... _Args>
    132       void
    133       deque<_Tp, _Alloc>::
    134       emplace_back(_Args&&... __args)
    135       {
    136 	if (this->_M_impl._M_finish._M_cur
    137 	    != this->_M_impl._M_finish._M_last - 1)
    138 	  {
    139 	    this->_M_impl.construct(this->_M_impl._M_finish._M_cur,
    140 				    std::forward<_Args>(__args)...);
    141 	    ++this->_M_impl._M_finish._M_cur;
    142 	  }
    143 	else
    144 	  _M_push_back_aux(std::forward<_Args>(__args)...);
    145       }
    146 #endif
    147 
    148   template <typename _Tp, typename _Alloc>
    149     typename deque<_Tp, _Alloc>::iterator
    150     deque<_Tp, _Alloc>::
    151     insert(iterator __position, const value_type& __x)
    152     {
    153       if (__position._M_cur == this->_M_impl._M_start._M_cur)
    154 	{
    155 	  push_front(__x);
    156 	  return this->_M_impl._M_start;
    157 	}
    158       else if (__position._M_cur == this->_M_impl._M_finish._M_cur)
    159 	{
    160 	  push_back(__x);
    161 	  iterator __tmp = this->_M_impl._M_finish;
    162 	  --__tmp;
    163 	  return __tmp;
    164 	}
    165       else
    166         return _M_insert_aux(__position, __x);
    167     }
    168 
    169 #ifdef __GXX_EXPERIMENTAL_CXX0X__
    170   template<typename _Tp, typename _Alloc>
    171     template<typename... _Args>
    172       typename deque<_Tp, _Alloc>::iterator
    173       deque<_Tp, _Alloc>::
    174       emplace(iterator __position, _Args&&... __args)
    175       {
    176 	if (__position._M_cur == this->_M_impl._M_start._M_cur)
    177 	  {
    178 	    emplace_front(std::forward<_Args>(__args)...);
    179 	    return this->_M_impl._M_start;
    180 	  }
    181 	else if (__position._M_cur == this->_M_impl._M_finish._M_cur)
    182 	  {
    183 	    emplace_back(std::forward<_Args>(__args)...);
    184 	    iterator __tmp = this->_M_impl._M_finish;
    185 	    --__tmp;
    186 	    return __tmp;
    187 	  }
    188 	else
    189 	  return _M_insert_aux(__position, std::forward<_Args>(__args)...);
    190       }
    191 #endif
    192 
    193   template <typename _Tp, typename _Alloc>
    194     typename deque<_Tp, _Alloc>::iterator
    195     deque<_Tp, _Alloc>::
    196     erase(iterator __position)
    197     {
    198       iterator __next = __position;
    199       ++__next;
    200       const difference_type __index = __position - begin();
    201       if (static_cast<size_type>(__index) < (size() >> 1))
    202 	{
    203 	  if (__position != begin())
    204 	    _GLIBCXX_MOVE_BACKWARD3(begin(), __position, __next);
    205 	  pop_front();
    206 	}
    207       else
    208 	{
    209 	  if (__next != end())
    210 	    _GLIBCXX_MOVE3(__next, end(), __position);
    211 	  pop_back();
    212 	}
    213       return begin() + __index;
    214     }
    215 
    216   template <typename _Tp, typename _Alloc>
    217     typename deque<_Tp, _Alloc>::iterator
    218     deque<_Tp, _Alloc>::
    219     erase(iterator __first, iterator __last)
    220     {
    221       if (__first == __last)
    222 	return __first;
    223       else if (__first == begin() && __last == end())
    224 	{
    225 	  clear();
    226 	  return end();
    227 	}
    228       else
    229 	{
    230 	  const difference_type __n = __last - __first;
    231 	  const difference_type __elems_before = __first - begin();
    232 	  if (static_cast<size_type>(__elems_before) <= (size() - __n) / 2)
    233 	    {
    234 	      if (__first != begin())
    235 		_GLIBCXX_MOVE_BACKWARD3(begin(), __first, __last);
    236 	      _M_erase_at_begin(begin() + __n);
    237 	    }
    238 	  else
    239 	    {
    240 	      if (__last != end())
    241 		_GLIBCXX_MOVE3(__last, end(), __first);
    242 	      _M_erase_at_end(end() - __n);
    243 	    }
    244 	  return begin() + __elems_before;
    245 	}
    246     }
    247 
    248   template <typename _Tp, class _Alloc>
    249     template <typename _InputIterator>
    250       void
    251       deque<_Tp, _Alloc>::
    252       _M_assign_aux(_InputIterator __first, _InputIterator __last,
    253 		    std::input_iterator_tag)
    254       {
    255         iterator __cur = begin();
    256         for (; __first != __last && __cur != end(); ++__cur, ++__first)
    257           *__cur = *__first;
    258         if (__first == __last)
    259           _M_erase_at_end(__cur);
    260         else
    261           insert(end(), __first, __last);
    262       }
    263 
    264   template <typename _Tp, typename _Alloc>
    265     void
    266     deque<_Tp, _Alloc>::
    267     _M_fill_insert(iterator __pos, size_type __n, const value_type& __x)
    268     {
    269       if (__pos._M_cur == this->_M_impl._M_start._M_cur)
    270 	{
    271 	  iterator __new_start = _M_reserve_elements_at_front(__n);
    272 	  __try
    273 	    {
    274 	      std::__uninitialized_fill_a(__new_start, this->_M_impl._M_start,
    275 					  __x, _M_get_Tp_allocator());
    276 	      this->_M_impl._M_start = __new_start;
    277 	    }
    278 	  __catch(...)
    279 	    {
    280 	      _M_destroy_nodes(__new_start._M_node,
    281 			       this->_M_impl._M_start._M_node);
    282 	      __throw_exception_again;
    283 	    }
    284 	}
    285       else if (__pos._M_cur == this->_M_impl._M_finish._M_cur)
    286 	{
    287 	  iterator __new_finish = _M_reserve_elements_at_back(__n);
    288 	  __try
    289 	    {
    290 	      std::__uninitialized_fill_a(this->_M_impl._M_finish,
    291 					  __new_finish, __x,
    292 					  _M_get_Tp_allocator());
    293 	      this->_M_impl._M_finish = __new_finish;
    294 	    }
    295 	  __catch(...)
    296 	    {
    297 	      _M_destroy_nodes(this->_M_impl._M_finish._M_node + 1,
    298 			       __new_finish._M_node + 1);
    299 	      __throw_exception_again;
    300 	    }
    301 	}
    302       else
    303         _M_insert_aux(__pos, __n, __x);
    304     }
    305 
    306 #ifdef __GXX_EXPERIMENTAL_CXX0X__
    307   template <typename _Tp, typename _Alloc>
    308     void
    309     deque<_Tp, _Alloc>::
    310     _M_default_append(size_type __n)
    311     {
    312       if (__n)
    313 	{
    314 	  iterator __new_finish = _M_reserve_elements_at_back(__n);
    315 	  __try
    316 	    {
    317 	      std::__uninitialized_default_a(this->_M_impl._M_finish,
    318 					     __new_finish,
    319 					     _M_get_Tp_allocator());
    320 	      this->_M_impl._M_finish = __new_finish;
    321 	    }
    322 	  __catch(...)
    323 	    {
    324 	      _M_destroy_nodes(this->_M_impl._M_finish._M_node + 1,
    325 			       __new_finish._M_node + 1);
    326 	      __throw_exception_again;
    327 	    }
    328 	}
    329     }
    330 
    331   template <typename _Tp, typename _Alloc>
    332     bool
    333     deque<_Tp, _Alloc>::
    334     _M_shrink_to_fit()
    335     {
    336       const difference_type __front_capacity
    337 	= (this->_M_impl._M_start._M_cur - this->_M_impl._M_start._M_first);
    338       if (__front_capacity == 0)
    339 	return false;
    340 
    341       const difference_type __back_capacity
    342 	= (this->_M_impl._M_finish._M_last - this->_M_impl._M_finish._M_cur);
    343       if (__front_capacity + __back_capacity < _S_buffer_size())
    344 	return false;
    345 
    346       return std::__shrink_to_fit_aux<deque>::_S_do_it(*this);
    347     }
    348 #endif
    349 
    350   template <typename _Tp, typename _Alloc>
    351     void
    352     deque<_Tp, _Alloc>::
    353     _M_fill_initialize(const value_type& __value)
    354     {
    355       _Map_pointer __cur;
    356       __try
    357         {
    358           for (__cur = this->_M_impl._M_start._M_node;
    359 	       __cur < this->_M_impl._M_finish._M_node;
    360 	       ++__cur)
    361             std::__uninitialized_fill_a(*__cur, *__cur + _S_buffer_size(),
    362 					__value, _M_get_Tp_allocator());
    363           std::__uninitialized_fill_a(this->_M_impl._M_finish._M_first,
    364 				      this->_M_impl._M_finish._M_cur,
    365 				      __value, _M_get_Tp_allocator());
    366         }
    367       __catch(...)
    368         {
    369           std::_Destroy(this->_M_impl._M_start, iterator(*__cur, __cur),
    370 			_M_get_Tp_allocator());
    371           __throw_exception_again;
    372         }
    373     }
    374 
    375   template <typename _Tp, typename _Alloc>
    376     template <typename _InputIterator>
    377       void
    378       deque<_Tp, _Alloc>::
    379       _M_range_initialize(_InputIterator __first, _InputIterator __last,
    380                           std::input_iterator_tag)
    381       {
    382         this->_M_initialize_map(0);
    383         __try
    384           {
    385             for (; __first != __last; ++__first)
    386               push_back(*__first);
    387           }
    388         __catch(...)
    389           {
    390             clear();
    391             __throw_exception_again;
    392           }
    393       }
    394 
    395   template <typename _Tp, typename _Alloc>
    396     template <typename _ForwardIterator>
    397       void
    398       deque<_Tp, _Alloc>::
    399       _M_range_initialize(_ForwardIterator __first, _ForwardIterator __last,
    400                           std::forward_iterator_tag)
    401       {
    402         const size_type __n = std::distance(__first, __last);
    403         this->_M_initialize_map(__n);
    404 
    405         _Map_pointer __cur_node;
    406         __try
    407           {
    408             for (__cur_node = this->_M_impl._M_start._M_node;
    409                  __cur_node < this->_M_impl._M_finish._M_node;
    410                  ++__cur_node)
    411 	      {
    412 		_ForwardIterator __mid = __first;
    413 		std::advance(__mid, _S_buffer_size());
    414 		std::__uninitialized_copy_a(__first, __mid, *__cur_node,
    415 					    _M_get_Tp_allocator());
    416 		__first = __mid;
    417 	      }
    418             std::__uninitialized_copy_a(__first, __last,
    419 					this->_M_impl._M_finish._M_first,
    420 					_M_get_Tp_allocator());
    421           }
    422         __catch(...)
    423           {
    424             std::_Destroy(this->_M_impl._M_start,
    425 			  iterator(*__cur_node, __cur_node),
    426 			  _M_get_Tp_allocator());
    427             __throw_exception_again;
    428           }
    429       }
    430 
    431   // Called only if _M_impl._M_finish._M_cur == _M_impl._M_finish._M_last - 1.
    432   template<typename _Tp, typename _Alloc>
    433 #ifdef __GXX_EXPERIMENTAL_CXX0X__
    434     template<typename... _Args>
    435       void
    436       deque<_Tp, _Alloc>::
    437       _M_push_back_aux(_Args&&... __args)
    438 #else
    439       void
    440       deque<_Tp, _Alloc>::
    441       _M_push_back_aux(const value_type& __t)
    442 #endif
    443       {
    444 	_M_reserve_map_at_back();
    445 	*(this->_M_impl._M_finish._M_node + 1) = this->_M_allocate_node();
    446 	__try
    447 	  {
    448 #ifdef __GXX_EXPERIMENTAL_CXX0X__
    449 	    this->_M_impl.construct(this->_M_impl._M_finish._M_cur,
    450 				    std::forward<_Args>(__args)...);
    451 #else
    452 	    this->_M_impl.construct(this->_M_impl._M_finish._M_cur, __t);
    453 #endif
    454 	    this->_M_impl._M_finish._M_set_node(this->_M_impl._M_finish._M_node
    455 						+ 1);
    456 	    this->_M_impl._M_finish._M_cur = this->_M_impl._M_finish._M_first;
    457 	  }
    458 	__catch(...)
    459 	  {
    460 	    _M_deallocate_node(*(this->_M_impl._M_finish._M_node + 1));
    461 	    __throw_exception_again;
    462 	  }
    463       }
    464 
    465   // Called only if _M_impl._M_start._M_cur == _M_impl._M_start._M_first.
    466   template<typename _Tp, typename _Alloc>
    467 #ifdef __GXX_EXPERIMENTAL_CXX0X__
    468     template<typename... _Args>
    469       void
    470       deque<_Tp, _Alloc>::
    471       _M_push_front_aux(_Args&&... __args)
    472 #else
    473       void
    474       deque<_Tp, _Alloc>::
    475       _M_push_front_aux(const value_type& __t)
    476 #endif
    477       {
    478 	_M_reserve_map_at_front();
    479 	*(this->_M_impl._M_start._M_node - 1) = this->_M_allocate_node();
    480 	__try
    481 	  {
    482 	    this->_M_impl._M_start._M_set_node(this->_M_impl._M_start._M_node
    483 					       - 1);
    484 	    this->_M_impl._M_start._M_cur = this->_M_impl._M_start._M_last - 1;
    485 #ifdef __GXX_EXPERIMENTAL_CXX0X__
    486 	    this->_M_impl.construct(this->_M_impl._M_start._M_cur,
    487 				    std::forward<_Args>(__args)...);
    488 #else
    489 	    this->_M_impl.construct(this->_M_impl._M_start._M_cur, __t);
    490 #endif
    491 	  }
    492 	__catch(...)
    493 	  {
    494 	    ++this->_M_impl._M_start;
    495 	    _M_deallocate_node(*(this->_M_impl._M_start._M_node - 1));
    496 	    __throw_exception_again;
    497 	  }
    498       }
    499 
    500   // Called only if _M_impl._M_finish._M_cur == _M_impl._M_finish._M_first.
    501   template <typename _Tp, typename _Alloc>
    502     void deque<_Tp, _Alloc>::
    503     _M_pop_back_aux()
    504     {
    505       _M_deallocate_node(this->_M_impl._M_finish._M_first);
    506       this->_M_impl._M_finish._M_set_node(this->_M_impl._M_finish._M_node - 1);
    507       this->_M_impl._M_finish._M_cur = this->_M_impl._M_finish._M_last - 1;
    508       this->_M_impl.destroy(this->_M_impl._M_finish._M_cur);
    509     }
    510 
    511   // Called only if _M_impl._M_start._M_cur == _M_impl._M_start._M_last - 1.
    512   // Note that if the deque has at least one element (a precondition for this
    513   // member function), and if
    514   //   _M_impl._M_start._M_cur == _M_impl._M_start._M_last,
    515   // then the deque must have at least two nodes.
    516   template <typename _Tp, typename _Alloc>
    517     void deque<_Tp, _Alloc>::
    518     _M_pop_front_aux()
    519     {
    520       this->_M_impl.destroy(this->_M_impl._M_start._M_cur);
    521       _M_deallocate_node(this->_M_impl._M_start._M_first);
    522       this->_M_impl._M_start._M_set_node(this->_M_impl._M_start._M_node + 1);
    523       this->_M_impl._M_start._M_cur = this->_M_impl._M_start._M_first;
    524     }
    525 
    526   template <typename _Tp, typename _Alloc>
    527     template <typename _InputIterator>
    528       void
    529       deque<_Tp, _Alloc>::
    530       _M_range_insert_aux(iterator __pos,
    531                           _InputIterator __first, _InputIterator __last,
    532                           std::input_iterator_tag)
    533       { std::copy(__first, __last, std::inserter(*this, __pos)); }
    534 
    535   template <typename _Tp, typename _Alloc>
    536     template <typename _ForwardIterator>
    537       void
    538       deque<_Tp, _Alloc>::
    539       _M_range_insert_aux(iterator __pos,
    540                           _ForwardIterator __first, _ForwardIterator __last,
    541                           std::forward_iterator_tag)
    542       {
    543         const size_type __n = std::distance(__first, __last);
    544         if (__pos._M_cur == this->_M_impl._M_start._M_cur)
    545 	  {
    546 	    iterator __new_start = _M_reserve_elements_at_front(__n);
    547 	    __try
    548 	      {
    549 		std::__uninitialized_copy_a(__first, __last, __new_start,
    550 					    _M_get_Tp_allocator());
    551 		this->_M_impl._M_start = __new_start;
    552 	      }
    553 	    __catch(...)
    554 	      {
    555 		_M_destroy_nodes(__new_start._M_node,
    556 				 this->_M_impl._M_start._M_node);
    557 		__throw_exception_again;
    558 	      }
    559 	  }
    560         else if (__pos._M_cur == this->_M_impl._M_finish._M_cur)
    561 	  {
    562 	    iterator __new_finish = _M_reserve_elements_at_back(__n);
    563 	    __try
    564 	      {
    565 		std::__uninitialized_copy_a(__first, __last,
    566 					    this->_M_impl._M_finish,
    567 					    _M_get_Tp_allocator());
    568 		this->_M_impl._M_finish = __new_finish;
    569 	      }
    570 	    __catch(...)
    571 	      {
    572 		_M_destroy_nodes(this->_M_impl._M_finish._M_node + 1,
    573 				 __new_finish._M_node + 1);
    574 		__throw_exception_again;
    575 	      }
    576 	  }
    577         else
    578           _M_insert_aux(__pos, __first, __last, __n);
    579       }
    580 
    581   template<typename _Tp, typename _Alloc>
    582 #ifdef __GXX_EXPERIMENTAL_CXX0X__
    583     template<typename... _Args>
    584       typename deque<_Tp, _Alloc>::iterator
    585       deque<_Tp, _Alloc>::
    586       _M_insert_aux(iterator __pos, _Args&&... __args)
    587       {
    588 	value_type __x_copy(std::forward<_Args>(__args)...); // XXX copy
    589 #else
    590     typename deque<_Tp, _Alloc>::iterator
    591       deque<_Tp, _Alloc>::
    592       _M_insert_aux(iterator __pos, const value_type& __x)
    593       {
    594 	value_type __x_copy = __x; // XXX copy
    595 #endif
    596 	difference_type __index = __pos - this->_M_impl._M_start;
    597 	if (static_cast<size_type>(__index) < size() / 2)
    598 	  {
    599 	    push_front(_GLIBCXX_MOVE(front()));
    600 	    iterator __front1 = this->_M_impl._M_start;
    601 	    ++__front1;
    602 	    iterator __front2 = __front1;
    603 	    ++__front2;
    604 	    __pos = this->_M_impl._M_start + __index;
    605 	    iterator __pos1 = __pos;
    606 	    ++__pos1;
    607 	    _GLIBCXX_MOVE3(__front2, __pos1, __front1);
    608 	  }
    609 	else
    610 	  {
    611 	    push_back(_GLIBCXX_MOVE(back()));
    612 	    iterator __back1 = this->_M_impl._M_finish;
    613 	    --__back1;
    614 	    iterator __back2 = __back1;
    615 	    --__back2;
    616 	    __pos = this->_M_impl._M_start + __index;
    617 	    _GLIBCXX_MOVE_BACKWARD3(__pos, __back2, __back1);
    618 	  }
    619 	*__pos = _GLIBCXX_MOVE(__x_copy);
    620 	return __pos;
    621       }
    622 
    623   template <typename _Tp, typename _Alloc>
    624     void
    625     deque<_Tp, _Alloc>::
    626     _M_insert_aux(iterator __pos, size_type __n, const value_type& __x)
    627     {
    628       const difference_type __elems_before = __pos - this->_M_impl._M_start;
    629       const size_type __length = this->size();
    630       value_type __x_copy = __x;
    631       if (__elems_before < difference_type(__length / 2))
    632 	{
    633 	  iterator __new_start = _M_reserve_elements_at_front(__n);
    634 	  iterator __old_start = this->_M_impl._M_start;
    635 	  __pos = this->_M_impl._M_start + __elems_before;
    636 	  __try
    637 	    {
    638 	      if (__elems_before >= difference_type(__n))
    639 		{
    640 		  iterator __start_n = (this->_M_impl._M_start
    641 					+ difference_type(__n));
    642 		  std::__uninitialized_move_a(this->_M_impl._M_start,
    643 					      __start_n, __new_start,
    644 					      _M_get_Tp_allocator());
    645 		  this->_M_impl._M_start = __new_start;
    646 		  _GLIBCXX_MOVE3(__start_n, __pos, __old_start);
    647 		  std::fill(__pos - difference_type(__n), __pos, __x_copy);
    648 		}
    649 	      else
    650 		{
    651 		  std::__uninitialized_move_fill(this->_M_impl._M_start,
    652 						 __pos, __new_start,
    653 						 this->_M_impl._M_start,
    654 						 __x_copy,
    655 						 _M_get_Tp_allocator());
    656 		  this->_M_impl._M_start = __new_start;
    657 		  std::fill(__old_start, __pos, __x_copy);
    658 		}
    659 	    }
    660 	  __catch(...)
    661 	    {
    662 	      _M_destroy_nodes(__new_start._M_node,
    663 			       this->_M_impl._M_start._M_node);
    664 	      __throw_exception_again;
    665 	    }
    666 	}
    667       else
    668 	{
    669 	  iterator __new_finish = _M_reserve_elements_at_back(__n);
    670 	  iterator __old_finish = this->_M_impl._M_finish;
    671 	  const difference_type __elems_after =
    672 	    difference_type(__length) - __elems_before;
    673 	  __pos = this->_M_impl._M_finish - __elems_after;
    674 	  __try
    675 	    {
    676 	      if (__elems_after > difference_type(__n))
    677 		{
    678 		  iterator __finish_n = (this->_M_impl._M_finish
    679 					 - difference_type(__n));
    680 		  std::__uninitialized_move_a(__finish_n,
    681 					      this->_M_impl._M_finish,
    682 					      this->_M_impl._M_finish,
    683 					      _M_get_Tp_allocator());
    684 		  this->_M_impl._M_finish = __new_finish;
    685 		  _GLIBCXX_MOVE_BACKWARD3(__pos, __finish_n, __old_finish);
    686 		  std::fill(__pos, __pos + difference_type(__n), __x_copy);
    687 		}
    688 	      else
    689 		{
    690 		  std::__uninitialized_fill_move(this->_M_impl._M_finish,
    691 						 __pos + difference_type(__n),
    692 						 __x_copy, __pos,
    693 						 this->_M_impl._M_finish,
    694 						 _M_get_Tp_allocator());
    695 		  this->_M_impl._M_finish = __new_finish;
    696 		  std::fill(__pos, __old_finish, __x_copy);
    697 		}
    698 	    }
    699 	  __catch(...)
    700 	    {
    701 	      _M_destroy_nodes(this->_M_impl._M_finish._M_node + 1,
    702 			       __new_finish._M_node + 1);
    703 	      __throw_exception_again;
    704 	    }
    705 	}
    706     }
    707 
    708   template <typename _Tp, typename _Alloc>
    709     template <typename _ForwardIterator>
    710       void
    711       deque<_Tp, _Alloc>::
    712       _M_insert_aux(iterator __pos,
    713                     _ForwardIterator __first, _ForwardIterator __last,
    714                     size_type __n)
    715       {
    716         const difference_type __elemsbefore = __pos - this->_M_impl._M_start;
    717         const size_type __length = size();
    718         if (static_cast<size_type>(__elemsbefore) < __length / 2)
    719 	  {
    720 	    iterator __new_start = _M_reserve_elements_at_front(__n);
    721 	    iterator __old_start = this->_M_impl._M_start;
    722 	    __pos = this->_M_impl._M_start + __elemsbefore;
    723 	    __try
    724 	      {
    725 		if (__elemsbefore >= difference_type(__n))
    726 		  {
    727 		    iterator __start_n = (this->_M_impl._M_start
    728 					  + difference_type(__n));
    729 		    std::__uninitialized_move_a(this->_M_impl._M_start,
    730 						__start_n, __new_start,
    731 						_M_get_Tp_allocator());
    732 		    this->_M_impl._M_start = __new_start;
    733 		    _GLIBCXX_MOVE3(__start_n, __pos, __old_start);
    734 		    std::copy(__first, __last, __pos - difference_type(__n));
    735 		  }
    736 		else
    737 		  {
    738 		    _ForwardIterator __mid = __first;
    739 		    std::advance(__mid, difference_type(__n) - __elemsbefore);
    740 		    std::__uninitialized_move_copy(this->_M_impl._M_start,
    741 						   __pos, __first, __mid,
    742 						   __new_start,
    743 						   _M_get_Tp_allocator());
    744 		    this->_M_impl._M_start = __new_start;
    745 		    std::copy(__mid, __last, __old_start);
    746 		  }
    747 	      }
    748 	    __catch(...)
    749 	      {
    750 		_M_destroy_nodes(__new_start._M_node,
    751 				 this->_M_impl._M_start._M_node);
    752 		__throw_exception_again;
    753 	      }
    754 	  }
    755         else
    756         {
    757           iterator __new_finish = _M_reserve_elements_at_back(__n);
    758           iterator __old_finish = this->_M_impl._M_finish;
    759           const difference_type __elemsafter =
    760             difference_type(__length) - __elemsbefore;
    761           __pos = this->_M_impl._M_finish - __elemsafter;
    762           __try
    763             {
    764               if (__elemsafter > difference_type(__n))
    765 		{
    766 		  iterator __finish_n = (this->_M_impl._M_finish
    767 					 - difference_type(__n));
    768 		  std::__uninitialized_move_a(__finish_n,
    769 					      this->_M_impl._M_finish,
    770 					      this->_M_impl._M_finish,
    771 					      _M_get_Tp_allocator());
    772 		  this->_M_impl._M_finish = __new_finish;
    773 		  _GLIBCXX_MOVE_BACKWARD3(__pos, __finish_n, __old_finish);
    774 		  std::copy(__first, __last, __pos);
    775 		}
    776               else
    777 		{
    778 		  _ForwardIterator __mid = __first;
    779 		  std::advance(__mid, __elemsafter);
    780 		  std::__uninitialized_copy_move(__mid, __last, __pos,
    781 						 this->_M_impl._M_finish,
    782 						 this->_M_impl._M_finish,
    783 						 _M_get_Tp_allocator());
    784 		  this->_M_impl._M_finish = __new_finish;
    785 		  std::copy(__first, __mid, __pos);
    786 		}
    787             }
    788           __catch(...)
    789             {
    790               _M_destroy_nodes(this->_M_impl._M_finish._M_node + 1,
    791 			       __new_finish._M_node + 1);
    792               __throw_exception_again;
    793             }
    794         }
    795       }
    796 
    797    template<typename _Tp, typename _Alloc>
    798      void
    799      deque<_Tp, _Alloc>::
    800      _M_destroy_data_aux(iterator __first, iterator __last)
    801      {
    802        for (_Map_pointer __node = __first._M_node + 1;
    803 	    __node < __last._M_node; ++__node)
    804 	 std::_Destroy(*__node, *__node + _S_buffer_size(),
    805 		       _M_get_Tp_allocator());
    806 
    807        if (__first._M_node != __last._M_node)
    808 	 {
    809 	   std::_Destroy(__first._M_cur, __first._M_last,
    810 			 _M_get_Tp_allocator());
    811 	   std::_Destroy(__last._M_first, __last._M_cur,
    812 			 _M_get_Tp_allocator());
    813 	 }
    814        else
    815 	 std::_Destroy(__first._M_cur, __last._M_cur,
    816 		       _M_get_Tp_allocator());
    817      }
    818 
    819   template <typename _Tp, typename _Alloc>
    820     void
    821     deque<_Tp, _Alloc>::
    822     _M_new_elements_at_front(size_type __new_elems)
    823     {
    824       if (this->max_size() - this->size() < __new_elems)
    825 	__throw_length_error(__N("deque::_M_new_elements_at_front"));
    826 
    827       const size_type __new_nodes = ((__new_elems + _S_buffer_size() - 1)
    828 				     / _S_buffer_size());
    829       _M_reserve_map_at_front(__new_nodes);
    830       size_type __i;
    831       __try
    832         {
    833           for (__i = 1; __i <= __new_nodes; ++__i)
    834             *(this->_M_impl._M_start._M_node - __i) = this->_M_allocate_node();
    835         }
    836       __catch(...)
    837         {
    838           for (size_type __j = 1; __j < __i; ++__j)
    839             _M_deallocate_node(*(this->_M_impl._M_start._M_node - __j));
    840           __throw_exception_again;
    841         }
    842     }
    843 
    844   template <typename _Tp, typename _Alloc>
    845     void
    846     deque<_Tp, _Alloc>::
    847     _M_new_elements_at_back(size_type __new_elems)
    848     {
    849       if (this->max_size() - this->size() < __new_elems)
    850 	__throw_length_error(__N("deque::_M_new_elements_at_back"));
    851 
    852       const size_type __new_nodes = ((__new_elems + _S_buffer_size() - 1)
    853 				     / _S_buffer_size());
    854       _M_reserve_map_at_back(__new_nodes);
    855       size_type __i;
    856       __try
    857         {
    858           for (__i = 1; __i <= __new_nodes; ++__i)
    859             *(this->_M_impl._M_finish._M_node + __i) = this->_M_allocate_node();
    860         }
    861       __catch(...)
    862         {
    863           for (size_type __j = 1; __j < __i; ++__j)
    864             _M_deallocate_node(*(this->_M_impl._M_finish._M_node + __j));
    865           __throw_exception_again;
    866         }
    867     }
    868 
    869   template <typename _Tp, typename _Alloc>
    870     void
    871     deque<_Tp, _Alloc>::
    872     _M_reallocate_map(size_type __nodes_to_add, bool __add_at_front)
    873     {
    874       const size_type __old_num_nodes
    875 	= this->_M_impl._M_finish._M_node - this->_M_impl._M_start._M_node + 1;
    876       const size_type __new_num_nodes = __old_num_nodes + __nodes_to_add;
    877 
    878       _Map_pointer __new_nstart;
    879       if (this->_M_impl._M_map_size > 2 * __new_num_nodes)
    880 	{
    881 	  __new_nstart = this->_M_impl._M_map + (this->_M_impl._M_map_size
    882 					 - __new_num_nodes) / 2
    883 	                 + (__add_at_front ? __nodes_to_add : 0);
    884 	  if (__new_nstart < this->_M_impl._M_start._M_node)
    885 	    std::copy(this->_M_impl._M_start._M_node,
    886 		      this->_M_impl._M_finish._M_node + 1,
    887 		      __new_nstart);
    888 	  else
    889 	    std::copy_backward(this->_M_impl._M_start._M_node,
    890 			       this->_M_impl._M_finish._M_node + 1,
    891 			       __new_nstart + __old_num_nodes);
    892 	}
    893       else
    894 	{
    895 	  size_type __new_map_size = this->_M_impl._M_map_size
    896 	                             + std::max(this->_M_impl._M_map_size,
    897 						__nodes_to_add) + 2;
    898 
    899 	  _Map_pointer __new_map = this->_M_allocate_map(__new_map_size);
    900 	  __new_nstart = __new_map + (__new_map_size - __new_num_nodes) / 2
    901 	                 + (__add_at_front ? __nodes_to_add : 0);
    902 	  std::copy(this->_M_impl._M_start._M_node,
    903 		    this->_M_impl._M_finish._M_node + 1,
    904 		    __new_nstart);
    905 	  _M_deallocate_map(this->_M_impl._M_map, this->_M_impl._M_map_size);
    906 
    907 	  this->_M_impl._M_map = __new_map;
    908 	  this->_M_impl._M_map_size = __new_map_size;
    909 	}
    910 
    911       this->_M_impl._M_start._M_set_node(__new_nstart);
    912       this->_M_impl._M_finish._M_set_node(__new_nstart + __old_num_nodes - 1);
    913     }
    914 
    915   // Overload for deque::iterators, exploiting the "segmented-iterator
    916   // optimization".
    917   template<typename _Tp>
    918     void
    919     fill(const _Deque_iterator<_Tp, _Tp&, _Tp*>& __first,
    920 	 const _Deque_iterator<_Tp, _Tp&, _Tp*>& __last, const _Tp& __value)
    921     {
    922       typedef typename _Deque_iterator<_Tp, _Tp&, _Tp*>::_Self _Self;
    923 
    924       for (typename _Self::_Map_pointer __node = __first._M_node + 1;
    925            __node < __last._M_node; ++__node)
    926 	std::fill(*__node, *__node + _Self::_S_buffer_size(), __value);
    927 
    928       if (__first._M_node != __last._M_node)
    929 	{
    930 	  std::fill(__first._M_cur, __first._M_last, __value);
    931 	  std::fill(__last._M_first, __last._M_cur, __value);
    932 	}
    933       else
    934 	std::fill(__first._M_cur, __last._M_cur, __value);
    935     }
    936 
    937   template<typename _Tp>
    938     _Deque_iterator<_Tp, _Tp&, _Tp*>
    939     copy(_Deque_iterator<_Tp, const _Tp&, const _Tp*> __first,
    940 	 _Deque_iterator<_Tp, const _Tp&, const _Tp*> __last,
    941 	 _Deque_iterator<_Tp, _Tp&, _Tp*> __result)
    942     {
    943       typedef typename _Deque_iterator<_Tp, _Tp&, _Tp*>::_Self _Self;
    944       typedef typename _Self::difference_type difference_type;
    945 
    946       difference_type __len = __last - __first;
    947       while (__len > 0)
    948 	{
    949 	  const difference_type __clen
    950 	    = std::min(__len, std::min(__first._M_last - __first._M_cur,
    951 				       __result._M_last - __result._M_cur));
    952 	  std::copy(__first._M_cur, __first._M_cur + __clen, __result._M_cur);
    953 	  __first += __clen;
    954 	  __result += __clen;
    955 	  __len -= __clen;
    956 	}
    957       return __result;
    958     }
    959 
    960   template<typename _Tp>
    961     _Deque_iterator<_Tp, _Tp&, _Tp*>
    962     copy_backward(_Deque_iterator<_Tp, const _Tp&, const _Tp*> __first,
    963 		  _Deque_iterator<_Tp, const _Tp&, const _Tp*> __last,
    964 		  _Deque_iterator<_Tp, _Tp&, _Tp*> __result)
    965     {
    966       typedef typename _Deque_iterator<_Tp, _Tp&, _Tp*>::_Self _Self;
    967       typedef typename _Self::difference_type difference_type;
    968 
    969       difference_type __len = __last - __first;
    970       while (__len > 0)
    971 	{
    972 	  difference_type __llen = __last._M_cur - __last._M_first;
    973 	  _Tp* __lend = __last._M_cur;
    974 
    975 	  difference_type __rlen = __result._M_cur - __result._M_first;
    976 	  _Tp* __rend = __result._M_cur;
    977 
    978 	  if (!__llen)
    979 	    {
    980 	      __llen = _Self::_S_buffer_size();
    981 	      __lend = *(__last._M_node - 1) + __llen;
    982 	    }
    983 	  if (!__rlen)
    984 	    {
    985 	      __rlen = _Self::_S_buffer_size();
    986 	      __rend = *(__result._M_node - 1) + __rlen;
    987 	    }
    988 
    989 	  const difference_type __clen = std::min(__len,
    990 						  std::min(__llen, __rlen));
    991 	  std::copy_backward(__lend - __clen, __lend, __rend);
    992 	  __last -= __clen;
    993 	  __result -= __clen;
    994 	  __len -= __clen;
    995 	}
    996       return __result;
    997     }
    998 
    999 #ifdef __GXX_EXPERIMENTAL_CXX0X__
   1000   template<typename _Tp>
   1001     _Deque_iterator<_Tp, _Tp&, _Tp*>
   1002     move(_Deque_iterator<_Tp, const _Tp&, const _Tp*> __first,
   1003 	 _Deque_iterator<_Tp, const _Tp&, const _Tp*> __last,
   1004 	 _Deque_iterator<_Tp, _Tp&, _Tp*> __result)
   1005     {
   1006       typedef typename _Deque_iterator<_Tp, _Tp&, _Tp*>::_Self _Self;
   1007       typedef typename _Self::difference_type difference_type;
   1008 
   1009       difference_type __len = __last - __first;
   1010       while (__len > 0)
   1011 	{
   1012 	  const difference_type __clen
   1013 	    = std::min(__len, std::min(__first._M_last - __first._M_cur,
   1014 				       __result._M_last - __result._M_cur));
   1015 	  std::move(__first._M_cur, __first._M_cur + __clen, __result._M_cur);
   1016 	  __first += __clen;
   1017 	  __result += __clen;
   1018 	  __len -= __clen;
   1019 	}
   1020       return __result;
   1021     }
   1022 
   1023   template<typename _Tp>
   1024     _Deque_iterator<_Tp, _Tp&, _Tp*>
   1025     move_backward(_Deque_iterator<_Tp, const _Tp&, const _Tp*> __first,
   1026 		  _Deque_iterator<_Tp, const _Tp&, const _Tp*> __last,
   1027 		  _Deque_iterator<_Tp, _Tp&, _Tp*> __result)
   1028     {
   1029       typedef typename _Deque_iterator<_Tp, _Tp&, _Tp*>::_Self _Self;
   1030       typedef typename _Self::difference_type difference_type;
   1031 
   1032       difference_type __len = __last - __first;
   1033       while (__len > 0)
   1034 	{
   1035 	  difference_type __llen = __last._M_cur - __last._M_first;
   1036 	  _Tp* __lend = __last._M_cur;
   1037 
   1038 	  difference_type __rlen = __result._M_cur - __result._M_first;
   1039 	  _Tp* __rend = __result._M_cur;
   1040 
   1041 	  if (!__llen)
   1042 	    {
   1043 	      __llen = _Self::_S_buffer_size();
   1044 	      __lend = *(__last._M_node - 1) + __llen;
   1045 	    }
   1046 	  if (!__rlen)
   1047 	    {
   1048 	      __rlen = _Self::_S_buffer_size();
   1049 	      __rend = *(__result._M_node - 1) + __rlen;
   1050 	    }
   1051 
   1052 	  const difference_type __clen = std::min(__len,
   1053 						  std::min(__llen, __rlen));
   1054 	  std::move_backward(__lend - __clen, __lend, __rend);
   1055 	  __last -= __clen;
   1056 	  __result -= __clen;
   1057 	  __len -= __clen;
   1058 	}
   1059       return __result;
   1060     }
   1061 #endif
   1062 
   1063 _GLIBCXX_END_NAMESPACE_CONTAINER
   1064 } // namespace std
   1065 
   1066 #endif
   1067