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