1// Debugging vector implementation -*- C++ -*-
3// Copyright (C) 2003-2021 Free Software Foundation, Inc.
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)
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.
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.
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/>.
26 * This file is a GNU debug extension to the Standard C++ Library.
29#ifndef _GLIBCXX_DEBUG_VECTOR
30#define _GLIBCXX_DEBUG_VECTOR 1
32#pragma GCC system_header
34#include <bits/c++config.h>
35namespace std _GLIBCXX_VISIBILITY(default) { namespace __debug {
36 template<typename _Tp, typename _Allocator> class vector;
37} } // namespace std::__debug
41#include <debug/safe_sequence.h>
42#include <debug/safe_container.h>
43#include <debug/safe_iterator.h>
47 /** @brief Base class for Debug Mode vector.
49 * Adds information about the guaranteed capacity, which is useful for
50 * detecting code which relies on non-portable implementation details of
51 * the libstdc++ reallocation policy.
53 template<typename _SafeSequence,
54 typename _BaseSequence>
57 typedef typename _BaseSequence::size_type size_type;
60 _M_seq() const { return *static_cast<const _SafeSequence*>(this); }
63 _Safe_vector() _GLIBCXX_NOEXCEPT
64 : _M_guaranteed_capacity(0)
65 { _M_update_guaranteed_capacity(); }
67 _Safe_vector(const _Safe_vector&) _GLIBCXX_NOEXCEPT
68 : _M_guaranteed_capacity(0)
69 { _M_update_guaranteed_capacity(); }
71 _Safe_vector(size_type __n) _GLIBCXX_NOEXCEPT
72 : _M_guaranteed_capacity(__n)
75#if __cplusplus >= 201103L
76 _Safe_vector(_Safe_vector&& __x) noexcept
78 { __x._M_guaranteed_capacity = 0; }
81 operator=(const _Safe_vector&) noexcept
83 _M_update_guaranteed_capacity();
88 operator=(_Safe_vector&& __x) noexcept
90 _M_update_guaranteed_capacity();
91 __x._M_guaranteed_capacity = 0;
96 size_type _M_guaranteed_capacity;
99 _M_requires_reallocation(size_type __elements) const _GLIBCXX_NOEXCEPT
100 { return __elements > _M_seq().capacity(); }
103 _M_update_guaranteed_capacity() _GLIBCXX_NOEXCEPT
105 if (_M_seq().size() > _M_guaranteed_capacity)
106 _M_guaranteed_capacity = _M_seq().size();
111namespace std _GLIBCXX_VISIBILITY(default)
115 /// Class std::vector with safety/checking/debug instrumentation.
116 template<typename _Tp,
117 typename _Allocator = std::allocator<_Tp> >
119 : public __gnu_debug::_Safe_container<
120 vector<_Tp, _Allocator>, _Allocator, __gnu_debug::_Safe_sequence>,
121 public _GLIBCXX_STD_C::vector<_Tp, _Allocator>,
122 public __gnu_debug::_Safe_vector<
123 vector<_Tp, _Allocator>,
124 _GLIBCXX_STD_C::vector<_Tp, _Allocator> >
126 typedef _GLIBCXX_STD_C::vector<_Tp, _Allocator> _Base;
127 typedef __gnu_debug::_Safe_container<
128 vector, _Allocator, __gnu_debug::_Safe_sequence> _Safe;
129 typedef __gnu_debug::_Safe_vector<vector, _Base> _Safe_vector;
131 typedef typename _Base::iterator _Base_iterator;
132 typedef typename _Base::const_iterator _Base_const_iterator;
133 typedef __gnu_debug::_Equal_to<_Base_const_iterator> _Equal;
135 template<typename _ItT, typename _SeqT, typename _CatT>
136 friend class ::__gnu_debug::_Safe_iterator;
138 // Reference wrapper for base class. Disambiguates vector(const _Base&)
139 // from copy constructor by requiring a user-defined conversion.
140 // See PR libstdc++/90102.
143 _Base_ref(const _Base& __r) : _M_ref(__r) { }
149 typedef typename _Base::reference reference;
150 typedef typename _Base::const_reference const_reference;
152 typedef __gnu_debug::_Safe_iterator<
153 _Base_iterator, vector> iterator;
154 typedef __gnu_debug::_Safe_iterator<
155 _Base_const_iterator, vector> const_iterator;
157 typedef typename _Base::size_type size_type;
158 typedef typename _Base::difference_type difference_type;
160 typedef _Tp value_type;
161 typedef _Allocator allocator_type;
162 typedef typename _Base::pointer pointer;
163 typedef typename _Base::const_pointer const_pointer;
164 typedef std::reverse_iterator<iterator> reverse_iterator;
165 typedef std::reverse_iterator<const_iterator> const_reverse_iterator;
167 // 23.2.4.1 construct/copy/destroy:
169#if __cplusplus < 201103L
170 vector() _GLIBCXX_NOEXCEPT
177 vector(const _Allocator& __a) _GLIBCXX_NOEXCEPT
180#if __cplusplus >= 201103L
182 vector(size_type __n, const _Allocator& __a = _Allocator())
183 : _Base(__n, __a), _Safe_vector(__n) { }
185 vector(size_type __n, const __type_identity_t<_Tp>& __value,
186 const _Allocator& __a = _Allocator())
187 : _Base(__n, __value, __a) { }
190 vector(size_type __n, const _Tp& __value = _Tp(),
191 const _Allocator& __a = _Allocator())
192 : _Base(__n, __value, __a) { }
195#if __cplusplus >= 201103L
196 template<class _InputIterator,
197 typename = std::_RequireInputIter<_InputIterator>>
199 template<class _InputIterator>
201 vector(_InputIterator __first, _InputIterator __last,
202 const _Allocator& __a = _Allocator())
203 : _Base(__gnu_debug::__base(
204 __glibcxx_check_valid_constructor_range(__first, __last)),
205 __gnu_debug::__base(__last), __a) { }
207#if __cplusplus < 201103L
208 vector(const vector& __x)
211 ~vector() _GLIBCXX_NOEXCEPT { }
213 vector(const vector&) = default;
214 vector(vector&&) = default;
216 vector(const vector& __x, const allocator_type& __a)
217 : _Base(__x, __a) { }
219 vector(vector&& __x, const allocator_type& __a)
221 std::is_nothrow_constructible<_Base,
222 _Base, const allocator_type&>::value )
223 : _Safe(std::move(__x._M_safe()), __a),
224 _Base(std::move(__x._M_base()), __a),
225 _Safe_vector(std::move(__x)) { }
227 vector(initializer_list<value_type> __l,
228 const allocator_type& __a = allocator_type())
229 : _Base(__l, __a) { }
234 /// Construction from a normal-mode vector
235 vector(_Base_ref __x)
236 : _Base(__x._M_ref) { }
238#if __cplusplus < 201103L
240 operator=(const vector& __x)
242 this->_M_safe() = __x;
244 this->_M_update_guaranteed_capacity();
249 operator=(const vector&) = default;
252 operator=(vector&&) = default;
255 operator=(initializer_list<value_type> __l)
258 this->_M_invalidate_all();
259 this->_M_update_guaranteed_capacity();
264#if __cplusplus >= 201103L
265 template<typename _InputIterator,
266 typename = std::_RequireInputIter<_InputIterator>>
268 template<typename _InputIterator>
271 assign(_InputIterator __first, _InputIterator __last)
273 typename __gnu_debug::_Distance_traits<_InputIterator>::__type __dist;
274 __glibcxx_check_valid_range2(__first, __last, __dist);
276 if (__dist.second >= __gnu_debug::__dp_sign)
277 _Base::assign(__gnu_debug::__unsafe(__first),
278 __gnu_debug::__unsafe(__last));
280 _Base::assign(__first, __last);
282 this->_M_invalidate_all();
283 this->_M_update_guaranteed_capacity();
287 assign(size_type __n, const _Tp& __u)
289 _Base::assign(__n, __u);
290 this->_M_invalidate_all();
291 this->_M_update_guaranteed_capacity();
294#if __cplusplus >= 201103L
296 assign(initializer_list<value_type> __l)
299 this->_M_invalidate_all();
300 this->_M_update_guaranteed_capacity();
304 using _Base::get_allocator;
308 begin() _GLIBCXX_NOEXCEPT
309 { return iterator(_Base::begin(), this); }
312 begin() const _GLIBCXX_NOEXCEPT
313 { return const_iterator(_Base::begin(), this); }
316 end() _GLIBCXX_NOEXCEPT
317 { return iterator(_Base::end(), this); }
320 end() const _GLIBCXX_NOEXCEPT
321 { return const_iterator(_Base::end(), this); }
324 rbegin() _GLIBCXX_NOEXCEPT
325 { return reverse_iterator(end()); }
327 const_reverse_iterator
328 rbegin() const _GLIBCXX_NOEXCEPT
329 { return const_reverse_iterator(end()); }
332 rend() _GLIBCXX_NOEXCEPT
333 { return reverse_iterator(begin()); }
335 const_reverse_iterator
336 rend() const _GLIBCXX_NOEXCEPT
337 { return const_reverse_iterator(begin()); }
339#if __cplusplus >= 201103L
341 cbegin() const noexcept
342 { return const_iterator(_Base::begin(), this); }
345 cend() const noexcept
346 { return const_iterator(_Base::end(), this); }
348 const_reverse_iterator
349 crbegin() const noexcept
350 { return const_reverse_iterator(end()); }
352 const_reverse_iterator
353 crend() const noexcept
354 { return const_reverse_iterator(begin()); }
357 // 23.2.4.2 capacity:
359 using _Base::max_size;
361#if __cplusplus >= 201103L
363 resize(size_type __sz)
365 bool __realloc = this->_M_requires_reallocation(__sz);
366 if (__sz < this->size())
367 this->_M_invalidate_after_nth(__sz);
370 this->_M_invalidate_all();
371 this->_M_update_guaranteed_capacity();
375 resize(size_type __sz, const _Tp& __c)
377 bool __realloc = this->_M_requires_reallocation(__sz);
378 if (__sz < this->size())
379 this->_M_invalidate_after_nth(__sz);
380 _Base::resize(__sz, __c);
382 this->_M_invalidate_all();
383 this->_M_update_guaranteed_capacity();
387 resize(size_type __sz, _Tp __c = _Tp())
389 bool __realloc = this->_M_requires_reallocation(__sz);
390 if (__sz < this->size())
391 this->_M_invalidate_after_nth(__sz);
392 _Base::resize(__sz, __c);
394 this->_M_invalidate_all();
395 this->_M_update_guaranteed_capacity();
399#if __cplusplus >= 201103L
403 if (_Base::_M_shrink_to_fit())
405 this->_M_guaranteed_capacity = _Base::capacity();
406 this->_M_invalidate_all();
412 capacity() const _GLIBCXX_NOEXCEPT
414#ifdef _GLIBCXX_DEBUG_PEDANTIC
415 return this->_M_guaranteed_capacity;
417 return _Base::capacity();
424 reserve(size_type __n)
426 bool __realloc = this->_M_requires_reallocation(__n);
428 if (__n > this->_M_guaranteed_capacity)
429 this->_M_guaranteed_capacity = __n;
431 this->_M_invalidate_all();
436 operator[](size_type __n) _GLIBCXX_NOEXCEPT
438 __glibcxx_check_subscript(__n);
439 return _M_base()[__n];
443 operator[](size_type __n) const _GLIBCXX_NOEXCEPT
445 __glibcxx_check_subscript(__n);
446 return _M_base()[__n];
452 front() _GLIBCXX_NOEXCEPT
454 __glibcxx_check_nonempty();
455 return _Base::front();
459 front() const _GLIBCXX_NOEXCEPT
461 __glibcxx_check_nonempty();
462 return _Base::front();
466 back() _GLIBCXX_NOEXCEPT
468 __glibcxx_check_nonempty();
469 return _Base::back();
473 back() const _GLIBCXX_NOEXCEPT
475 __glibcxx_check_nonempty();
476 return _Base::back();
479 // _GLIBCXX_RESOLVE_LIB_DEFECTS
480 // DR 464. Suggestion for new member functions in standard containers.
483 // 23.2.4.3 modifiers:
485 push_back(const _Tp& __x)
487 bool __realloc = this->_M_requires_reallocation(this->size() + 1);
488 _Base::push_back(__x);
490 this->_M_invalidate_all();
491 this->_M_update_guaranteed_capacity();
494#if __cplusplus >= 201103L
495 template<typename _Up = _Tp>
496 typename __gnu_cxx::__enable_if<!std::__are_same<_Up, bool>::__value,
499 { emplace_back(std::move(__x)); }
501 template<typename... _Args>
502#if __cplusplus > 201402L
507 emplace_back(_Args&&... __args)
509 bool __realloc = this->_M_requires_reallocation(this->size() + 1);
510 _Base::emplace_back(std::forward<_Args>(__args)...);
512 this->_M_invalidate_all();
513 this->_M_update_guaranteed_capacity();
514#if __cplusplus > 201402L
521 pop_back() _GLIBCXX_NOEXCEPT
523 __glibcxx_check_nonempty();
524 this->_M_invalidate_if(_Equal(--_Base::end()));
528#if __cplusplus >= 201103L
529 template<typename... _Args>
531 emplace(const_iterator __position, _Args&&... __args)
533 __glibcxx_check_insert(__position);
534 bool __realloc = this->_M_requires_reallocation(this->size() + 1);
535 difference_type __offset = __position.base() - _Base::cbegin();
536 _Base_iterator __res = _Base::emplace(__position.base(),
537 std::forward<_Args>(__args)...);
539 this->_M_invalidate_all();
541 this->_M_invalidate_after_nth(__offset);
542 this->_M_update_guaranteed_capacity();
543 return { __res, this };
548#if __cplusplus >= 201103L
549 insert(const_iterator __position, const _Tp& __x)
551 insert(iterator __position, const _Tp& __x)
554 __glibcxx_check_insert(__position);
555 bool __realloc = this->_M_requires_reallocation(this->size() + 1);
556 difference_type __offset = __position.base() - _Base::begin();
557 _Base_iterator __res = _Base::insert(__position.base(), __x);
559 this->_M_invalidate_all();
561 this->_M_invalidate_after_nth(__offset);
562 this->_M_update_guaranteed_capacity();
563 return iterator(__res, this);
566#if __cplusplus >= 201103L
567 template<typename _Up = _Tp>
568 typename __gnu_cxx::__enable_if<!std::__are_same<_Up, bool>::__value,
570 insert(const_iterator __position, _Tp&& __x)
571 { return emplace(__position, std::move(__x)); }
574 insert(const_iterator __position, initializer_list<value_type> __l)
575 { return this->insert(__position, __l.begin(), __l.end()); }
578#if __cplusplus >= 201103L
580 insert(const_iterator __position, size_type __n, const _Tp& __x)
582 __glibcxx_check_insert(__position);
583 bool __realloc = this->_M_requires_reallocation(this->size() + __n);
584 difference_type __offset = __position.base() - _Base::cbegin();
585 _Base_iterator __res = _Base::insert(__position.base(), __n, __x);
587 this->_M_invalidate_all();
589 this->_M_invalidate_after_nth(__offset);
590 this->_M_update_guaranteed_capacity();
591 return { __res, this };
595 insert(iterator __position, size_type __n, const _Tp& __x)
597 __glibcxx_check_insert(__position);
598 bool __realloc = this->_M_requires_reallocation(this->size() + __n);
599 difference_type __offset = __position.base() - _Base::begin();
600 _Base::insert(__position.base(), __n, __x);
602 this->_M_invalidate_all();
604 this->_M_invalidate_after_nth(__offset);
605 this->_M_update_guaranteed_capacity();
609#if __cplusplus >= 201103L
610 template<class _InputIterator,
611 typename = std::_RequireInputIter<_InputIterator>>
613 insert(const_iterator __position,
614 _InputIterator __first, _InputIterator __last)
616 typename __gnu_debug::_Distance_traits<_InputIterator>::__type __dist;
617 __glibcxx_check_insert_range(__position, __first, __last, __dist);
619 /* Hard to guess if invalidation will occur, because __last
620 - __first can't be calculated in all cases, so we just
621 punt here by checking if it did occur. */
622 _Base_iterator __old_begin = _M_base().begin();
623 difference_type __offset = __position.base() - _Base::cbegin();
624 _Base_iterator __res;
625 if (__dist.second >= __gnu_debug::__dp_sign)
626 __res = _Base::insert(__position.base(),
627 __gnu_debug::__unsafe(__first),
628 __gnu_debug::__unsafe(__last));
630 __res = _Base::insert(__position.base(), __first, __last);
632 if (_M_base().begin() != __old_begin)
633 this->_M_invalidate_all();
635 this->_M_invalidate_after_nth(__offset);
636 this->_M_update_guaranteed_capacity();
637 return { __res, this };
640 template<class _InputIterator>
642 insert(iterator __position,
643 _InputIterator __first, _InputIterator __last)
645 typename __gnu_debug::_Distance_traits<_InputIterator>::__type __dist;
646 __glibcxx_check_insert_range(__position, __first, __last, __dist);
648 /* Hard to guess if invalidation will occur, because __last
649 - __first can't be calculated in all cases, so we just
650 punt here by checking if it did occur. */
651 _Base_iterator __old_begin = _M_base().begin();
652 difference_type __offset = __position.base() - _Base::begin();
653 if (__dist.second >= __gnu_debug::__dp_sign)
654 _Base::insert(__position.base(), __gnu_debug::__unsafe(__first),
655 __gnu_debug::__unsafe(__last));
657 _Base::insert(__position.base(), __first, __last);
659 if (_M_base().begin() != __old_begin)
660 this->_M_invalidate_all();
662 this->_M_invalidate_after_nth(__offset);
663 this->_M_update_guaranteed_capacity();
668#if __cplusplus >= 201103L
669 erase(const_iterator __position)
671 erase(iterator __position)
674 __glibcxx_check_erase(__position);
675 difference_type __offset = __position.base() - _Base::begin();
676 _Base_iterator __res = _Base::erase(__position.base());
677 this->_M_invalidate_after_nth(__offset);
678 return iterator(__res, this);
682#if __cplusplus >= 201103L
683 erase(const_iterator __first, const_iterator __last)
685 erase(iterator __first, iterator __last)
688 // _GLIBCXX_RESOLVE_LIB_DEFECTS
689 // 151. can't currently clear() empty container
690 __glibcxx_check_erase_range(__first, __last);
692 if (__first.base() != __last.base())
694 difference_type __offset = __first.base() - _Base::begin();
695 _Base_iterator __res = _Base::erase(__first.base(),
697 this->_M_invalidate_after_nth(__offset);
698 return iterator(__res, this);
701#if __cplusplus >= 201103L
702 return { _Base::begin() + (__first.base() - _Base::cbegin()), this };
710 _GLIBCXX_NOEXCEPT_IF( noexcept(declval<_Base&>().swap(__x)) )
714 std::swap(this->_M_guaranteed_capacity, __x._M_guaranteed_capacity);
718 clear() _GLIBCXX_NOEXCEPT
721 this->_M_invalidate_all();
725 _M_base() _GLIBCXX_NOEXCEPT { return *this; }
728 _M_base() const _GLIBCXX_NOEXCEPT { return *this; }
732 _M_invalidate_after_nth(difference_type __n) _GLIBCXX_NOEXCEPT
734 typedef __gnu_debug::_After_nth_from<_Base_const_iterator> _After_nth;
735 this->_M_invalidate_if(_After_nth(__n, _Base::begin()));
739 template<typename _Tp, typename _Alloc>
741 operator==(const vector<_Tp, _Alloc>& __lhs,
742 const vector<_Tp, _Alloc>& __rhs)
743 { return __lhs._M_base() == __rhs._M_base(); }
745#if __cpp_lib_three_way_comparison
746 template<typename _Tp, typename _Alloc>
747 constexpr __detail::__synth3way_t<_Tp>
748 operator<=>(const vector<_Tp, _Alloc>& __x, const vector<_Tp, _Alloc>& __y)
749 { return __x._M_base() <=> __y._M_base(); }
751 template<typename _Tp, typename _Alloc>
753 operator!=(const vector<_Tp, _Alloc>& __lhs,
754 const vector<_Tp, _Alloc>& __rhs)
755 { return __lhs._M_base() != __rhs._M_base(); }
757 template<typename _Tp, typename _Alloc>
759 operator<(const vector<_Tp, _Alloc>& __lhs,
760 const vector<_Tp, _Alloc>& __rhs)
761 { return __lhs._M_base() < __rhs._M_base(); }
763 template<typename _Tp, typename _Alloc>
765 operator<=(const vector<_Tp, _Alloc>& __lhs,
766 const vector<_Tp, _Alloc>& __rhs)
767 { return __lhs._M_base() <= __rhs._M_base(); }
769 template<typename _Tp, typename _Alloc>
771 operator>=(const vector<_Tp, _Alloc>& __lhs,
772 const vector<_Tp, _Alloc>& __rhs)
773 { return __lhs._M_base() >= __rhs._M_base(); }
775 template<typename _Tp, typename _Alloc>
777 operator>(const vector<_Tp, _Alloc>& __lhs,
778 const vector<_Tp, _Alloc>& __rhs)
779 { return __lhs._M_base() > __rhs._M_base(); }
780#endif // three-way comparison
782 template<typename _Tp, typename _Alloc>
784 swap(vector<_Tp, _Alloc>& __lhs, vector<_Tp, _Alloc>& __rhs)
785 _GLIBCXX_NOEXCEPT_IF(noexcept(__lhs.swap(__rhs)))
786 { __lhs.swap(__rhs); }
788#if __cpp_deduction_guides >= 201606
789 template<typename _InputIterator, typename _ValT
790 = typename iterator_traits<_InputIterator>::value_type,
791 typename _Allocator = allocator<_ValT>,
792 typename = _RequireInputIter<_InputIterator>,
793 typename = _RequireAllocator<_Allocator>>
794 vector(_InputIterator, _InputIterator, _Allocator = _Allocator())
795 -> vector<_ValT, _Allocator>;
797 template<typename _Tp, typename _Allocator = allocator<_Tp>,
798 typename = _RequireAllocator<_Allocator>>
799 vector(size_t, _Tp, _Allocator = _Allocator())
800 -> vector<_Tp, _Allocator>;
803} // namespace __debug
805_GLIBCXX_BEGIN_NAMESPACE_VERSION
807#if __cplusplus >= 201103L
809 /// std::hash specialization for vector<bool>.
810 template<typename _Alloc>
811 struct hash<__debug::vector<bool, _Alloc>>
812 : public __hash_base<size_t, __debug::vector<bool, _Alloc>>
815 operator()(const __debug::vector<bool, _Alloc>& __b) const noexcept
816 { return std::hash<_GLIBCXX_STD_C::vector<bool, _Alloc>>()(__b); }
820#if __cplusplus >= 201703L
821 namespace __detail::__variant
823 template<typename> struct _Never_valueless_alt; // see <variant>
825 // Provide the strong exception-safety guarantee when emplacing a
826 // vector into a variant, but only if move assignment cannot throw.
827 template<typename _Tp, typename _Alloc>
828 struct _Never_valueless_alt<__debug::vector<_Tp, _Alloc>>
829 : std::is_nothrow_move_assignable<__debug::vector<_Tp, _Alloc>>
831 } // namespace __detail::__variant
834_GLIBCXX_END_NAMESPACE_VERSION
839 template<typename _Tp, typename _Alloc>
840 struct _Is_contiguous_sequence<std::__debug::vector<_Tp, _Alloc> >
844 template<typename _Alloc>
845 struct _Is_contiguous_sequence<std::__debug::vector<bool, _Alloc> >