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