libstdc++
debug/vector
Go to the documentation of this file.
1 // Debugging vector implementation -*- C++ -*-
2 
3 // Copyright (C) 2003-2015 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 /** @file debug/vector
26  * This file is a GNU debug extension to the Standard C++ Library.
27  */
28 
29 #ifndef _GLIBCXX_DEBUG_VECTOR
30 #define _GLIBCXX_DEBUG_VECTOR 1
31 
32 #include <vector>
33 #include <utility>
34 #include <debug/safe_sequence.h>
35 #include <debug/safe_container.h>
36 #include <debug/safe_iterator.h>
37 
38 namespace __gnu_debug
39 {
40  /** @brief Base class for Debug Mode vector.
41  *
42  * Adds information about the guaranteed capacity, which is useful for
43  * detecting code which relies on non-portable implementation details of
44  * the libstdc++ reallocation policy.
45  */
46  template<typename _SafeSequence,
47  typename _BaseSequence>
48  class _Safe_vector
49  {
50  typedef typename _BaseSequence::size_type size_type;
51 
52  const _SafeSequence&
53  _M_seq() const { return *static_cast<const _SafeSequence*>(this); }
54 
55  protected:
56  _Safe_vector() _GLIBCXX_NOEXCEPT
57  : _M_guaranteed_capacity(0)
58  { _M_update_guaranteed_capacity(); }
59 
60  _Safe_vector(const _Safe_vector&) _GLIBCXX_NOEXCEPT
61  : _M_guaranteed_capacity(0)
62  { _M_update_guaranteed_capacity(); }
63 
64  _Safe_vector(size_type __n) _GLIBCXX_NOEXCEPT
65  : _M_guaranteed_capacity(__n)
66  { }
67 
68 #if __cplusplus >= 201103L
69  _Safe_vector(_Safe_vector&& __x) noexcept
70  : _Safe_vector()
71  { __x._M_guaranteed_capacity = 0; }
72 
73  _Safe_vector&
74  operator=(const _Safe_vector&) noexcept
75  {
76  _M_update_guaranteed_capacity();
77  return *this;
78  }
79 
80  _Safe_vector&
81  operator=(_Safe_vector&& __x) noexcept
82  {
83  _M_update_guaranteed_capacity();
84  __x._M_guaranteed_capacity = 0;
85  return *this;
86  }
87 #endif
88 
89  size_type _M_guaranteed_capacity;
90 
91  bool
92  _M_requires_reallocation(size_type __elements) const _GLIBCXX_NOEXCEPT
93  { return __elements > _M_seq().capacity(); }
94 
95  void
96  _M_update_guaranteed_capacity() _GLIBCXX_NOEXCEPT
97  {
98  if (_M_seq().size() > _M_guaranteed_capacity)
99  _M_guaranteed_capacity = _M_seq().size();
100  }
101  };
102 }
103 
104 namespace std _GLIBCXX_VISIBILITY(default)
105 {
106 namespace __debug
107 {
108  /// Class std::vector with safety/checking/debug instrumentation.
109  template<typename _Tp,
110  typename _Allocator = std::allocator<_Tp> >
111  class vector
112  : public __gnu_debug::_Safe_container<
113  vector<_Tp, _Allocator>, _Allocator, __gnu_debug::_Safe_sequence>,
114  public _GLIBCXX_STD_C::vector<_Tp, _Allocator>,
115  public __gnu_debug::_Safe_vector<
116  vector<_Tp, _Allocator>,
117  _GLIBCXX_STD_C::vector<_Tp, _Allocator> >
118  {
119  typedef _GLIBCXX_STD_C::vector<_Tp, _Allocator> _Base;
120  typedef __gnu_debug::_Safe_container<
121  vector, _Allocator, __gnu_debug::_Safe_sequence> _Safe;
122  typedef __gnu_debug::_Safe_vector<vector, _Base> _Safe_vector;
123 
124  typedef typename _Base::iterator _Base_iterator;
125  typedef typename _Base::const_iterator _Base_const_iterator;
126  typedef __gnu_debug::_Equal_to<_Base_const_iterator> _Equal;
127 
128  public:
129  typedef typename _Base::reference reference;
130  typedef typename _Base::const_reference const_reference;
131 
132  typedef __gnu_debug::_Safe_iterator<
133  _Base_iterator, vector> iterator;
134  typedef __gnu_debug::_Safe_iterator<
135  _Base_const_iterator, vector> const_iterator;
136 
137  typedef typename _Base::size_type size_type;
138  typedef typename _Base::difference_type difference_type;
139 
140  typedef _Tp value_type;
141  typedef _Allocator allocator_type;
142  typedef typename _Base::pointer pointer;
143  typedef typename _Base::const_pointer const_pointer;
144  typedef std::reverse_iterator<iterator> reverse_iterator;
145  typedef std::reverse_iterator<const_iterator> const_reverse_iterator;
146 
147  // 23.2.4.1 construct/copy/destroy:
148 
149 #if __cplusplus < 201103L
150  vector() _GLIBCXX_NOEXCEPT
151  : _Base() { }
152 #else
153  vector() = default;
154 #endif
155 
156  explicit
157  vector(const _Allocator& __a) _GLIBCXX_NOEXCEPT
158  : _Base(__a) { }
159 
160 #if __cplusplus >= 201103L
161  explicit
162  vector(size_type __n, const _Allocator& __a = _Allocator())
163  : _Base(__n, __a), _Safe_vector(__n) { }
164 
165  vector(size_type __n, const _Tp& __value,
166  const _Allocator& __a = _Allocator())
167  : _Base(__n, __value, __a) { }
168 #else
169  explicit
170  vector(size_type __n, const _Tp& __value = _Tp(),
171  const _Allocator& __a = _Allocator())
172  : _Base(__n, __value, __a) { }
173 #endif
174 
175 #if __cplusplus >= 201103L
176  template<class _InputIterator,
177  typename = std::_RequireInputIter<_InputIterator>>
178 #else
179  template<class _InputIterator>
180 #endif
181  vector(_InputIterator __first, _InputIterator __last,
182  const _Allocator& __a = _Allocator())
183  : _Base(__gnu_debug::__base(__gnu_debug::__check_valid_range(__first,
184  __last)),
185  __gnu_debug::__base(__last), __a) { }
186 
187 #if __cplusplus < 201103L
188  vector(const vector& __x)
189  : _Base(__x) { }
190 
191  ~vector() _GLIBCXX_NOEXCEPT { }
192 #else
193  vector(const vector&) = default;
194  vector(vector&&) = default;
195 
196  vector(const vector& __x, const allocator_type& __a)
197  : _Base(__x, __a) { }
198 
199  vector(vector&& __x, const allocator_type& __a)
200  : _Safe(std::move(__x._M_safe()), __a),
201  _Base(std::move(__x._M_base()), __a),
202  _Safe_vector(std::move(__x)) { }
203 
204  vector(initializer_list<value_type> __l,
205  const allocator_type& __a = allocator_type())
206  : _Base(__l, __a) { }
207 
208  ~vector() = default;
209 #endif
210 
211  /// Construction from a normal-mode vector
212  vector(const _Base& __x)
213  : _Base(__x) { }
214 
215 #if __cplusplus < 201103L
216  vector&
217  operator=(const vector& __x)
218  {
219  this->_M_safe() = __x;
220  _M_base() = __x;
221  this->_M_update_guaranteed_capacity();
222  return *this;
223  }
224 #else
225  vector&
226  operator=(const vector&) = default;
227 
228  vector&
229  operator=(vector&&) = default;
230 
231  vector&
232  operator=(initializer_list<value_type> __l)
233  {
234  _M_base() = __l;
235  this->_M_invalidate_all();
236  this->_M_update_guaranteed_capacity();
237  return *this;
238  }
239 #endif
240 
241 #if __cplusplus >= 201103L
242  template<typename _InputIterator,
243  typename = std::_RequireInputIter<_InputIterator>>
244 #else
245  template<typename _InputIterator>
246 #endif
247  void
248  assign(_InputIterator __first, _InputIterator __last)
249  {
250  __glibcxx_check_valid_range(__first, __last);
251  _Base::assign(__gnu_debug::__base(__first),
252  __gnu_debug::__base(__last));
253  this->_M_invalidate_all();
254  this->_M_update_guaranteed_capacity();
255  }
256 
257  void
258  assign(size_type __n, const _Tp& __u)
259  {
260  _Base::assign(__n, __u);
261  this->_M_invalidate_all();
262  this->_M_update_guaranteed_capacity();
263  }
264 
265 #if __cplusplus >= 201103L
266  void
267  assign(initializer_list<value_type> __l)
268  {
269  _Base::assign(__l);
270  this->_M_invalidate_all();
271  this->_M_update_guaranteed_capacity();
272  }
273 #endif
274 
275  using _Base::get_allocator;
276 
277  // iterators:
278  iterator
279  begin() _GLIBCXX_NOEXCEPT
280  { return iterator(_Base::begin(), this); }
281 
282  const_iterator
283  begin() const _GLIBCXX_NOEXCEPT
284  { return const_iterator(_Base::begin(), this); }
285 
286  iterator
287  end() _GLIBCXX_NOEXCEPT
288  { return iterator(_Base::end(), this); }
289 
290  const_iterator
291  end() const _GLIBCXX_NOEXCEPT
292  { return const_iterator(_Base::end(), this); }
293 
294  reverse_iterator
295  rbegin() _GLIBCXX_NOEXCEPT
296  { return reverse_iterator(end()); }
297 
298  const_reverse_iterator
299  rbegin() const _GLIBCXX_NOEXCEPT
300  { return const_reverse_iterator(end()); }
301 
302  reverse_iterator
303  rend() _GLIBCXX_NOEXCEPT
304  { return reverse_iterator(begin()); }
305 
306  const_reverse_iterator
307  rend() const _GLIBCXX_NOEXCEPT
308  { return const_reverse_iterator(begin()); }
309 
310 #if __cplusplus >= 201103L
311  const_iterator
312  cbegin() const noexcept
313  { return const_iterator(_Base::begin(), this); }
314 
315  const_iterator
316  cend() const noexcept
317  { return const_iterator(_Base::end(), this); }
318 
319  const_reverse_iterator
320  crbegin() const noexcept
321  { return const_reverse_iterator(end()); }
322 
323  const_reverse_iterator
324  crend() const noexcept
325  { return const_reverse_iterator(begin()); }
326 #endif
327 
328  // 23.2.4.2 capacity:
329  using _Base::size;
330  using _Base::max_size;
331 
332 #if __cplusplus >= 201103L
333  void
334  resize(size_type __sz)
335  {
336  bool __realloc = this->_M_requires_reallocation(__sz);
337  if (__sz < this->size())
338  this->_M_invalidate_after_nth(__sz);
339  _Base::resize(__sz);
340  if (__realloc)
341  this->_M_invalidate_all();
342  this->_M_update_guaranteed_capacity();
343  }
344 
345  void
346  resize(size_type __sz, const _Tp& __c)
347  {
348  bool __realloc = this->_M_requires_reallocation(__sz);
349  if (__sz < this->size())
350  this->_M_invalidate_after_nth(__sz);
351  _Base::resize(__sz, __c);
352  if (__realloc)
353  this->_M_invalidate_all();
354  this->_M_update_guaranteed_capacity();
355  }
356 #else
357  void
358  resize(size_type __sz, _Tp __c = _Tp())
359  {
360  bool __realloc = this->_M_requires_reallocation(__sz);
361  if (__sz < this->size())
362  this->_M_invalidate_after_nth(__sz);
363  _Base::resize(__sz, __c);
364  if (__realloc)
365  this->_M_invalidate_all();
366  this->_M_update_guaranteed_capacity();
367  }
368 #endif
369 
370 #if __cplusplus >= 201103L
371  void
372  shrink_to_fit()
373  {
374  if (_Base::_M_shrink_to_fit())
375  {
376  this->_M_guaranteed_capacity = _Base::capacity();
377  this->_M_invalidate_all();
378  }
379  }
380 #endif
381 
382  size_type
383  capacity() const _GLIBCXX_NOEXCEPT
384  {
385 #ifdef _GLIBCXX_DEBUG_PEDANTIC
386  return this->_M_guaranteed_capacity;
387 #else
388  return _Base::capacity();
389 #endif
390  }
391 
392  using _Base::empty;
393 
394  void
395  reserve(size_type __n)
396  {
397  bool __realloc = this->_M_requires_reallocation(__n);
398  _Base::reserve(__n);
399  if (__n > this->_M_guaranteed_capacity)
400  this->_M_guaranteed_capacity = __n;
401  if (__realloc)
402  this->_M_invalidate_all();
403  }
404 
405  // element access:
406  reference
407  operator[](size_type __n) _GLIBCXX_NOEXCEPT
408  {
409  __glibcxx_check_subscript(__n);
410  return _M_base()[__n];
411  }
412 
413  const_reference
414  operator[](size_type __n) const _GLIBCXX_NOEXCEPT
415  {
416  __glibcxx_check_subscript(__n);
417  return _M_base()[__n];
418  }
419 
420  using _Base::at;
421 
422  reference
423  front() _GLIBCXX_NOEXCEPT
424  {
425  __glibcxx_check_nonempty();
426  return _Base::front();
427  }
428 
429  const_reference
430  front() const _GLIBCXX_NOEXCEPT
431  {
432  __glibcxx_check_nonempty();
433  return _Base::front();
434  }
435 
436  reference
437  back() _GLIBCXX_NOEXCEPT
438  {
439  __glibcxx_check_nonempty();
440  return _Base::back();
441  }
442 
443  const_reference
444  back() const _GLIBCXX_NOEXCEPT
445  {
446  __glibcxx_check_nonempty();
447  return _Base::back();
448  }
449 
450  // _GLIBCXX_RESOLVE_LIB_DEFECTS
451  // DR 464. Suggestion for new member functions in standard containers.
452  using _Base::data;
453 
454  // 23.2.4.3 modifiers:
455  void
456  push_back(const _Tp& __x)
457  {
458  bool __realloc = this->_M_requires_reallocation(this->size() + 1);
459  _Base::push_back(__x);
460  if (__realloc)
461  this->_M_invalidate_all();
462  this->_M_update_guaranteed_capacity();
463  }
464 
465 #if __cplusplus >= 201103L
466  template<typename _Up = _Tp>
467  typename __gnu_cxx::__enable_if<!std::__are_same<_Up, bool>::__value,
468  void>::__type
469  push_back(_Tp&& __x)
470  { emplace_back(std::move(__x)); }
471 
472  template<typename... _Args>
473  void
474  emplace_back(_Args&&... __args)
475  {
476  bool __realloc = this->_M_requires_reallocation(this->size() + 1);
477  _Base::emplace_back(std::forward<_Args>(__args)...);
478  if (__realloc)
479  this->_M_invalidate_all();
480  this->_M_update_guaranteed_capacity();
481  }
482 #endif
483 
484  void
485  pop_back() _GLIBCXX_NOEXCEPT
486  {
487  __glibcxx_check_nonempty();
488  this->_M_invalidate_if(_Equal(--_Base::end()));
489  _Base::pop_back();
490  }
491 
492 #if __cplusplus >= 201103L
493  template<typename... _Args>
494  iterator
495  emplace(const_iterator __position, _Args&&... __args)
496  {
497  __glibcxx_check_insert(__position);
498  bool __realloc = this->_M_requires_reallocation(this->size() + 1);
499  difference_type __offset = __position.base() - _Base::begin();
500  _Base_iterator __res = _Base::emplace(__position.base(),
501  std::forward<_Args>(__args)...);
502  if (__realloc)
503  this->_M_invalidate_all();
504  else
505  this->_M_invalidate_after_nth(__offset);
506  this->_M_update_guaranteed_capacity();
507  return iterator(__res, this);
508  }
509 #endif
510 
511  iterator
512 #if __cplusplus >= 201103L
513  insert(const_iterator __position, const _Tp& __x)
514 #else
515  insert(iterator __position, const _Tp& __x)
516 #endif
517  {
518  __glibcxx_check_insert(__position);
519  bool __realloc = this->_M_requires_reallocation(this->size() + 1);
520  difference_type __offset = __position.base() - _Base::begin();
521  _Base_iterator __res = _Base::insert(__position.base(), __x);
522  if (__realloc)
523  this->_M_invalidate_all();
524  else
525  this->_M_invalidate_after_nth(__offset);
526  this->_M_update_guaranteed_capacity();
527  return iterator(__res, this);
528  }
529 
530 #if __cplusplus >= 201103L
531  template<typename _Up = _Tp>
532  typename __gnu_cxx::__enable_if<!std::__are_same<_Up, bool>::__value,
533  iterator>::__type
534  insert(const_iterator __position, _Tp&& __x)
535  { return emplace(__position, std::move(__x)); }
536 
537  iterator
538  insert(const_iterator __position, initializer_list<value_type> __l)
539  { return this->insert(__position, __l.begin(), __l.end()); }
540 #endif
541 
542 #if __cplusplus >= 201103L
543  iterator
544  insert(const_iterator __position, size_type __n, const _Tp& __x)
545  {
546  __glibcxx_check_insert(__position);
547  bool __realloc = this->_M_requires_reallocation(this->size() + __n);
548  difference_type __offset = __position.base() - _Base::cbegin();
549  _Base_iterator __res = _Base::insert(__position.base(), __n, __x);
550  if (__realloc)
551  this->_M_invalidate_all();
552  else
553  this->_M_invalidate_after_nth(__offset);
554  this->_M_update_guaranteed_capacity();
555  return iterator(__res, this);
556  }
557 #else
558  void
559  insert(iterator __position, size_type __n, const _Tp& __x)
560  {
561  __glibcxx_check_insert(__position);
562  bool __realloc = this->_M_requires_reallocation(this->size() + __n);
563  difference_type __offset = __position.base() - _Base::begin();
564  _Base::insert(__position.base(), __n, __x);
565  if (__realloc)
566  this->_M_invalidate_all();
567  else
568  this->_M_invalidate_after_nth(__offset);
569  this->_M_update_guaranteed_capacity();
570  }
571 #endif
572 
573 #if __cplusplus >= 201103L
574  template<class _InputIterator,
575  typename = std::_RequireInputIter<_InputIterator>>
576  iterator
577  insert(const_iterator __position,
578  _InputIterator __first, _InputIterator __last)
579  {
580  __glibcxx_check_insert_range(__position, __first, __last);
581 
582  /* Hard to guess if invalidation will occur, because __last
583  - __first can't be calculated in all cases, so we just
584  punt here by checking if it did occur. */
585  _Base_iterator __old_begin = _M_base().begin();
586  difference_type __offset = __position.base() - _Base::cbegin();
587  _Base_iterator __res = _Base::insert(__position.base(),
588  __gnu_debug::__base(__first),
589  __gnu_debug::__base(__last));
590 
591  if (_M_base().begin() != __old_begin)
592  this->_M_invalidate_all();
593  else
594  this->_M_invalidate_after_nth(__offset);
595  this->_M_update_guaranteed_capacity();
596  return iterator(__res, this);
597  }
598 #else
599  template<class _InputIterator>
600  void
601  insert(iterator __position,
602  _InputIterator __first, _InputIterator __last)
603  {
604  __glibcxx_check_insert_range(__position, __first, __last);
605 
606  /* Hard to guess if invalidation will occur, because __last
607  - __first can't be calculated in all cases, so we just
608  punt here by checking if it did occur. */
609  _Base_iterator __old_begin = _M_base().begin();
610  difference_type __offset = __position.base() - _Base::begin();
611  _Base::insert(__position.base(), __gnu_debug::__base(__first),
612  __gnu_debug::__base(__last));
613 
614  if (_M_base().begin() != __old_begin)
615  this->_M_invalidate_all();
616  else
617  this->_M_invalidate_after_nth(__offset);
618  this->_M_update_guaranteed_capacity();
619  }
620 #endif
621 
622  iterator
623 #if __cplusplus >= 201103L
624  erase(const_iterator __position)
625 #else
626  erase(iterator __position)
627 #endif
628  {
629  __glibcxx_check_erase(__position);
630  difference_type __offset = __position.base() - _Base::begin();
631  _Base_iterator __res = _Base::erase(__position.base());
632  this->_M_invalidate_after_nth(__offset);
633  return iterator(__res, this);
634  }
635 
636  iterator
637 #if __cplusplus >= 201103L
638  erase(const_iterator __first, const_iterator __last)
639 #else
640  erase(iterator __first, iterator __last)
641 #endif
642  {
643  // _GLIBCXX_RESOLVE_LIB_DEFECTS
644  // 151. can't currently clear() empty container
645  __glibcxx_check_erase_range(__first, __last);
646 
647  if (__first.base() != __last.base())
648  {
649  difference_type __offset = __first.base() - _Base::begin();
650  _Base_iterator __res = _Base::erase(__first.base(),
651  __last.base());
652  this->_M_invalidate_after_nth(__offset);
653  return iterator(__res, this);
654  }
655  else
656 #if __cplusplus >= 201103L
657  return begin() + (__first.base() - cbegin().base());
658 #else
659  return __first;
660 #endif
661  }
662 
663  void
664  swap(vector& __x)
665 #if __cplusplus >= 201103L
666  noexcept( noexcept(declval<_Base>().swap(__x)) )
667 #endif
668  {
669  _Safe::_M_swap(__x);
670  _Base::swap(__x);
671  std::swap(this->_M_guaranteed_capacity, __x._M_guaranteed_capacity);
672  }
673 
674  void
675  clear() _GLIBCXX_NOEXCEPT
676  {
677  _Base::clear();
678  this->_M_invalidate_all();
679  }
680 
681  _Base&
682  _M_base() _GLIBCXX_NOEXCEPT { return *this; }
683 
684  const _Base&
685  _M_base() const _GLIBCXX_NOEXCEPT { return *this; }
686 
687  private:
688  void
689  _M_invalidate_after_nth(difference_type __n) _GLIBCXX_NOEXCEPT
690  {
691  typedef __gnu_debug::_After_nth_from<_Base_const_iterator> _After_nth;
692  this->_M_invalidate_if(_After_nth(__n, _Base::begin()));
693  }
694  };
695 
696  template<typename _Tp, typename _Alloc>
697  inline bool
698  operator==(const vector<_Tp, _Alloc>& __lhs,
699  const vector<_Tp, _Alloc>& __rhs)
700  { return __lhs._M_base() == __rhs._M_base(); }
701 
702  template<typename _Tp, typename _Alloc>
703  inline bool
704  operator!=(const vector<_Tp, _Alloc>& __lhs,
705  const vector<_Tp, _Alloc>& __rhs)
706  { return __lhs._M_base() != __rhs._M_base(); }
707 
708  template<typename _Tp, typename _Alloc>
709  inline bool
710  operator<(const vector<_Tp, _Alloc>& __lhs,
711  const vector<_Tp, _Alloc>& __rhs)
712  { return __lhs._M_base() < __rhs._M_base(); }
713 
714  template<typename _Tp, typename _Alloc>
715  inline bool
716  operator<=(const vector<_Tp, _Alloc>& __lhs,
717  const vector<_Tp, _Alloc>& __rhs)
718  { return __lhs._M_base() <= __rhs._M_base(); }
719 
720  template<typename _Tp, typename _Alloc>
721  inline bool
722  operator>=(const vector<_Tp, _Alloc>& __lhs,
723  const vector<_Tp, _Alloc>& __rhs)
724  { return __lhs._M_base() >= __rhs._M_base(); }
725 
726  template<typename _Tp, typename _Alloc>
727  inline bool
728  operator>(const vector<_Tp, _Alloc>& __lhs,
729  const vector<_Tp, _Alloc>& __rhs)
730  { return __lhs._M_base() > __rhs._M_base(); }
731 
732  template<typename _Tp, typename _Alloc>
733  inline void
734  swap(vector<_Tp, _Alloc>& __lhs, vector<_Tp, _Alloc>& __rhs)
735  { __lhs.swap(__rhs); }
736 
737 } // namespace __debug
738 
739 #if __cplusplus >= 201103L
740  // DR 1182.
741  /// std::hash specialization for vector<bool>.
742  template<typename _Alloc>
743  struct hash<__debug::vector<bool, _Alloc>>
744  : public __hash_base<size_t, __debug::vector<bool, _Alloc>>
745  {
746  size_t
747  operator()(const __debug::vector<bool, _Alloc>& __b) const noexcept
748  { return std::hash<_GLIBCXX_STD_C::vector<bool, _Alloc>>()
749  (__b._M_base()); }
750  };
751 #endif
752 
753 } // namespace std
754 
755 namespace __gnu_debug
756 {
757  template<typename _Tp, typename _Alloc>
758  struct _Is_contiguous_sequence<std::__debug::vector<_Tp, _Alloc> >
759  : std::__true_type
760  { };
761 
762  template<typename _Alloc>
763  struct _Is_contiguous_sequence<std::__debug::vector<bool, _Alloc> >
764  : std::__false_type
765  { };
766 }
767 
768 #endif