1 // Safe iterator implementation -*- C++ -*-
3 // Copyright (C) 2003-2024 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/>.
25 /** @file debug/safe_iterator.h
26 * This file is a GNU debug extension to the Standard C++ Library.
29 #ifndef _GLIBCXX_DEBUG_SAFE_ITERATOR_H
30 #define _GLIBCXX_DEBUG_SAFE_ITERATOR_H 1
32 #include <debug/assertions.h>
33 #include <debug/macros.h>
34 #include <debug/functions.h>
35 #include <debug/safe_base.h>
36 #include <bits/stl_pair.h>
37 #include <ext/type_traits.h>
38 #if __cplusplus > 201703L
42 #define _GLIBCXX_DEBUG_VERIFY_OPERANDS(_Lhs, _Rhs, _BadMsgId, _DiffMsgId) \
43 if (!std::__is_constant_evaluated()) { \
44 _GLIBCXX_DEBUG_VERIFY((!_Lhs._M_singular() && !_Rhs._M_singular()) \
45 || (_Lhs._M_value_initialized() \
46 && _Rhs._M_value_initialized()), \
47 _M_message(_BadMsgId) \
48 ._M_iterator(_Lhs, #_Lhs) \
49 ._M_iterator(_Rhs, #_Rhs)); \
50 _GLIBCXX_DEBUG_VERIFY(_Lhs._M_can_compare(_Rhs), \
51 _M_message(_DiffMsgId) \
52 ._M_iterator(_Lhs, #_Lhs) \
53 ._M_iterator(_Rhs, #_Rhs)); \
56 #define _GLIBCXX_DEBUG_VERIFY_EQ_OPERANDS(_Lhs, _Rhs) \
57 _GLIBCXX_DEBUG_VERIFY_OPERANDS(_Lhs, _Rhs, __msg_iter_compare_bad, \
58 __msg_compare_different)
60 #define _GLIBCXX_DEBUG_VERIFY_REL_OPERANDS(_Lhs, _Rhs) \
61 _GLIBCXX_DEBUG_VERIFY_OPERANDS(_Lhs, _Rhs, __msg_iter_order_bad, \
62 __msg_order_different)
64 #define _GLIBCXX_DEBUG_VERIFY_DIST_OPERANDS(_Lhs, _Rhs) \
65 _GLIBCXX_DEBUG_VERIFY_OPERANDS(_Lhs, _Rhs, __msg_distance_bad, \
66 __msg_distance_different)
68 // This pair of macros helps with writing valid C++20 constexpr functions that
69 // contain a non-constexpr code path that defines a non-literal variable, which
70 // was otherwise disallowed until P2242R3 for C++23. We use them below around
71 // __gnu_cxx::__scoped_lock variables so that the containing functions are still
72 // considered valid C++20 constexpr functions.
74 #if __cplusplus >= 202002L && __cpp_constexpr < 202110L
75 # define _GLIBCXX20_CONSTEXPR_NON_LITERAL_SCOPE_BEGIN [&]() -> void
76 # define _GLIBCXX20_CONSTEXPR_NON_LITERAL_SCOPE_END ();
78 # define _GLIBCXX20_CONSTEXPR_NON_LITERAL_SCOPE_BEGIN
79 # define _GLIBCXX20_CONSTEXPR_NON_LITERAL_SCOPE_END
84 /** Helper struct to deal with sequence offering a before_begin
87 template<typename _Sequence
>
88 struct _BeforeBeginHelper
90 template<typename _Iterator
, typename _Category
>
92 _S_Is(const _Safe_iterator
<_Iterator
, _Sequence
, _Category
>&)
95 template<typename _Iterator
, typename _Category
>
97 _S_Is_Beginnest(const _Safe_iterator
<_Iterator
, _Sequence
, _Category
>& __it
)
98 { return __it
.base() == __it
._M_get_sequence()->_M_base().begin(); }
101 /** Sequence traits giving the size of a container if possible. */
102 template<typename _Sequence
>
103 struct _Sequence_traits
105 typedef _Distance_traits
<typename
_Sequence::iterator
> _DistTraits
;
107 static typename
_DistTraits::__type
108 _S_size(const _Sequence
& __seq
)
109 { return std::make_pair(__seq
.size(), __dp_exact
); }
112 /** \brief Safe iterator wrapper.
114 * The class template %_Safe_iterator is a wrapper around an
115 * iterator that tracks the iterator's movement among sequences and
116 * checks that operations performed on the "safe" iterator are
117 * legal. In additional to the basic iterator operations (which are
118 * validated, and then passed to the underlying iterator),
119 * %_Safe_iterator has member functions for iterator invalidation,
120 * attaching/detaching the iterator from sequences, and querying
121 * the iterator's state.
123 * Note that _Iterator must be the first base class so that it gets
124 * initialized before the iterator is being attached to the container's list
125 * of iterators and it is being detached before _Iterator get
126 * destroyed. Otherwise it would result in a data race.
128 template<typename _Iterator
, typename _Sequence
, typename _Category
129 = typename
std::iterator_traits
<_Iterator
>::iterator_category
>
132 public _Safe_iterator_base
134 typedef _Iterator _Iter_base
;
135 typedef _Safe_iterator_base _Safe_base
;
137 typedef std::iterator_traits
<_Iterator
> _Traits
;
140 typedef std::__are_same
<typename
_Sequence::_Base::const_iterator
,
141 _Iterator
> _IsConstant
;
143 typedef typename
__gnu_cxx::__conditional_type
<
144 _IsConstant::__value
,
145 typename
_Sequence::_Base::iterator
,
146 typename
_Sequence::_Base::const_iterator
>::__type _OtherIterator
;
148 struct _Unchecked
{ };
151 _Safe_iterator(const _Safe_iterator
& __x
, _Unchecked
) _GLIBCXX_NOEXCEPT
152 : _Iter_base(__x
.base()), _Safe_base()
154 if (!std::__is_constant_evaluated())
155 _M_attach(__x
._M_sequence
);
159 typedef _Iterator iterator_type
;
160 typedef typename
_Traits::iterator_category iterator_category
;
161 typedef typename
_Traits::value_type value_type
;
162 typedef typename
_Traits::difference_type difference_type
;
163 typedef typename
_Traits::reference reference
;
164 typedef typename
_Traits::pointer pointer
;
166 #if __cplusplus > 201703L && __cpp_lib_concepts
167 using iterator_concept
= std::__detail::__iter_concept
<_Iterator
>;
170 /// @post the iterator is singular and unattached
172 _Safe_iterator() _GLIBCXX_NOEXCEPT
: _Iter_base() { }
175 * @brief Safe iterator construction from an unsafe iterator and
178 * @pre @p seq is not NULL
179 * @post this is not singular
182 _Safe_iterator(_Iterator __i
, const _Safe_sequence_base
* __seq
)
184 : _Iter_base(__i
), _Safe_base(__seq
, _S_constant())
188 * @brief Copy construction.
191 _Safe_iterator(const _Safe_iterator
& __x
) _GLIBCXX_NOEXCEPT
192 : _Iter_base(__x
.base()), _Safe_base()
194 if (std::__is_constant_evaluated())
197 // _GLIBCXX_RESOLVE_LIB_DEFECTS
198 // DR 408. Is vector<reverse_iterator<char*> > forbidden?
199 _GLIBCXX_DEBUG_VERIFY(!__x
._M_singular()
200 || __x
._M_value_initialized(),
201 _M_message(__msg_init_copy_singular
)
202 ._M_iterator(*this, "this")
203 ._M_iterator(__x
, "other"));
204 _M_attach(__x
._M_sequence
);
207 #if __cplusplus >= 201103L
209 * @brief Move construction.
210 * @post __x is singular and unattached
213 _Safe_iterator(_Safe_iterator
&& __x
) noexcept
216 if (std::__is_constant_evaluated())
222 _GLIBCXX_DEBUG_VERIFY(!__x
._M_singular()
223 || __x
._M_value_initialized(),
224 _M_message(__msg_init_copy_singular
)
225 ._M_iterator(*this, "this")
226 ._M_iterator(__x
, "other"));
227 _Safe_sequence_base
* __seq
= __x
._M_sequence
;
229 std::swap(base(), __x
.base());
235 * @brief Converting constructor from a mutable iterator to a
238 template<typename _MutableIterator
>
241 const _Safe_iterator
<_MutableIterator
, _Sequence
,
242 typename
__gnu_cxx::__enable_if
<_IsConstant::__value
&&
243 std::__are_same
<_MutableIterator
, _OtherIterator
>::__value
,
244 _Category
>::__type
>& __x
)
246 : _Iter_base(__x
.base())
248 if (std::__is_constant_evaluated())
251 // _GLIBCXX_RESOLVE_LIB_DEFECTS
252 // DR 408. Is vector<reverse_iterator<char*> > forbidden?
253 _GLIBCXX_DEBUG_VERIFY(!__x
._M_singular()
254 || __x
._M_value_initialized(),
255 _M_message(__msg_init_const_singular
)
256 ._M_iterator(*this, "this")
257 ._M_iterator(__x
, "other"));
258 _M_attach(__x
._M_sequence
);
262 * @brief Copy assignment.
266 operator=(const _Safe_iterator
& __x
) _GLIBCXX_NOEXCEPT
268 if (std::__is_constant_evaluated())
274 // _GLIBCXX_RESOLVE_LIB_DEFECTS
275 // DR 408. Is vector<reverse_iterator<char*> > forbidden?
276 _GLIBCXX_DEBUG_VERIFY(!__x
._M_singular()
277 || __x
._M_value_initialized(),
278 _M_message(__msg_copy_singular
)
279 ._M_iterator(*this, "this")
280 ._M_iterator(__x
, "other"));
282 if (this->_M_sequence
&& this->_M_sequence
== __x
._M_sequence
)
283 _GLIBCXX20_CONSTEXPR_NON_LITERAL_SCOPE_BEGIN
{
284 __gnu_cxx::__scoped_lock
__l(this->_M_get_mutex());
286 _M_version
= __x
._M_sequence
->_M_version
;
287 } _GLIBCXX20_CONSTEXPR_NON_LITERAL_SCOPE_END
292 _M_attach(__x
._M_sequence
);
298 #if __cplusplus >= 201103L
300 * @brief Move assignment.
301 * @post __x is singular and unattached
305 operator=(_Safe_iterator
&& __x
) noexcept
307 if (std::__is_constant_evaluated())
313 _GLIBCXX_DEBUG_VERIFY(!__x
._M_singular()
314 || __x
._M_value_initialized(),
315 _M_message(__msg_copy_singular
)
316 ._M_iterator(*this, "this")
317 ._M_iterator(__x
, "other"));
319 if (std::__addressof(__x
) == this)
322 if (this->_M_sequence
&& this->_M_sequence
== __x
._M_sequence
)
323 _GLIBCXX20_CONSTEXPR_NON_LITERAL_SCOPE_BEGIN
{
324 __gnu_cxx::__scoped_lock
__l(this->_M_get_mutex());
326 _M_version
= __x
._M_sequence
->_M_version
;
327 } _GLIBCXX20_CONSTEXPR_NON_LITERAL_SCOPE_END
332 _M_attach(__x
._M_sequence
);
336 __x
.base() = _Iterator();
342 * @brief Iterator dereference.
343 * @pre iterator is dereferenceable
348 operator*() const _GLIBCXX_NOEXCEPT
350 if (!std::__is_constant_evaluated())
352 _GLIBCXX_DEBUG_VERIFY(this->_M_dereferenceable(),
353 _M_message(__msg_bad_deref
)
354 ._M_iterator(*this, "this"));
360 * @brief Iterator dereference.
361 * @pre iterator is dereferenceable
366 operator->() const _GLIBCXX_NOEXCEPT
368 if (!std::__is_constant_evaluated())
370 _GLIBCXX_DEBUG_VERIFY(this->_M_dereferenceable(),
371 _M_message(__msg_bad_deref
)
372 ._M_iterator(*this, "this"));
374 return base().operator->();
377 // ------ Input iterator requirements ------
379 * @brief Iterator preincrement
380 * @pre iterator is incrementable
384 operator++() _GLIBCXX_NOEXCEPT
386 if (std::__is_constant_evaluated())
392 _GLIBCXX_DEBUG_VERIFY(this->_M_incrementable(),
393 _M_message(__msg_bad_inc
)
394 ._M_iterator(*this, "this"));
395 _GLIBCXX20_CONSTEXPR_NON_LITERAL_SCOPE_BEGIN
{
396 __gnu_cxx::__scoped_lock
__l(this->_M_get_mutex());
398 } _GLIBCXX20_CONSTEXPR_NON_LITERAL_SCOPE_END
403 * @brief Iterator postincrement
404 * @pre iterator is incrementable
408 operator++(int) _GLIBCXX_NOEXCEPT
410 if (!std::__is_constant_evaluated())
412 _GLIBCXX_DEBUG_VERIFY(this->_M_incrementable(),
413 _M_message(__msg_bad_inc
)
414 ._M_iterator(*this, "this"));
416 _Safe_iterator
__ret(*this, _Unchecked());
421 // ------ Utilities ------
423 /// Determine if this is a constant iterator.
424 static _GLIBCXX_CONSTEXPR
bool
426 { return _IsConstant::__value
; }
429 * @brief Return the underlying iterator
433 base() _GLIBCXX_NOEXCEPT
{ return *this; }
437 base() const _GLIBCXX_NOEXCEPT
{ return *this; }
440 * @brief Conversion to underlying non-debug iterator to allow
441 * better interaction with non-debug containers.
444 operator _Iterator() const _GLIBCXX_NOEXCEPT
{ return *this; }
446 /** Attach iterator to the given sequence. */
448 _M_attach(_Safe_sequence_base
* __seq
)
449 { _Safe_base::_M_attach(__seq
, _S_constant()); }
451 /** Likewise, but not thread-safe. */
453 _M_attach_single(_Safe_sequence_base
* __seq
)
454 { _Safe_base::_M_attach_single(__seq
, _S_constant()); }
456 /// Is the iterator dereferenceable?
458 _M_dereferenceable() const
459 { return !this->_M_singular() && !_M_is_end() && !_M_is_before_begin(); }
461 /// Is the iterator before a dereferenceable one?
463 _M_before_dereferenceable() const
465 if (this->_M_incrementable())
467 _Iterator __base
= base();
468 return ++__base
!= _M_get_sequence()->_M_base().end();
473 /// Is the iterator incrementable?
475 _M_incrementable() const
476 { return !this->_M_singular() && !_M_is_end(); }
478 /// Is the iterator value-initialized?
480 _M_value_initialized() const
481 { return _M_version
== 0 && base() == _Iter_base(); }
483 // Can we advance the iterator @p __n steps (@p __n may be negative)
485 _M_can_advance(difference_type __n
, bool __strict
= false) const;
487 // Can we advance the iterator using @p __dist in @p __way direction.
488 template<typename _Diff
>
490 _M_can_advance(const std::pair
<_Diff
, _Distance_precision
>& __dist
,
493 // Is the iterator range [*this, __rhs) valid?
495 _M_valid_range(const _Safe_iterator
& __rhs
,
496 std::pair
<difference_type
, _Distance_precision
>& __dist
,
497 bool __check_dereferenceable
= true) const;
499 // The sequence this iterator references.
500 typename
__gnu_cxx::__conditional_type
<
501 _IsConstant::__value
, const _Sequence
*, _Sequence
*>::__type
502 _M_get_sequence() const
503 { return static_cast<_Sequence
*>(_M_sequence
); }
505 // Get distance to __rhs.
506 typename _Distance_traits
<_Iterator
>::__type
507 _M_get_distance_to(const _Safe_iterator
& __rhs
) const;
509 // Get distance from sequence begin up to *this.
510 typename _Distance_traits
<_Iterator
>::__type
511 _M_get_distance_from_begin() const;
513 // Get distance from *this to sequence end.
514 typename _Distance_traits
<_Iterator
>::__type
515 _M_get_distance_to_end() const;
517 /// Is this iterator equal to the sequence's begin() iterator?
521 { return base() == _M_get_sequence()->_M_base().begin(); }
523 /// Is this iterator equal to the sequence's end() iterator?
526 { return base() == _M_get_sequence()->_M_base().end(); }
528 /// Is this iterator equal to the sequence's before_begin() iterator if
531 _M_is_before_begin() const
532 { return _BeforeBeginHelper
<_Sequence
>::_S_Is(*this); }
534 /// Is this iterator equal to the sequence's before_begin() iterator if
535 /// any or begin() otherwise?
537 _M_is_beginnest() const
538 { return _BeforeBeginHelper
<_Sequence
>::_S_Is_Beginnest(*this); }
540 // ------ Operators ------
542 typedef _Safe_iterator
<_Iterator
, _Sequence
, iterator_category
> _Self
;
547 operator==(const _Self
& __lhs
, const _Self
& __rhs
) _GLIBCXX_NOEXCEPT
549 _GLIBCXX_DEBUG_VERIFY_EQ_OPERANDS(__lhs
, __rhs
);
550 return __lhs
.base() == __rhs
.base();
553 template<typename _IteR
>
557 operator==(const _Self
& __lhs
,
558 const _Safe_iterator
<_IteR
, _Sequence
, iterator_category
>& __rhs
)
561 _GLIBCXX_DEBUG_VERIFY_EQ_OPERANDS(__lhs
, __rhs
);
562 return __lhs
.base() == __rhs
.base();
565 #if ! __cpp_lib_three_way_comparison
568 operator!=(const _Self
& __lhs
, const _Self
& __rhs
) _GLIBCXX_NOEXCEPT
570 _GLIBCXX_DEBUG_VERIFY_EQ_OPERANDS(__lhs
, __rhs
);
571 return __lhs
.base() != __rhs
.base();
574 template<typename _IteR
>
577 operator!=(const _Self
& __lhs
,
578 const _Safe_iterator
<_IteR
, _Sequence
, iterator_category
>& __rhs
)
581 _GLIBCXX_DEBUG_VERIFY_EQ_OPERANDS(__lhs
, __rhs
);
582 return __lhs
.base() != __rhs
.base();
584 #endif // three-way comparison
587 template<typename _Iterator
, typename _Sequence
>
588 class _Safe_iterator
<_Iterator
, _Sequence
, std::bidirectional_iterator_tag
>
589 : public _Safe_iterator
<_Iterator
, _Sequence
, std::forward_iterator_tag
>
591 typedef _Safe_iterator
<_Iterator
, _Sequence
,
592 std::forward_iterator_tag
> _Safe_base
;
595 typedef typename
_Safe_base::_OtherIterator _OtherIterator
;
597 typedef typename
_Safe_base::_Unchecked _Unchecked
;
600 _Safe_iterator(const _Safe_iterator
& __x
,
601 _Unchecked __unchecked
) _GLIBCXX_NOEXCEPT
602 : _Safe_base(__x
, __unchecked
)
606 /// @post the iterator is singular and unattached
608 _Safe_iterator() _GLIBCXX_NOEXCEPT
{ }
611 * @brief Safe iterator construction from an unsafe iterator and
614 * @pre @p seq is not NULL
615 * @post this is not singular
618 _Safe_iterator(_Iterator __i
, const _Safe_sequence_base
* __seq
)
620 : _Safe_base(__i
, __seq
)
624 * @brief Copy construction.
627 _Safe_iterator(const _Safe_iterator
& __x
) _GLIBCXX_NOEXCEPT
631 #if __cplusplus >= 201103L
632 /** @brief Move construction. */
634 _Safe_iterator(_Safe_iterator
&&) = default;
638 * @brief Converting constructor from a mutable iterator to a
641 template<typename _MutableIterator
>
644 const _Safe_iterator
<_MutableIterator
, _Sequence
,
645 typename
__gnu_cxx::__enable_if
<_Safe_base::_IsConstant::__value
&&
646 std::__are_same
<_MutableIterator
, _OtherIterator
>::__value
,
647 std::bidirectional_iterator_tag
>::__type
>& __x
)
652 #if __cplusplus >= 201103L
653 /** @brief Copy assignment. */
655 operator=(const _Safe_iterator
&) = default;
657 /** @brief Move assignment. */
659 operator=(_Safe_iterator
&&) = default;
661 /** @brief Copy assignment. */
663 operator=(const _Safe_iterator
& __x
)
665 _Safe_base::operator=(__x
);
670 // ------ Input iterator requirements ------
672 * @brief Iterator preincrement
673 * @pre iterator is incrementable
677 operator++() _GLIBCXX_NOEXCEPT
679 _Safe_base::operator++();
684 * @brief Iterator postincrement
685 * @pre iterator is incrementable
688 operator++(int) _GLIBCXX_NOEXCEPT
690 _GLIBCXX_DEBUG_VERIFY(this->_M_incrementable(),
691 _M_message(__msg_bad_inc
)
692 ._M_iterator(*this, "this"));
693 _Safe_iterator
__ret(*this, _Unchecked());
698 // ------ Bidirectional iterator requirements ------
700 * @brief Iterator predecrement
701 * @pre iterator is decrementable
705 operator--() _GLIBCXX_NOEXCEPT
707 if (std::__is_constant_evaluated())
713 _GLIBCXX_DEBUG_VERIFY(this->_M_decrementable(),
714 _M_message(__msg_bad_dec
)
715 ._M_iterator(*this, "this"));
716 _GLIBCXX20_CONSTEXPR_NON_LITERAL_SCOPE_BEGIN
{
717 __gnu_cxx::__scoped_lock
__l(this->_M_get_mutex());
719 } _GLIBCXX20_CONSTEXPR_NON_LITERAL_SCOPE_END
724 * @brief Iterator postdecrement
725 * @pre iterator is decrementable
728 operator--(int) _GLIBCXX_NOEXCEPT
730 _GLIBCXX_DEBUG_VERIFY(this->_M_decrementable(),
731 _M_message(__msg_bad_dec
)
732 ._M_iterator(*this, "this"));
733 _Safe_iterator
__ret(*this, _Unchecked());
738 // ------ Utilities ------
740 // Is the iterator decrementable?
742 _M_decrementable() const
743 { return !this->_M_singular() && !this->_M_is_begin(); }
746 template<typename _Iterator
, typename _Sequence
>
747 class _Safe_iterator
<_Iterator
, _Sequence
, std::random_access_iterator_tag
>
748 : public _Safe_iterator
<_Iterator
, _Sequence
,
749 std::bidirectional_iterator_tag
>
751 typedef _Safe_iterator
<_Iterator
, _Sequence
,
752 std::bidirectional_iterator_tag
> _Safe_base
;
753 typedef typename
_Safe_base::_OtherIterator _OtherIterator
;
755 typedef typename
_Safe_base::_Self _Self
;
756 typedef _Safe_iterator
<_OtherIterator
, _Sequence
,
757 std::random_access_iterator_tag
> _OtherSelf
;
759 typedef typename
_Safe_base::_Unchecked _Unchecked
;
762 _Safe_iterator(const _Safe_iterator
& __x
,
763 _Unchecked __unchecked
) _GLIBCXX_NOEXCEPT
764 : _Safe_base(__x
, __unchecked
)
768 typedef typename
_Safe_base::difference_type difference_type
;
769 typedef typename
_Safe_base::reference reference
;
771 /// @post the iterator is singular and unattached
773 _Safe_iterator() _GLIBCXX_NOEXCEPT
{ }
776 * @brief Safe iterator construction from an unsafe iterator and
779 * @pre @p seq is not NULL
780 * @post this is not singular
783 _Safe_iterator(_Iterator __i
, const _Safe_sequence_base
* __seq
)
785 : _Safe_base(__i
, __seq
)
789 * @brief Copy construction.
792 _Safe_iterator(const _Safe_iterator
& __x
) _GLIBCXX_NOEXCEPT
796 #if __cplusplus >= 201103L
797 /** @brief Move construction. */
798 _Safe_iterator(_Safe_iterator
&&) = default;
802 * @brief Converting constructor from a mutable iterator to a
805 template<typename _MutableIterator
>
808 const _Safe_iterator
<_MutableIterator
, _Sequence
,
809 typename
__gnu_cxx::__enable_if
<_Safe_base::_IsConstant::__value
&&
810 std::__are_same
<_MutableIterator
, _OtherIterator
>::__value
,
811 std::random_access_iterator_tag
>::__type
>& __x
)
816 #if __cplusplus >= 201103L
817 /** @brief Copy assignment. */
819 operator=(const _Safe_iterator
&) = default;
821 /** @brief Move assignment. */
823 operator=(_Safe_iterator
&&) = default;
825 /** @brief Copy assignment. */
827 operator=(const _Safe_iterator
& __x
)
829 _Safe_base::operator=(__x
);
834 // Is the iterator range [*this, __rhs) valid?
836 _M_valid_range(const _Safe_iterator
& __rhs
,
837 std::pair
<difference_type
,
838 _Distance_precision
>& __dist
) const;
840 // ------ Input iterator requirements ------
842 * @brief Iterator preincrement
843 * @pre iterator is incrementable
847 operator++() _GLIBCXX_NOEXCEPT
849 _Safe_base::operator++();
854 * @brief Iterator postincrement
855 * @pre iterator is incrementable
859 operator++(int) _GLIBCXX_NOEXCEPT
861 if (!std::__is_constant_evaluated())
863 _GLIBCXX_DEBUG_VERIFY(this->_M_incrementable(),
864 _M_message(__msg_bad_inc
)
865 ._M_iterator(*this, "this"));
867 _Safe_iterator
__ret(*this, _Unchecked());
872 // ------ Bidirectional iterator requirements ------
874 * @brief Iterator predecrement
875 * @pre iterator is decrementable
879 operator--() _GLIBCXX_NOEXCEPT
881 _Safe_base::operator--();
886 * @brief Iterator postdecrement
887 * @pre iterator is decrementable
891 operator--(int) _GLIBCXX_NOEXCEPT
893 if (!std::__is_constant_evaluated())
895 _GLIBCXX_DEBUG_VERIFY(this->_M_decrementable(),
896 _M_message(__msg_bad_dec
)
897 ._M_iterator(*this, "this"));
899 _Safe_iterator
__ret(*this, _Unchecked());
904 // ------ Random access iterator requirements ------
908 operator[](difference_type __n
) const _GLIBCXX_NOEXCEPT
910 if (!std::__is_constant_evaluated())
912 _GLIBCXX_DEBUG_VERIFY(this->_M_can_advance(__n
)
913 && this->_M_can_advance(__n
+ 1),
914 _M_message(__msg_iter_subscript_oob
)
915 ._M_iterator(*this)._M_integer(__n
));
917 return this->base()[__n
];
922 operator+=(difference_type __n
) _GLIBCXX_NOEXCEPT
924 if (std::__is_constant_evaluated())
930 _GLIBCXX_DEBUG_VERIFY(this->_M_can_advance(__n
),
931 _M_message(__msg_advance_oob
)
932 ._M_iterator(*this)._M_integer(__n
));
933 _GLIBCXX20_CONSTEXPR_NON_LITERAL_SCOPE_BEGIN
{
934 __gnu_cxx::__scoped_lock
__l(this->_M_get_mutex());
936 } _GLIBCXX20_CONSTEXPR_NON_LITERAL_SCOPE_END
942 operator-=(difference_type __n
) _GLIBCXX_NOEXCEPT
944 if (std::__is_constant_evaluated())
950 _GLIBCXX_DEBUG_VERIFY(this->_M_can_advance(-__n
),
951 _M_message(__msg_retreat_oob
)
952 ._M_iterator(*this)._M_integer(__n
));
953 _GLIBCXX20_CONSTEXPR_NON_LITERAL_SCOPE_BEGIN
{
954 __gnu_cxx::__scoped_lock
__l(this->_M_get_mutex());
956 } _GLIBCXX20_CONSTEXPR_NON_LITERAL_SCOPE_END
960 #if __cpp_lib_three_way_comparison
964 operator<=>(const _Self
& __lhs
, const _Self
& __rhs
) noexcept
966 _GLIBCXX_DEBUG_VERIFY_REL_OPERANDS(__lhs
, __rhs
);
967 return __lhs
.base() <=> __rhs
.base();
973 operator<=>(const _Self
& __lhs
, const _OtherSelf
& __rhs
) noexcept
975 _GLIBCXX_DEBUG_VERIFY_REL_OPERANDS(__lhs
, __rhs
);
976 return __lhs
.base() <=> __rhs
.base();
981 operator<(const _Self
& __lhs
, const _Self
& __rhs
) _GLIBCXX_NOEXCEPT
983 _GLIBCXX_DEBUG_VERIFY_REL_OPERANDS(__lhs
, __rhs
);
984 return __lhs
.base() < __rhs
.base();
989 operator<(const _Self
& __lhs
, const _OtherSelf
& __rhs
) _GLIBCXX_NOEXCEPT
991 _GLIBCXX_DEBUG_VERIFY_REL_OPERANDS(__lhs
, __rhs
);
992 return __lhs
.base() < __rhs
.base();
997 operator<=(const _Self
& __lhs
, const _Self
& __rhs
) _GLIBCXX_NOEXCEPT
999 _GLIBCXX_DEBUG_VERIFY_REL_OPERANDS(__lhs
, __rhs
);
1000 return __lhs
.base() <= __rhs
.base();
1005 operator<=(const _Self
& __lhs
, const _OtherSelf
& __rhs
) _GLIBCXX_NOEXCEPT
1007 _GLIBCXX_DEBUG_VERIFY_REL_OPERANDS(__lhs
, __rhs
);
1008 return __lhs
.base() <= __rhs
.base();
1013 operator>(const _Self
& __lhs
, const _Self
& __rhs
) _GLIBCXX_NOEXCEPT
1015 _GLIBCXX_DEBUG_VERIFY_REL_OPERANDS(__lhs
, __rhs
);
1016 return __lhs
.base() > __rhs
.base();
1021 operator>(const _Self
& __lhs
, const _OtherSelf
& __rhs
) _GLIBCXX_NOEXCEPT
1023 _GLIBCXX_DEBUG_VERIFY_REL_OPERANDS(__lhs
, __rhs
);
1024 return __lhs
.base() > __rhs
.base();
1029 operator>=(const _Self
& __lhs
, const _Self
& __rhs
) _GLIBCXX_NOEXCEPT
1031 _GLIBCXX_DEBUG_VERIFY_REL_OPERANDS(__lhs
, __rhs
);
1032 return __lhs
.base() >= __rhs
.base();
1037 operator>=(const _Self
& __lhs
, const _OtherSelf
& __rhs
) _GLIBCXX_NOEXCEPT
1039 _GLIBCXX_DEBUG_VERIFY_REL_OPERANDS(__lhs
, __rhs
);
1040 return __lhs
.base() >= __rhs
.base();
1042 #endif // three-way comparison
1044 // _GLIBCXX_RESOLVE_LIB_DEFECTS
1045 // According to the resolution of DR179 not only the various comparison
1046 // operators but also operator- must accept mixed iterator/const_iterator
1049 _GLIBCXX20_CONSTEXPR
1050 friend difference_type
1051 operator-(const _Self
& __lhs
, const _OtherSelf
& __rhs
) _GLIBCXX_NOEXCEPT
1053 _GLIBCXX_DEBUG_VERIFY_DIST_OPERANDS(__lhs
, __rhs
);
1054 return __lhs
.base() - __rhs
.base();
1058 _GLIBCXX20_CONSTEXPR
1059 friend difference_type
1060 operator-(const _Self
& __lhs
, const _Self
& __rhs
) _GLIBCXX_NOEXCEPT
1062 _GLIBCXX_DEBUG_VERIFY_DIST_OPERANDS(__lhs
, __rhs
);
1063 return __lhs
.base() - __rhs
.base();
1067 _GLIBCXX20_CONSTEXPR
1069 operator+(const _Self
& __x
, difference_type __n
) _GLIBCXX_NOEXCEPT
1071 if (!std::__is_constant_evaluated())
1073 _GLIBCXX_DEBUG_VERIFY(__x
._M_can_advance(__n
),
1074 _M_message(__msg_advance_oob
)
1075 ._M_iterator(__x
)._M_integer(__n
));
1077 return _Safe_iterator(__x
.base() + __n
, __x
._M_sequence
);
1081 _GLIBCXX20_CONSTEXPR
1083 operator+(difference_type __n
, const _Self
& __x
) _GLIBCXX_NOEXCEPT
1085 if (!std::__is_constant_evaluated())
1087 _GLIBCXX_DEBUG_VERIFY(__x
._M_can_advance(__n
),
1088 _M_message(__msg_advance_oob
)
1089 ._M_iterator(__x
)._M_integer(__n
));
1091 return _Safe_iterator(__n
+ __x
.base(), __x
._M_sequence
);
1095 _GLIBCXX20_CONSTEXPR
1097 operator-(const _Self
& __x
, difference_type __n
) _GLIBCXX_NOEXCEPT
1099 if (!std::__is_constant_evaluated())
1101 _GLIBCXX_DEBUG_VERIFY(__x
._M_can_advance(-__n
),
1102 _M_message(__msg_retreat_oob
)
1103 ._M_iterator(__x
)._M_integer(__n
));
1105 return _Safe_iterator(__x
.base() - __n
, __x
._M_sequence
);
1109 /** Safe iterators know how to check if they form a valid range. */
1110 template<typename _Iterator
, typename _Sequence
, typename _Category
>
1112 __valid_range(const _Safe_iterator
<_Iterator
, _Sequence
,
1113 _Category
>& __first
,
1114 const _Safe_iterator
<_Iterator
, _Sequence
,
1116 typename _Distance_traits
<_Iterator
>::__type
& __dist
)
1117 { return __first
._M_valid_range(__last
, __dist
); }
1119 template<typename _Iterator
, typename _Sequence
, typename _Category
>
1121 __valid_range(const _Safe_iterator
<_Iterator
, _Sequence
,
1122 _Category
>& __first
,
1123 const _Safe_iterator
<_Iterator
, _Sequence
,
1126 typename _Distance_traits
<_Iterator
>::__type __dist
;
1127 return __first
._M_valid_range(__last
, __dist
);
1130 template<typename _Iterator
, typename _Sequence
, typename _Category
,
1133 __can_advance(const _Safe_iterator
<_Iterator
, _Sequence
, _Category
>& __it
,
1135 { return __it
._M_can_advance(__n
); }
1137 template<typename _Iterator
, typename _Sequence
, typename _Category
,
1140 __can_advance(const _Safe_iterator
<_Iterator
, _Sequence
, _Category
>& __it
,
1141 const std::pair
<_Diff
, _Distance_precision
>& __dist
,
1143 { return __it
._M_can_advance(__dist
, __way
); }
1145 template<typename _Iterator
, typename _Sequence
>
1147 __base(const _Safe_iterator
<_Iterator
, _Sequence
,
1148 std::random_access_iterator_tag
>& __it
)
1149 { return __it
.base(); }
1151 #if __cplusplus < 201103L
1152 template<typename _Iterator
, typename _Sequence
>
1153 struct _Unsafe_type
<_Safe_iterator
<_Iterator
, _Sequence
> >
1154 { typedef _Iterator _Type
; };
1157 template<typename _Iterator
, typename _Sequence
>
1159 __unsafe(const _Safe_iterator
<_Iterator
, _Sequence
>& __it
)
1160 { return __it
.base(); }
1162 } // namespace __gnu_debug
1164 #if __cplusplus >= 201103L && __cplusplus <= 201703L
1165 namespace std
_GLIBCXX_VISIBILITY(default)
1167 _GLIBCXX_BEGIN_NAMESPACE_VERSION
1169 template<typename _Iterator
, typename _Container
, typename _Sequence
>
1171 __to_address(const __gnu_debug::_Safe_iterator
<
1172 __gnu_cxx::__normal_iterator
<_Iterator
, _Container
>,
1173 _Sequence
>& __it
) noexcept
1174 -> decltype(std::__to_address(__it
.base().base()))
1175 { return std::__to_address(__it
.base().base()); }
1177 _GLIBCXX_END_NAMESPACE_VERSION
1181 #undef _GLIBCXX20_CONSTEXPR_NON_LITERAL_SCOPE_END
1182 #undef _GLIBCXX20_CONSTEXPR_NON_LITERAL_SCOPE_BEGIN
1183 #undef _GLIBCXX_DEBUG_VERIFY_DIST_OPERANDS
1184 #undef _GLIBCXX_DEBUG_VERIFY_REL_OPERANDS
1185 #undef _GLIBCXX_DEBUG_VERIFY_EQ_OPERANDS
1186 #undef _GLIBCXX_DEBUG_VERIFY_OPERANDS
1188 #include <debug/safe_iterator.tcc>