1// Vector implementation (out of line) -*- C++ -*-
2
3// Copyright (C) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010,
4// 2011 Free Software Foundation, Inc.
5//
6// This file is part of the GNU ISO C++ Library.  This library is free
7// software; you can redistribute it and/or modify it under the
8// terms of the GNU General Public License as published by the
9// Free Software Foundation; either version 3, or (at your option)
10// any later version.
11
12// This library is distributed in the hope that it will be useful,
13// but WITHOUT ANY WARRANTY; without even the implied warranty of
14// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15// GNU General Public License for more details.
16
17// Under Section 7 of GPL version 3, you are granted additional
18// permissions described in the GCC Runtime Library Exception, version
19// 3.1, as published by the Free Software Foundation.
20
21// You should have received a copy of the GNU General Public License and
22// a copy of the GCC Runtime Library Exception along with this program;
23// see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
24// <http://www.gnu.org/licenses/>.
25
26/*
27 *
28 * Copyright (c) 1994
29 * Hewlett-Packard Company
30 *
31 * Permission to use, copy, modify, distribute and sell this software
32 * and its documentation for any purpose is hereby granted without fee,
33 * provided that the above copyright notice appear in all copies and
34 * that both that copyright notice and this permission notice appear
35 * in supporting documentation.  Hewlett-Packard Company makes no
36 * representations about the suitability of this software for any
37 * purpose.  It is provided "as is" without express or implied warranty.
38 *
39 *
40 * Copyright (c) 1996
41 * Silicon Graphics Computer Systems, Inc.
42 *
43 * Permission to use, copy, modify, distribute and sell this software
44 * and its documentation for any purpose is hereby granted without fee,
45 * provided that the above copyright notice appear in all copies and
46 * that both that copyright notice and this permission notice appear
47 * in supporting documentation.  Silicon Graphics makes no
48 * representations about the suitability of this  software for any
49 * purpose.  It is provided "as is" without express or implied warranty.
50 */
51
52/** @file bits/vector.tcc
53 *  This is an internal header file, included by other library headers.
54 *  Do not attempt to use it directly. @headername{vector}
55 */
56
57#ifndef _VECTOR_TCC
58#define _VECTOR_TCC 1
59
60namespace std _GLIBCXX_VISIBILITY(default)
61{
62_GLIBCXX_BEGIN_NAMESPACE_CONTAINER
63
64  template<typename _Tp, typename _Alloc>
65    void
66    vector<_Tp, _Alloc>::
67    reserve(size_type __n)
68    {
69      if (__n > this->max_size())
70	__throw_length_error(__N("vector::reserve"));
71      if (this->capacity() < __n)
72	{
73	  const size_type __old_size = size();
74	  pointer __tmp = _M_allocate_and_copy(__n,
75	    _GLIBCXX_MAKE_MOVE_IF_NOEXCEPT_ITERATOR(this->_M_impl._M_start),
76	    _GLIBCXX_MAKE_MOVE_IF_NOEXCEPT_ITERATOR(this->_M_impl._M_finish));
77	  std::_Destroy(this->_M_impl._M_start, this->_M_impl._M_finish,
78			_M_get_Tp_allocator());
79	  _M_deallocate(this->_M_impl._M_start,
80			this->_M_impl._M_end_of_storage
81			- this->_M_impl._M_start);
82	  this->_M_impl._M_start = __tmp;
83	  this->_M_impl._M_finish = __tmp + __old_size;
84	  this->_M_impl._M_end_of_storage = this->_M_impl._M_start + __n;
85	}
86    }
87
88#ifdef __GXX_EXPERIMENTAL_CXX0X__
89  template<typename _Tp, typename _Alloc>
90    template<typename... _Args>
91      void
92      vector<_Tp, _Alloc>::
93      emplace_back(_Args&&... __args)
94      {
95	if (this->_M_impl._M_finish != this->_M_impl._M_end_of_storage)
96	  {
97	    _Alloc_traits::construct(this->_M_impl, this->_M_impl._M_finish,
98				     std::forward<_Args>(__args)...);
99	    ++this->_M_impl._M_finish;
100	  }
101	else
102	  _M_emplace_back_aux(std::forward<_Args>(__args)...);
103      }
104#endif
105
106  template<typename _Tp, typename _Alloc>
107    typename vector<_Tp, _Alloc>::iterator
108    vector<_Tp, _Alloc>::
109    insert(iterator __position, const value_type& __x)
110    {
111      const size_type __n = __position - begin();
112      if (this->_M_impl._M_finish != this->_M_impl._M_end_of_storage
113	  && __position == end())
114	{
115	  _Alloc_traits::construct(this->_M_impl, this->_M_impl._M_finish, __x);
116	  ++this->_M_impl._M_finish;
117	}
118      else
119	{
120#ifdef __GXX_EXPERIMENTAL_CXX0X__
121	  if (this->_M_impl._M_finish != this->_M_impl._M_end_of_storage)
122	    {
123	      _Tp __x_copy = __x;
124	      _M_insert_aux(__position, std::move(__x_copy));
125	    }
126	  else
127#endif
128	    _M_insert_aux(__position, __x);
129	}
130      return iterator(this->_M_impl._M_start + __n);
131    }
132
133  template<typename _Tp, typename _Alloc>
134    typename vector<_Tp, _Alloc>::iterator
135    vector<_Tp, _Alloc>::
136    erase(iterator __position)
137    {
138      if (__position + 1 != end())
139	_GLIBCXX_MOVE3(__position + 1, end(), __position);
140      --this->_M_impl._M_finish;
141      _Alloc_traits::destroy(this->_M_impl, this->_M_impl._M_finish);
142      return __position;
143    }
144
145  template<typename _Tp, typename _Alloc>
146    typename vector<_Tp, _Alloc>::iterator
147    vector<_Tp, _Alloc>::
148    erase(iterator __first, iterator __last)
149    {
150      if (__first != __last)
151	{
152	  if (__last != end())
153	    _GLIBCXX_MOVE3(__last, end(), __first);
154	  _M_erase_at_end(__first.base() + (end() - __last));
155	}
156      return __first;
157    }
158
159  template<typename _Tp, typename _Alloc>
160    vector<_Tp, _Alloc>&
161    vector<_Tp, _Alloc>::
162    operator=(const vector<_Tp, _Alloc>& __x)
163    {
164      if (&__x != this)
165	{
166#ifdef __GXX_EXPERIMENTAL_CXX0X__
167	  if (_Alloc_traits::_S_propagate_on_copy_assign())
168	    {
169	      if (!_Alloc_traits::_S_always_equal()
170	          && _M_get_Tp_allocator() != __x._M_get_Tp_allocator())
171	        {
172		  // replacement allocator cannot free existing storage
173		  this->clear();
174		  _M_deallocate(this->_M_impl._M_start,
175				this->_M_impl._M_end_of_storage
176				- this->_M_impl._M_start);
177		}
178	      std::__alloc_on_copy(_M_get_Tp_allocator(),
179				   __x._M_get_Tp_allocator());
180	    }
181#endif
182	  const size_type __xlen = __x.size();
183	  if (__xlen > capacity())
184	    {
185	      pointer __tmp = _M_allocate_and_copy(__xlen, __x.begin(),
186						   __x.end());
187	      std::_Destroy(this->_M_impl._M_start, this->_M_impl._M_finish,
188			    _M_get_Tp_allocator());
189	      _M_deallocate(this->_M_impl._M_start,
190			    this->_M_impl._M_end_of_storage
191			    - this->_M_impl._M_start);
192	      this->_M_impl._M_start = __tmp;
193	      this->_M_impl._M_end_of_storage = this->_M_impl._M_start + __xlen;
194	    }
195	  else if (size() >= __xlen)
196	    {
197	      std::_Destroy(std::copy(__x.begin(), __x.end(), begin()),
198			    end(), _M_get_Tp_allocator());
199	    }
200	  else
201	    {
202	      std::copy(__x._M_impl._M_start, __x._M_impl._M_start + size(),
203			this->_M_impl._M_start);
204	      std::__uninitialized_copy_a(__x._M_impl._M_start + size(),
205					  __x._M_impl._M_finish,
206					  this->_M_impl._M_finish,
207					  _M_get_Tp_allocator());
208	    }
209	  this->_M_impl._M_finish = this->_M_impl._M_start + __xlen;
210	}
211      return *this;
212    }
213
214  template<typename _Tp, typename _Alloc>
215    void
216    vector<_Tp, _Alloc>::
217    _M_fill_assign(size_t __n, const value_type& __val)
218    {
219      if (__n > capacity())
220	{
221	  vector __tmp(__n, __val, _M_get_Tp_allocator());
222	  __tmp.swap(*this);
223	}
224      else if (__n > size())
225	{
226	  std::fill(begin(), end(), __val);
227	  std::__uninitialized_fill_n_a(this->_M_impl._M_finish,
228					__n - size(), __val,
229					_M_get_Tp_allocator());
230	  this->_M_impl._M_finish += __n - size();
231	}
232      else
233        _M_erase_at_end(std::fill_n(this->_M_impl._M_start, __n, __val));
234    }
235
236  template<typename _Tp, typename _Alloc>
237    template<typename _InputIterator>
238      void
239      vector<_Tp, _Alloc>::
240      _M_assign_aux(_InputIterator __first, _InputIterator __last,
241		    std::input_iterator_tag)
242      {
243	pointer __cur(this->_M_impl._M_start);
244	for (; __first != __last && __cur != this->_M_impl._M_finish;
245	     ++__cur, ++__first)
246	  *__cur = *__first;
247	if (__first == __last)
248	  _M_erase_at_end(__cur);
249	else
250	  insert(end(), __first, __last);
251      }
252
253  template<typename _Tp, typename _Alloc>
254    template<typename _ForwardIterator>
255      void
256      vector<_Tp, _Alloc>::
257      _M_assign_aux(_ForwardIterator __first, _ForwardIterator __last,
258		    std::forward_iterator_tag)
259      {
260	const size_type __len = std::distance(__first, __last);
261
262	if (__len > capacity())
263	  {
264	    pointer __tmp(_M_allocate_and_copy(__len, __first, __last));
265	    std::_Destroy(this->_M_impl._M_start, this->_M_impl._M_finish,
266			  _M_get_Tp_allocator());
267	    _M_deallocate(this->_M_impl._M_start,
268			  this->_M_impl._M_end_of_storage
269			  - this->_M_impl._M_start);
270	    this->_M_impl._M_start = __tmp;
271	    this->_M_impl._M_finish = this->_M_impl._M_start + __len;
272	    this->_M_impl._M_end_of_storage = this->_M_impl._M_finish;
273	  }
274	else if (size() >= __len)
275	  _M_erase_at_end(std::copy(__first, __last, this->_M_impl._M_start));
276	else
277	  {
278	    _ForwardIterator __mid = __first;
279	    std::advance(__mid, size());
280	    std::copy(__first, __mid, this->_M_impl._M_start);
281	    this->_M_impl._M_finish =
282	      std::__uninitialized_copy_a(__mid, __last,
283					  this->_M_impl._M_finish,
284					  _M_get_Tp_allocator());
285	  }
286      }
287
288#ifdef __GXX_EXPERIMENTAL_CXX0X__
289  template<typename _Tp, typename _Alloc>
290    template<typename... _Args>
291      typename vector<_Tp, _Alloc>::iterator
292      vector<_Tp, _Alloc>::
293      emplace(iterator __position, _Args&&... __args)
294      {
295	const size_type __n = __position - begin();
296	if (this->_M_impl._M_finish != this->_M_impl._M_end_of_storage
297	    && __position == end())
298	  {
299	    _Alloc_traits::construct(this->_M_impl, this->_M_impl._M_finish,
300				     std::forward<_Args>(__args)...);
301	    ++this->_M_impl._M_finish;
302	  }
303	else
304	  _M_insert_aux(__position, std::forward<_Args>(__args)...);
305	return iterator(this->_M_impl._M_start + __n);
306      }
307
308  template<typename _Tp, typename _Alloc>
309    template<typename... _Args>
310      void
311      vector<_Tp, _Alloc>::
312      _M_insert_aux(iterator __position, _Args&&... __args)
313#else
314  template<typename _Tp, typename _Alloc>
315    void
316    vector<_Tp, _Alloc>::
317    _M_insert_aux(iterator __position, const _Tp& __x)
318#endif
319    {
320      if (this->_M_impl._M_finish != this->_M_impl._M_end_of_storage)
321	{
322	  _Alloc_traits::construct(this->_M_impl, this->_M_impl._M_finish,
323			           _GLIBCXX_MOVE(*(this->_M_impl._M_finish
324				                   - 1)));
325	  ++this->_M_impl._M_finish;
326#ifndef __GXX_EXPERIMENTAL_CXX0X__
327	  _Tp __x_copy = __x;
328#endif
329	  _GLIBCXX_MOVE_BACKWARD3(__position.base(),
330				  this->_M_impl._M_finish - 2,
331				  this->_M_impl._M_finish - 1);
332#ifndef __GXX_EXPERIMENTAL_CXX0X__
333	  *__position = __x_copy;
334#else
335	  *__position = _Tp(std::forward<_Args>(__args)...);
336#endif
337	}
338      else
339	{
340	  const size_type __len =
341	    _M_check_len(size_type(1), "vector::_M_insert_aux");
342	  const size_type __elems_before = __position - begin();
343	  pointer __new_start(this->_M_allocate(__len));
344	  pointer __new_finish(__new_start);
345	  __try
346	    {
347	      // The order of the three operations is dictated by the C++0x
348	      // case, where the moves could alter a new element belonging
349	      // to the existing vector.  This is an issue only for callers
350	      // taking the element by const lvalue ref (see 23.1/13).
351	      _Alloc_traits::construct(this->_M_impl,
352		                       __new_start + __elems_before,
353#ifdef __GXX_EXPERIMENTAL_CXX0X__
354				       std::forward<_Args>(__args)...);
355#else
356	                               __x);
357#endif
358	      __new_finish = 0;
359
360	      __new_finish
361		= std::__uninitialized_move_if_noexcept_a
362		(this->_M_impl._M_start, __position.base(),
363		 __new_start, _M_get_Tp_allocator());
364
365	      ++__new_finish;
366
367	      __new_finish
368		= std::__uninitialized_move_if_noexcept_a
369		(__position.base(), this->_M_impl._M_finish,
370		 __new_finish, _M_get_Tp_allocator());
371	    }
372          __catch(...)
373	    {
374	      if (!__new_finish)
375		_Alloc_traits::destroy(this->_M_impl,
376		                       __new_start + __elems_before);
377	      else
378		std::_Destroy(__new_start, __new_finish, _M_get_Tp_allocator());
379	      _M_deallocate(__new_start, __len);
380	      __throw_exception_again;
381	    }
382	  std::_Destroy(this->_M_impl._M_start, this->_M_impl._M_finish,
383			_M_get_Tp_allocator());
384	  _M_deallocate(this->_M_impl._M_start,
385			this->_M_impl._M_end_of_storage
386			- this->_M_impl._M_start);
387	  this->_M_impl._M_start = __new_start;
388	  this->_M_impl._M_finish = __new_finish;
389	  this->_M_impl._M_end_of_storage = __new_start + __len;
390	}
391    }
392
393#ifdef __GXX_EXPERIMENTAL_CXX0X__
394  template<typename _Tp, typename _Alloc>
395    template<typename... _Args>
396      void
397      vector<_Tp, _Alloc>::
398      _M_emplace_back_aux(_Args&&... __args)
399      {
400	const size_type __len =
401	  _M_check_len(size_type(1), "vector::_M_emplace_back_aux");
402	pointer __new_start(this->_M_allocate(__len));
403	pointer __new_finish(__new_start);
404	__try
405	  {
406	    _Alloc_traits::construct(this->_M_impl, __new_start + size(),
407				     std::forward<_Args>(__args)...);
408	    __new_finish = 0;
409
410	    __new_finish
411	      = std::__uninitialized_move_if_noexcept_a
412	      (this->_M_impl._M_start, this->_M_impl._M_finish,
413	       __new_start, _M_get_Tp_allocator());
414
415	    ++__new_finish;
416	  }
417	__catch(...)
418	  {
419	    if (!__new_finish)
420	      _Alloc_traits::destroy(this->_M_impl, __new_start + size());
421	    else
422	      std::_Destroy(__new_start, __new_finish, _M_get_Tp_allocator());
423	    _M_deallocate(__new_start, __len);
424	    __throw_exception_again;
425	  }
426	std::_Destroy(this->_M_impl._M_start, this->_M_impl._M_finish,
427		      _M_get_Tp_allocator());
428	_M_deallocate(this->_M_impl._M_start,
429		      this->_M_impl._M_end_of_storage
430		      - this->_M_impl._M_start);
431	this->_M_impl._M_start = __new_start;
432	this->_M_impl._M_finish = __new_finish;
433	this->_M_impl._M_end_of_storage = __new_start + __len;
434      }
435#endif
436
437  template<typename _Tp, typename _Alloc>
438    void
439    vector<_Tp, _Alloc>::
440    _M_fill_insert(iterator __position, size_type __n, const value_type& __x)
441    {
442      if (__n != 0)
443	{
444	  if (size_type(this->_M_impl._M_end_of_storage
445			- this->_M_impl._M_finish) >= __n)
446	    {
447	      value_type __x_copy = __x;
448	      const size_type __elems_after = end() - __position;
449	      pointer __old_finish(this->_M_impl._M_finish);
450	      if (__elems_after > __n)
451		{
452		  std::__uninitialized_move_a(this->_M_impl._M_finish - __n,
453					      this->_M_impl._M_finish,
454					      this->_M_impl._M_finish,
455					      _M_get_Tp_allocator());
456		  this->_M_impl._M_finish += __n;
457		  _GLIBCXX_MOVE_BACKWARD3(__position.base(),
458					  __old_finish - __n, __old_finish);
459		  std::fill(__position.base(), __position.base() + __n,
460			    __x_copy);
461		}
462	      else
463		{
464		  std::__uninitialized_fill_n_a(this->_M_impl._M_finish,
465						__n - __elems_after,
466						__x_copy,
467						_M_get_Tp_allocator());
468		  this->_M_impl._M_finish += __n - __elems_after;
469		  std::__uninitialized_move_a(__position.base(), __old_finish,
470					      this->_M_impl._M_finish,
471					      _M_get_Tp_allocator());
472		  this->_M_impl._M_finish += __elems_after;
473		  std::fill(__position.base(), __old_finish, __x_copy);
474		}
475	    }
476	  else
477	    {
478	      const size_type __len =
479		_M_check_len(__n, "vector::_M_fill_insert");
480	      const size_type __elems_before = __position - begin();
481	      pointer __new_start(this->_M_allocate(__len));
482	      pointer __new_finish(__new_start);
483	      __try
484		{
485		  // See _M_insert_aux above.
486		  std::__uninitialized_fill_n_a(__new_start + __elems_before,
487						__n, __x,
488						_M_get_Tp_allocator());
489		  __new_finish = 0;
490
491		  __new_finish
492		    = std::__uninitialized_move_if_noexcept_a
493		    (this->_M_impl._M_start, __position.base(),
494		     __new_start, _M_get_Tp_allocator());
495
496		  __new_finish += __n;
497
498		  __new_finish
499		    = std::__uninitialized_move_if_noexcept_a
500		    (__position.base(), this->_M_impl._M_finish,
501		     __new_finish, _M_get_Tp_allocator());
502		}
503	      __catch(...)
504		{
505		  if (!__new_finish)
506		    std::_Destroy(__new_start + __elems_before,
507				  __new_start + __elems_before + __n,
508				  _M_get_Tp_allocator());
509		  else
510		    std::_Destroy(__new_start, __new_finish,
511				  _M_get_Tp_allocator());
512		  _M_deallocate(__new_start, __len);
513		  __throw_exception_again;
514		}
515	      std::_Destroy(this->_M_impl._M_start, this->_M_impl._M_finish,
516			    _M_get_Tp_allocator());
517	      _M_deallocate(this->_M_impl._M_start,
518			    this->_M_impl._M_end_of_storage
519			    - this->_M_impl._M_start);
520	      this->_M_impl._M_start = __new_start;
521	      this->_M_impl._M_finish = __new_finish;
522	      this->_M_impl._M_end_of_storage = __new_start + __len;
523	    }
524	}
525    }
526
527#ifdef __GXX_EXPERIMENTAL_CXX0X__
528  template<typename _Tp, typename _Alloc>
529    void
530    vector<_Tp, _Alloc>::
531    _M_default_append(size_type __n)
532    {
533      if (__n != 0)
534	{
535	  if (size_type(this->_M_impl._M_end_of_storage
536			- this->_M_impl._M_finish) >= __n)
537	    {
538	      std::__uninitialized_default_n_a(this->_M_impl._M_finish,
539					       __n, _M_get_Tp_allocator());
540	      this->_M_impl._M_finish += __n;
541	    }
542	  else
543	    {
544	      const size_type __len =
545		_M_check_len(__n, "vector::_M_default_append");
546	      const size_type __old_size = this->size();
547	      pointer __new_start(this->_M_allocate(__len));
548	      pointer __new_finish(__new_start);
549	      __try
550		{
551		  __new_finish
552		    = std::__uninitialized_move_if_noexcept_a
553		    (this->_M_impl._M_start, this->_M_impl._M_finish,
554		     __new_start, _M_get_Tp_allocator());
555		  std::__uninitialized_default_n_a(__new_finish, __n,
556						   _M_get_Tp_allocator());
557		  __new_finish += __n;
558		}
559	      __catch(...)
560		{
561		  std::_Destroy(__new_start, __new_finish,
562				_M_get_Tp_allocator());
563		  _M_deallocate(__new_start, __len);
564		  __throw_exception_again;
565		}
566	      std::_Destroy(this->_M_impl._M_start, this->_M_impl._M_finish,
567			    _M_get_Tp_allocator());
568	      _M_deallocate(this->_M_impl._M_start,
569			    this->_M_impl._M_end_of_storage
570			    - this->_M_impl._M_start);
571	      this->_M_impl._M_start = __new_start;
572	      this->_M_impl._M_finish = __new_finish;
573	      this->_M_impl._M_end_of_storage = __new_start + __len;
574	    }
575	}
576    }
577
578  template<typename _Tp, typename _Alloc>
579    bool
580    vector<_Tp, _Alloc>::
581    _M_shrink_to_fit()
582    {
583      if (capacity() == size())
584	return false;
585      return std::__shrink_to_fit_aux<vector>::_S_do_it(*this);
586    }
587#endif
588
589  template<typename _Tp, typename _Alloc>
590    template<typename _InputIterator>
591      void
592      vector<_Tp, _Alloc>::
593      _M_range_insert(iterator __pos, _InputIterator __first,
594		      _InputIterator __last, std::input_iterator_tag)
595      {
596	for (; __first != __last; ++__first)
597	  {
598	    __pos = insert(__pos, *__first);
599	    ++__pos;
600	  }
601      }
602
603  template<typename _Tp, typename _Alloc>
604    template<typename _ForwardIterator>
605      void
606      vector<_Tp, _Alloc>::
607      _M_range_insert(iterator __position, _ForwardIterator __first,
608		      _ForwardIterator __last, std::forward_iterator_tag)
609      {
610	if (__first != __last)
611	  {
612	    const size_type __n = std::distance(__first, __last);
613	    if (size_type(this->_M_impl._M_end_of_storage
614			  - this->_M_impl._M_finish) >= __n)
615	      {
616		const size_type __elems_after = end() - __position;
617		pointer __old_finish(this->_M_impl._M_finish);
618		if (__elems_after > __n)
619		  {
620		    std::__uninitialized_move_a(this->_M_impl._M_finish - __n,
621						this->_M_impl._M_finish,
622						this->_M_impl._M_finish,
623						_M_get_Tp_allocator());
624		    this->_M_impl._M_finish += __n;
625		    _GLIBCXX_MOVE_BACKWARD3(__position.base(),
626					    __old_finish - __n, __old_finish);
627		    std::copy(__first, __last, __position);
628		  }
629		else
630		  {
631		    _ForwardIterator __mid = __first;
632		    std::advance(__mid, __elems_after);
633		    std::__uninitialized_copy_a(__mid, __last,
634						this->_M_impl._M_finish,
635						_M_get_Tp_allocator());
636		    this->_M_impl._M_finish += __n - __elems_after;
637		    std::__uninitialized_move_a(__position.base(),
638						__old_finish,
639						this->_M_impl._M_finish,
640						_M_get_Tp_allocator());
641		    this->_M_impl._M_finish += __elems_after;
642		    std::copy(__first, __mid, __position);
643		  }
644	      }
645	    else
646	      {
647		const size_type __len =
648		  _M_check_len(__n, "vector::_M_range_insert");
649		pointer __new_start(this->_M_allocate(__len));
650		pointer __new_finish(__new_start);
651		__try
652		  {
653		    __new_finish
654		      = std::__uninitialized_move_if_noexcept_a
655		      (this->_M_impl._M_start, __position.base(),
656		       __new_start, _M_get_Tp_allocator());
657		    __new_finish
658		      = std::__uninitialized_copy_a(__first, __last,
659						    __new_finish,
660						    _M_get_Tp_allocator());
661		    __new_finish
662		      = std::__uninitialized_move_if_noexcept_a
663		      (__position.base(), this->_M_impl._M_finish,
664		       __new_finish, _M_get_Tp_allocator());
665		  }
666		__catch(...)
667		  {
668		    std::_Destroy(__new_start, __new_finish,
669				  _M_get_Tp_allocator());
670		    _M_deallocate(__new_start, __len);
671		    __throw_exception_again;
672		  }
673		std::_Destroy(this->_M_impl._M_start, this->_M_impl._M_finish,
674			      _M_get_Tp_allocator());
675		_M_deallocate(this->_M_impl._M_start,
676			      this->_M_impl._M_end_of_storage
677			      - this->_M_impl._M_start);
678		this->_M_impl._M_start = __new_start;
679		this->_M_impl._M_finish = __new_finish;
680		this->_M_impl._M_end_of_storage = __new_start + __len;
681	      }
682	  }
683      }
684
685
686  // vector<bool>
687  template<typename _Alloc>
688    void
689    vector<bool, _Alloc>::
690    _M_reallocate(size_type __n)
691    {
692      _Bit_type* __q = this->_M_allocate(__n);
693      this->_M_impl._M_finish = _M_copy_aligned(begin(), end(),
694						iterator(__q, 0));
695      this->_M_deallocate();
696      this->_M_impl._M_start = iterator(__q, 0);
697      this->_M_impl._M_end_of_storage = __q + _S_nword(__n);
698    }
699
700  template<typename _Alloc>
701    void
702    vector<bool, _Alloc>::
703    _M_fill_insert(iterator __position, size_type __n, bool __x)
704    {
705      if (__n == 0)
706	return;
707      if (capacity() - size() >= __n)
708	{
709	  std::copy_backward(__position, end(),
710			     this->_M_impl._M_finish + difference_type(__n));
711	  std::fill(__position, __position + difference_type(__n), __x);
712	  this->_M_impl._M_finish += difference_type(__n);
713	}
714      else
715	{
716	  const size_type __len = 
717	    _M_check_len(__n, "vector<bool>::_M_fill_insert");
718	  _Bit_type * __q = this->_M_allocate(__len);
719	  iterator __i = _M_copy_aligned(begin(), __position,
720					 iterator(__q, 0));
721	  std::fill(__i, __i + difference_type(__n), __x);
722	  this->_M_impl._M_finish = std::copy(__position, end(),
723					      __i + difference_type(__n));
724	  this->_M_deallocate();
725	  this->_M_impl._M_end_of_storage = __q + _S_nword(__len);
726	  this->_M_impl._M_start = iterator(__q, 0);
727	}
728    }
729
730  template<typename _Alloc>
731    template<typename _ForwardIterator>
732      void
733      vector<bool, _Alloc>::
734      _M_insert_range(iterator __position, _ForwardIterator __first, 
735		      _ForwardIterator __last, std::forward_iterator_tag)
736      {
737	if (__first != __last)
738	  {
739	    size_type __n = std::distance(__first, __last);
740	    if (capacity() - size() >= __n)
741	      {
742		std::copy_backward(__position, end(),
743				   this->_M_impl._M_finish
744				   + difference_type(__n));
745		std::copy(__first, __last, __position);
746		this->_M_impl._M_finish += difference_type(__n);
747	      }
748	    else
749	      {
750		const size_type __len =
751		  _M_check_len(__n, "vector<bool>::_M_insert_range");
752		_Bit_type * __q = this->_M_allocate(__len);
753		iterator __i = _M_copy_aligned(begin(), __position,
754					       iterator(__q, 0));
755		__i = std::copy(__first, __last, __i);
756		this->_M_impl._M_finish = std::copy(__position, end(), __i);
757		this->_M_deallocate();
758		this->_M_impl._M_end_of_storage = __q + _S_nword(__len);
759		this->_M_impl._M_start = iterator(__q, 0);
760	      }
761	  }
762      }
763
764  template<typename _Alloc>
765    void
766    vector<bool, _Alloc>::
767    _M_insert_aux(iterator __position, bool __x)
768    {
769      if (this->_M_impl._M_finish._M_p != this->_M_impl._M_end_of_storage)
770	{
771	  std::copy_backward(__position, this->_M_impl._M_finish, 
772			     this->_M_impl._M_finish + 1);
773	  *__position = __x;
774	  ++this->_M_impl._M_finish;
775	}
776      else
777	{
778	  const size_type __len =
779	    _M_check_len(size_type(1), "vector<bool>::_M_insert_aux");
780	  _Bit_type * __q = this->_M_allocate(__len);
781	  iterator __i = _M_copy_aligned(begin(), __position,
782					 iterator(__q, 0));
783	  *__i++ = __x;
784	  this->_M_impl._M_finish = std::copy(__position, end(), __i);
785	  this->_M_deallocate();
786	  this->_M_impl._M_end_of_storage = __q + _S_nword(__len);
787	  this->_M_impl._M_start = iterator(__q, 0);
788	}
789    }
790
791#ifdef __GXX_EXPERIMENTAL_CXX0X__
792  template<typename _Alloc>
793    bool
794    vector<bool, _Alloc>::
795    _M_shrink_to_fit()
796    {
797      if (capacity() - size() < int(_S_word_bit))
798	return false;
799      __try
800	{
801	  _M_reallocate(size());
802	  return true;
803	}
804      __catch(...)
805	{ return false; }
806    }
807#endif
808
809_GLIBCXX_END_NAMESPACE_CONTAINER
810} // namespace std
811
812#ifdef __GXX_EXPERIMENTAL_CXX0X__
813
814namespace std _GLIBCXX_VISIBILITY(default)
815{
816_GLIBCXX_BEGIN_NAMESPACE_VERSION
817
818  template<typename _Alloc>
819    size_t
820    hash<_GLIBCXX_STD_C::vector<bool, _Alloc>>::
821    operator()(const _GLIBCXX_STD_C::vector<bool, _Alloc>& __b) const noexcept
822    {
823      size_t __hash = 0;
824      using _GLIBCXX_STD_C::_S_word_bit;
825      using _GLIBCXX_STD_C::_Bit_type;
826
827      const size_t __words = __b.size() / _S_word_bit;
828      if (__words)
829	{
830	  const size_t __clength = __words * sizeof(_Bit_type);
831	  __hash = std::_Hash_impl::hash(__b._M_impl._M_start._M_p, __clength);
832	}
833
834      const size_t __extrabits = __b.size() % _S_word_bit;
835      if (__extrabits)
836	{
837	  _Bit_type __hiword = *__b._M_impl._M_finish._M_p;
838	  __hiword &= ~((~static_cast<_Bit_type>(0)) << __extrabits);
839
840	  const size_t __clength
841	    = (__extrabits + __CHAR_BIT__ - 1) / __CHAR_BIT__;
842	  if (__words)
843	    __hash = std::_Hash_impl::hash(&__hiword, __clength, __hash);
844	  else
845	    __hash = std::_Hash_impl::hash(&__hiword, __clength);
846	}
847
848      return __hash;
849    }
850
851_GLIBCXX_END_NAMESPACE_VERSION
852} // namespace std
853
854#endif // __GXX_EXPERIMENTAL_CXX0X__
855
856#endif /* _VECTOR_TCC */
857