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
38namespace __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
104namespace std _GLIBCXX_VISIBILITY(default)
105{
106namespace __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
755namespace __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
769