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