OSDN Git Service

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