Home | History | Annotate | Download | only in bits
      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 
     60 namespace 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 
    814 namespace 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