libstdc++
safe_iterator.h
Go to the documentation of this file.
1// Safe iterator implementation -*- C++ -*-
2
3// Copyright (C) 2003-2024 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/safe_iterator.h
26 * This file is a GNU debug extension to the Standard C++ Library.
27 */
28
29#ifndef _GLIBCXX_DEBUG_SAFE_ITERATOR_H
30#define _GLIBCXX_DEBUG_SAFE_ITERATOR_H 1
31
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
39# include <compare>
40#endif
41
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)); \
54 }
55
56#define _GLIBCXX_DEBUG_VERIFY_EQ_OPERANDS(_Lhs, _Rhs) \
57 _GLIBCXX_DEBUG_VERIFY_OPERANDS(_Lhs, _Rhs, __msg_iter_compare_bad, \
58 __msg_compare_different)
59
60#define _GLIBCXX_DEBUG_VERIFY_REL_OPERANDS(_Lhs, _Rhs) \
61 _GLIBCXX_DEBUG_VERIFY_OPERANDS(_Lhs, _Rhs, __msg_iter_order_bad, \
62 __msg_order_different)
63
64#define _GLIBCXX_DEBUG_VERIFY_DIST_OPERANDS(_Lhs, _Rhs) \
65 _GLIBCXX_DEBUG_VERIFY_OPERANDS(_Lhs, _Rhs, __msg_distance_bad, \
66 __msg_distance_different)
67
68namespace __gnu_debug
69{
70 /** Helper struct to deal with sequence offering a before_begin
71 * iterator.
72 **/
73 template<typename _Sequence>
75 {
76 template<typename _Iterator, typename _Category>
77 static bool
79 { return false; }
80
81 template<typename _Iterator, typename _Category>
82 static bool
83 _S_Is_Beginnest(const _Safe_iterator<_Iterator, _Sequence, _Category>& __it)
84 { return __it.base() == __it._M_get_sequence()->_M_base().begin(); }
85 };
86
87 /** Sequence traits giving the size of a container if possible. */
88 template<typename _Sequence>
90 {
91 typedef _Distance_traits<typename _Sequence::iterator> _DistTraits;
92
93 static typename _DistTraits::__type
94 _S_size(const _Sequence& __seq)
95 { return std::make_pair(__seq.size(), __dp_exact); }
96 };
97
98 /** \brief Safe iterator wrapper.
99 *
100 * The class template %_Safe_iterator is a wrapper around an
101 * iterator that tracks the iterator's movement among sequences and
102 * checks that operations performed on the "safe" iterator are
103 * legal. In additional to the basic iterator operations (which are
104 * validated, and then passed to the underlying iterator),
105 * %_Safe_iterator has member functions for iterator invalidation,
106 * attaching/detaching the iterator from sequences, and querying
107 * the iterator's state.
108 *
109 * Note that _Iterator must be the first base class so that it gets
110 * initialized before the iterator is being attached to the container's list
111 * of iterators and it is being detached before _Iterator get
112 * destroyed. Otherwise it would result in a data race.
113 */
114 template<typename _Iterator, typename _Sequence, typename _Category
117 : private _Iterator,
119 {
120 typedef _Iterator _Iter_base;
122
124
125 protected:
126 typedef std::__are_same<typename _Sequence::_Base::const_iterator,
127 _Iterator> _IsConstant;
128
129 typedef typename __gnu_cxx::__conditional_type<
130 _IsConstant::__value,
131 typename _Sequence::_Base::iterator,
132 typename _Sequence::_Base::const_iterator>::__type _OtherIterator;
133
134 struct _Unchecked { };
135
136 _GLIBCXX20_CONSTEXPR
137 _Safe_iterator(const _Safe_iterator& __x, _Unchecked) _GLIBCXX_NOEXCEPT
138 : _Iter_base(__x.base()), _Safe_base()
139 {
140 if (!std::__is_constant_evaluated())
142 }
143
144 public:
145 typedef _Iterator iterator_type;
146 typedef typename _Traits::iterator_category iterator_category;
147 typedef typename _Traits::value_type value_type;
148 typedef typename _Traits::difference_type difference_type;
149 typedef typename _Traits::reference reference;
150 typedef typename _Traits::pointer pointer;
151
152#if __cplusplus > 201703L && __cpp_lib_concepts
153 using iterator_concept = std::__detail::__iter_concept<_Iterator>;
154#endif
155
156 /// @post the iterator is singular and unattached
157 _GLIBCXX20_CONSTEXPR
158 _Safe_iterator() _GLIBCXX_NOEXCEPT : _Iter_base() { }
159
160 /**
161 * @brief Safe iterator construction from an unsafe iterator and
162 * its sequence.
163 *
164 * @pre @p seq is not NULL
165 * @post this is not singular
166 */
167 _GLIBCXX20_CONSTEXPR
168 _Safe_iterator(_Iterator __i, const _Safe_sequence_base* __seq)
169 _GLIBCXX_NOEXCEPT
170 : _Iter_base(__i), _Safe_base(__seq, _S_constant())
171 { }
172
173 /**
174 * @brief Copy construction.
175 */
176 _GLIBCXX20_CONSTEXPR
177 _Safe_iterator(const _Safe_iterator& __x) _GLIBCXX_NOEXCEPT
178 : _Iter_base(__x.base()), _Safe_base()
179 {
180 if (std::__is_constant_evaluated())
181 return;
182
183 // _GLIBCXX_RESOLVE_LIB_DEFECTS
184 // DR 408. Is vector<reverse_iterator<char*> > forbidden?
185 _GLIBCXX_DEBUG_VERIFY(!__x._M_singular()
186 || __x._M_value_initialized(),
187 _M_message(__msg_init_copy_singular)
188 ._M_iterator(*this, "this")
189 ._M_iterator(__x, "other"));
191 }
192
193#if __cplusplus >= 201103L
194 /**
195 * @brief Move construction.
196 * @post __x is singular and unattached
197 */
198 _GLIBCXX20_CONSTEXPR
200 : _Iter_base()
201 {
202 if (std::__is_constant_evaluated())
203 {
204 base() = __x.base();
205 return;
206 }
207
208 _GLIBCXX_DEBUG_VERIFY(!__x._M_singular()
209 || __x._M_value_initialized(),
210 _M_message(__msg_init_copy_singular)
211 ._M_iterator(*this, "this")
212 ._M_iterator(__x, "other"));
213 _Safe_sequence_base* __seq = __x._M_sequence;
214 __x._M_detach();
215 std::swap(base(), __x.base());
216 _M_attach(__seq);
217 }
218#endif
219
220 /**
221 * @brief Converting constructor from a mutable iterator to a
222 * constant iterator.
223 */
224 template<typename _MutableIterator>
225 _GLIBCXX20_CONSTEXPR
227 const _Safe_iterator<_MutableIterator, _Sequence,
228 typename __gnu_cxx::__enable_if<_IsConstant::__value &&
229 std::__are_same<_MutableIterator, _OtherIterator>::__value,
230 _Category>::__type>& __x)
231 _GLIBCXX_NOEXCEPT
232 : _Iter_base(__x.base())
233 {
234 if (std::__is_constant_evaluated())
235 return;
236
237 // _GLIBCXX_RESOLVE_LIB_DEFECTS
238 // DR 408. Is vector<reverse_iterator<char*> > forbidden?
239 _GLIBCXX_DEBUG_VERIFY(!__x._M_singular()
240 || __x._M_value_initialized(),
241 _M_message(__msg_init_const_singular)
242 ._M_iterator(*this, "this")
243 ._M_iterator(__x, "other"));
245 }
246
247 /**
248 * @brief Copy assignment.
249 */
250 _GLIBCXX20_CONSTEXPR
252 operator=(const _Safe_iterator& __x) _GLIBCXX_NOEXCEPT
253 {
254 if (std::__is_constant_evaluated())
255 {
256 base() = __x.base();
257 return *this;
258 }
259
260 // _GLIBCXX_RESOLVE_LIB_DEFECTS
261 // DR 408. Is vector<reverse_iterator<char*> > forbidden?
262 _GLIBCXX_DEBUG_VERIFY(!__x._M_singular()
263 || __x._M_value_initialized(),
264 _M_message(__msg_copy_singular)
265 ._M_iterator(*this, "this")
266 ._M_iterator(__x, "other"));
267
268 if (this->_M_sequence && this->_M_sequence == __x._M_sequence)
269 {
271 base() = __x.base();
273 }
274 else
275 {
276 _M_detach();
277 base() = __x.base();
279 }
280
281 return *this;
282 }
283
284#if __cplusplus >= 201103L
285 /**
286 * @brief Move assignment.
287 * @post __x is singular and unattached
288 */
289 _GLIBCXX20_CONSTEXPR
291 operator=(_Safe_iterator&& __x) noexcept
292 {
293 if (std::__is_constant_evaluated())
294 {
295 base() = __x.base();
296 return *this;
297 }
298
299 _GLIBCXX_DEBUG_VERIFY(!__x._M_singular()
300 || __x._M_value_initialized(),
301 _M_message(__msg_copy_singular)
302 ._M_iterator(*this, "this")
303 ._M_iterator(__x, "other"));
304
305 if (std::__addressof(__x) == this)
306 return *this;
307
308 if (this->_M_sequence && this->_M_sequence == __x._M_sequence)
309 {
311 base() = __x.base();
313 }
314 else
315 {
316 _M_detach();
317 base() = __x.base();
319 }
320
321 __x._M_detach();
322 __x.base() = _Iterator();
323 return *this;
324 }
325#endif
326
327 /**
328 * @brief Iterator dereference.
329 * @pre iterator is dereferenceable
330 */
331 _GLIBCXX_NODISCARD
332 _GLIBCXX20_CONSTEXPR
333 reference
334 operator*() const _GLIBCXX_NOEXCEPT
335 {
336 if (!std::__is_constant_evaluated())
337 {
338 _GLIBCXX_DEBUG_VERIFY(this->_M_dereferenceable(),
339 _M_message(__msg_bad_deref)
340 ._M_iterator(*this, "this"));
341 }
342 return *base();
343 }
344
345 /**
346 * @brief Iterator dereference.
347 * @pre iterator is dereferenceable
348 */
349 _GLIBCXX_NODISCARD
350 _GLIBCXX20_CONSTEXPR
351 pointer
352 operator->() const _GLIBCXX_NOEXCEPT
353 {
354 if (!std::__is_constant_evaluated())
355 {
356 _GLIBCXX_DEBUG_VERIFY(this->_M_dereferenceable(),
357 _M_message(__msg_bad_deref)
358 ._M_iterator(*this, "this"));
359 }
360 return base().operator->();
361 }
362
363 // ------ Input iterator requirements ------
364 /**
365 * @brief Iterator preincrement
366 * @pre iterator is incrementable
367 */
368 _GLIBCXX20_CONSTEXPR
370 operator++() _GLIBCXX_NOEXCEPT
371 {
372 if (std::__is_constant_evaluated())
373 {
374 ++base();
375 return *this;
376 }
377
378 _GLIBCXX_DEBUG_VERIFY(this->_M_incrementable(),
379 _M_message(__msg_bad_inc)
380 ._M_iterator(*this, "this"));
382 ++base();
383 return *this;
384 }
385
386 /**
387 * @brief Iterator postincrement
388 * @pre iterator is incrementable
389 */
390 _GLIBCXX20_CONSTEXPR
392 operator++(int) _GLIBCXX_NOEXCEPT
393 {
394 if (!std::__is_constant_evaluated())
395 {
396 _GLIBCXX_DEBUG_VERIFY(this->_M_incrementable(),
397 _M_message(__msg_bad_inc)
398 ._M_iterator(*this, "this"));
399 }
400 _Safe_iterator __ret(*this, _Unchecked());
401 ++*this;
402 return __ret;
403 }
404
405 // ------ Utilities ------
406
407 /// Determine if this is a constant iterator.
408 static _GLIBCXX_CONSTEXPR bool
410 { return _IsConstant::__value; }
411
412 /**
413 * @brief Return the underlying iterator
414 */
415 _GLIBCXX20_CONSTEXPR
416 _Iterator&
417 base() _GLIBCXX_NOEXCEPT { return *this; }
418
419 _GLIBCXX20_CONSTEXPR
420 const _Iterator&
421 base() const _GLIBCXX_NOEXCEPT { return *this; }
422
423 /**
424 * @brief Conversion to underlying non-debug iterator to allow
425 * better interaction with non-debug containers.
426 */
427 _GLIBCXX20_CONSTEXPR
428 operator _Iterator() const _GLIBCXX_NOEXCEPT { return *this; }
429
430 /** Attach iterator to the given sequence. */
431 void
434
435 /** Likewise, but not thread-safe. */
436 void
439
440 /// Is the iterator dereferenceable?
441 bool
443 { return !this->_M_singular() && !_M_is_end() && !_M_is_before_begin(); }
444
445 /// Is the iterator before a dereferenceable one?
446 bool
448 {
449 if (this->_M_incrementable())
450 {
451 _Iterator __base = base();
452 return ++__base != _M_get_sequence()->_M_base().end();
453 }
454 return false;
455 }
456
457 /// Is the iterator incrementable?
458 bool
460 { return !this->_M_singular() && !_M_is_end(); }
461
462 /// Is the iterator value-initialized?
463 bool
465 { return _M_version == 0 && base() == _Iter_base(); }
466
467 // Can we advance the iterator @p __n steps (@p __n may be negative)
468 bool
469 _M_can_advance(difference_type __n, bool __strict = false) const;
470
471 // Can we advance the iterator using @p __dist in @p __way direction.
472 template<typename _Diff>
473 bool
474 _M_can_advance(const std::pair<_Diff, _Distance_precision>& __dist,
475 int __way) const;
476
477 // Is the iterator range [*this, __rhs) valid?
478 bool
479 _M_valid_range(const _Safe_iterator& __rhs,
481 bool __check_dereferenceable = true) const;
482
483 // The sequence this iterator references.
484 typename __gnu_cxx::__conditional_type<
485 _IsConstant::__value, const _Sequence*, _Sequence*>::__type
486 _M_get_sequence() const
487 { return static_cast<_Sequence*>(_M_sequence); }
488
489 // Get distance to __rhs.
490 typename _Distance_traits<_Iterator>::__type
491 _M_get_distance_to(const _Safe_iterator& __rhs) const;
492
493 // Get distance from sequence begin up to *this.
494 typename _Distance_traits<_Iterator>::__type
495 _M_get_distance_from_begin() const;
496
497 // Get distance from *this to sequence end.
498 typename _Distance_traits<_Iterator>::__type
499 _M_get_distance_to_end() const;
500
501 /// Is this iterator equal to the sequence's begin() iterator?
502 _GLIBCXX20_CONSTEXPR
503 bool
505 { return base() == _M_get_sequence()->_M_base().begin(); }
506
507 /// Is this iterator equal to the sequence's end() iterator?
508 bool
509 _M_is_end() const
510 { return base() == _M_get_sequence()->_M_base().end(); }
511
512 /// Is this iterator equal to the sequence's before_begin() iterator if
513 /// any?
514 bool
517
518 /// Is this iterator equal to the sequence's before_begin() iterator if
519 /// any or begin() otherwise?
520 bool
523
524 // ------ Operators ------
525
527
528 _GLIBCXX_NODISCARD
529 _GLIBCXX20_CONSTEXPR
530 friend bool
531 operator==(const _Self& __lhs, const _Self& __rhs) _GLIBCXX_NOEXCEPT
532 {
533 _GLIBCXX_DEBUG_VERIFY_EQ_OPERANDS(__lhs, __rhs);
534 return __lhs.base() == __rhs.base();
535 }
536
537 template<typename _IteR>
538 _GLIBCXX_NODISCARD
539 _GLIBCXX20_CONSTEXPR
540 friend bool
541 operator==(const _Self& __lhs,
542 const _Safe_iterator<_IteR, _Sequence, iterator_category>& __rhs)
543 _GLIBCXX_NOEXCEPT
544 {
545 _GLIBCXX_DEBUG_VERIFY_EQ_OPERANDS(__lhs, __rhs);
546 return __lhs.base() == __rhs.base();
547 }
548
549#if ! __cpp_lib_three_way_comparison
550 _GLIBCXX_NODISCARD
551 friend bool
552 operator!=(const _Self& __lhs, const _Self& __rhs) _GLIBCXX_NOEXCEPT
553 {
554 _GLIBCXX_DEBUG_VERIFY_EQ_OPERANDS(__lhs, __rhs);
555 return __lhs.base() != __rhs.base();
556 }
557
558 template<typename _IteR>
559 _GLIBCXX_NODISCARD
560 friend bool
561 operator!=(const _Self& __lhs,
562 const _Safe_iterator<_IteR, _Sequence, iterator_category>& __rhs)
563 _GLIBCXX_NOEXCEPT
564 {
565 _GLIBCXX_DEBUG_VERIFY_EQ_OPERANDS(__lhs, __rhs);
566 return __lhs.base() != __rhs.base();
567 }
568#endif // three-way comparison
569 };
570
571 template<typename _Iterator, typename _Sequence>
572 class _Safe_iterator<_Iterator, _Sequence, std::bidirectional_iterator_tag>
573 : public _Safe_iterator<_Iterator, _Sequence, std::forward_iterator_tag>
574 {
575 typedef _Safe_iterator<_Iterator, _Sequence,
576 std::forward_iterator_tag> _Safe_base;
577
578 protected:
579 typedef typename _Safe_base::_OtherIterator _OtherIterator;
580
581 typedef typename _Safe_base::_Unchecked _Unchecked;
582
583 _GLIBCXX20_CONSTEXPR
585 _Unchecked __unchecked) _GLIBCXX_NOEXCEPT
586 : _Safe_base(__x, __unchecked)
587 { }
588
589 public:
590 /// @post the iterator is singular and unattached
591 _GLIBCXX20_CONSTEXPR
592 _Safe_iterator() _GLIBCXX_NOEXCEPT { }
593
594 /**
595 * @brief Safe iterator construction from an unsafe iterator and
596 * its sequence.
597 *
598 * @pre @p seq is not NULL
599 * @post this is not singular
600 */
601 _GLIBCXX20_CONSTEXPR
602 _Safe_iterator(_Iterator __i, const _Safe_sequence_base* __seq)
603 _GLIBCXX_NOEXCEPT
604 : _Safe_base(__i, __seq)
605 { }
606
607 /**
608 * @brief Copy construction.
609 */
610 _GLIBCXX20_CONSTEXPR
611 _Safe_iterator(const _Safe_iterator& __x) _GLIBCXX_NOEXCEPT
612 : _Safe_base(__x)
613 { }
614
615#if __cplusplus >= 201103L
616 /** @brief Move construction. */
617 _GLIBCXX20_CONSTEXPR
618 _Safe_iterator(_Safe_iterator&&) = default;
619#endif
620
621 /**
622 * @brief Converting constructor from a mutable iterator to a
623 * constant iterator.
624 */
625 template<typename _MutableIterator>
626 _GLIBCXX20_CONSTEXPR
628 const _Safe_iterator<_MutableIterator, _Sequence,
629 typename __gnu_cxx::__enable_if<_Safe_base::_IsConstant::__value &&
630 std::__are_same<_MutableIterator, _OtherIterator>::__value,
631 std::bidirectional_iterator_tag>::__type>& __x)
632 _GLIBCXX_NOEXCEPT
633 : _Safe_base(__x)
634 { }
635
636#if __cplusplus >= 201103L
637 /** @brief Copy assignment. */
639 operator=(const _Safe_iterator&) = default;
640
641 /** @brief Move assignment. */
643 operator=(_Safe_iterator&&) = default;
644#else
645 /** @brief Copy assignment. */
647 operator=(const _Safe_iterator& __x)
648 {
649 _Safe_base::operator=(__x);
650 return *this;
651 }
652#endif
653
654 // ------ Input iterator requirements ------
655 /**
656 * @brief Iterator preincrement
657 * @pre iterator is incrementable
658 */
659 _GLIBCXX20_CONSTEXPR
661 operator++() _GLIBCXX_NOEXCEPT
662 {
663 _Safe_base::operator++();
664 return *this;
665 }
666
667 /**
668 * @brief Iterator postincrement
669 * @pre iterator is incrementable
670 */
672 operator++(int) _GLIBCXX_NOEXCEPT
673 {
674 _GLIBCXX_DEBUG_VERIFY(this->_M_incrementable(),
675 _M_message(__msg_bad_inc)
676 ._M_iterator(*this, "this"));
677 _Safe_iterator __ret(*this, _Unchecked());
678 ++*this;
679 return __ret;
680 }
681
682 // ------ Bidirectional iterator requirements ------
683 /**
684 * @brief Iterator predecrement
685 * @pre iterator is decrementable
686 */
687 _GLIBCXX20_CONSTEXPR
689 operator--() _GLIBCXX_NOEXCEPT
690 {
691 if (std::__is_constant_evaluated())
692 {
693 --this->base();
694 return *this;
695 }
696
697 _GLIBCXX_DEBUG_VERIFY(this->_M_decrementable(),
698 _M_message(__msg_bad_dec)
699 ._M_iterator(*this, "this"));
701 --this->base();
702 return *this;
703 }
704
705 /**
706 * @brief Iterator postdecrement
707 * @pre iterator is decrementable
708 */
710 operator--(int) _GLIBCXX_NOEXCEPT
711 {
712 _GLIBCXX_DEBUG_VERIFY(this->_M_decrementable(),
713 _M_message(__msg_bad_dec)
714 ._M_iterator(*this, "this"));
715 _Safe_iterator __ret(*this, _Unchecked());
716 --*this;
717 return __ret;
718 }
719
720 // ------ Utilities ------
721
722 // Is the iterator decrementable?
723 bool
724 _M_decrementable() const
725 { return !this->_M_singular() && !this->_M_is_begin(); }
726 };
727
728 template<typename _Iterator, typename _Sequence>
729 class _Safe_iterator<_Iterator, _Sequence, std::random_access_iterator_tag>
730 : public _Safe_iterator<_Iterator, _Sequence,
731 std::bidirectional_iterator_tag>
732 {
733 typedef _Safe_iterator<_Iterator, _Sequence,
735 typedef typename _Safe_base::_OtherIterator _OtherIterator;
736
737 typedef typename _Safe_base::_Self _Self;
738 typedef _Safe_iterator<_OtherIterator, _Sequence,
740
741 typedef typename _Safe_base::_Unchecked _Unchecked;
742
743 _GLIBCXX20_CONSTEXPR
745 _Unchecked __unchecked) _GLIBCXX_NOEXCEPT
746 : _Safe_base(__x, __unchecked)
747 { }
748
749 public:
750 typedef typename _Safe_base::difference_type difference_type;
751 typedef typename _Safe_base::reference reference;
752
753 /// @post the iterator is singular and unattached
754 _GLIBCXX20_CONSTEXPR
755 _Safe_iterator() _GLIBCXX_NOEXCEPT { }
756
757 /**
758 * @brief Safe iterator construction from an unsafe iterator and
759 * its sequence.
760 *
761 * @pre @p seq is not NULL
762 * @post this is not singular
763 */
764 _GLIBCXX20_CONSTEXPR
765 _Safe_iterator(_Iterator __i, const _Safe_sequence_base* __seq)
766 _GLIBCXX_NOEXCEPT
767 : _Safe_base(__i, __seq)
768 { }
769
770 /**
771 * @brief Copy construction.
772 */
773 _GLIBCXX20_CONSTEXPR
774 _Safe_iterator(const _Safe_iterator& __x) _GLIBCXX_NOEXCEPT
775 : _Safe_base(__x)
776 { }
777
778#if __cplusplus >= 201103L
779 /** @brief Move construction. */
780 _Safe_iterator(_Safe_iterator&&) = default;
781#endif
782
783 /**
784 * @brief Converting constructor from a mutable iterator to a
785 * constant iterator.
786 */
787 template<typename _MutableIterator>
788 _GLIBCXX20_CONSTEXPR
790 const _Safe_iterator<_MutableIterator, _Sequence,
791 typename __gnu_cxx::__enable_if<_Safe_base::_IsConstant::__value &&
792 std::__are_same<_MutableIterator, _OtherIterator>::__value,
793 std::random_access_iterator_tag>::__type>& __x)
794 _GLIBCXX_NOEXCEPT
795 : _Safe_base(__x)
796 { }
797
798#if __cplusplus >= 201103L
799 /** @brief Copy assignment. */
801 operator=(const _Safe_iterator&) = default;
802
803 /** @brief Move assignment. */
805 operator=(_Safe_iterator&&) = default;
806#else
807 /** @brief Copy assignment. */
809 operator=(const _Safe_iterator& __x)
810 {
811 _Safe_base::operator=(__x);
812 return *this;
813 }
814#endif
815
816 // Is the iterator range [*this, __rhs) valid?
817 bool
818 _M_valid_range(const _Safe_iterator& __rhs,
819 std::pair<difference_type,
820 _Distance_precision>& __dist) const;
821
822 // ------ Input iterator requirements ------
823 /**
824 * @brief Iterator preincrement
825 * @pre iterator is incrementable
826 */
827 _GLIBCXX20_CONSTEXPR
829 operator++() _GLIBCXX_NOEXCEPT
830 {
831 _Safe_base::operator++();
832 return *this;
833 }
834
835 /**
836 * @brief Iterator postincrement
837 * @pre iterator is incrementable
838 */
839 _GLIBCXX20_CONSTEXPR
841 operator++(int) _GLIBCXX_NOEXCEPT
842 {
843 if (!std::__is_constant_evaluated())
844 {
845 _GLIBCXX_DEBUG_VERIFY(this->_M_incrementable(),
846 _M_message(__msg_bad_inc)
847 ._M_iterator(*this, "this"));
848 }
849 _Safe_iterator __ret(*this, _Unchecked());
850 ++*this;
851 return __ret;
852 }
853
854 // ------ Bidirectional iterator requirements ------
855 /**
856 * @brief Iterator predecrement
857 * @pre iterator is decrementable
858 */
859 _GLIBCXX20_CONSTEXPR
861 operator--() _GLIBCXX_NOEXCEPT
862 {
863 _Safe_base::operator--();
864 return *this;
865 }
866
867 /**
868 * @brief Iterator postdecrement
869 * @pre iterator is decrementable
870 */
871 _GLIBCXX20_CONSTEXPR
873 operator--(int) _GLIBCXX_NOEXCEPT
874 {
875 if (!std::__is_constant_evaluated())
876 {
877 _GLIBCXX_DEBUG_VERIFY(this->_M_decrementable(),
878 _M_message(__msg_bad_dec)
879 ._M_iterator(*this, "this"));
880 }
881 _Safe_iterator __ret(*this, _Unchecked());
882 --*this;
883 return __ret;
884 }
885
886 // ------ Random access iterator requirements ------
887 _GLIBCXX_NODISCARD
888 _GLIBCXX20_CONSTEXPR
889 reference
890 operator[](difference_type __n) const _GLIBCXX_NOEXCEPT
891 {
892 if (!std::__is_constant_evaluated())
893 {
894 _GLIBCXX_DEBUG_VERIFY(this->_M_can_advance(__n)
895 && this->_M_can_advance(__n + 1),
896 _M_message(__msg_iter_subscript_oob)
897 ._M_iterator(*this)._M_integer(__n));
898 }
899 return this->base()[__n];
900 }
901
902 _GLIBCXX20_CONSTEXPR
904 operator+=(difference_type __n) _GLIBCXX_NOEXCEPT
905 {
906 if (std::__is_constant_evaluated())
907 {
908 this->base() += __n;
909 return *this;
910 }
911
912 _GLIBCXX_DEBUG_VERIFY(this->_M_can_advance(__n),
913 _M_message(__msg_advance_oob)
914 ._M_iterator(*this)._M_integer(__n));
916 this->base() += __n;
917 return *this;
918 }
919
920 _GLIBCXX20_CONSTEXPR
922 operator-=(difference_type __n) _GLIBCXX_NOEXCEPT
923 {
924 if (std::__is_constant_evaluated())
925 {
926 this->base() -= __n;
927 return *this;
928 }
929
930 _GLIBCXX_DEBUG_VERIFY(this->_M_can_advance(-__n),
931 _M_message(__msg_retreat_oob)
932 ._M_iterator(*this)._M_integer(__n));
934 this->base() -= __n;
935 return *this;
936 }
937
938#if __cpp_lib_three_way_comparison
939 [[nodiscard]]
940 _GLIBCXX20_CONSTEXPR
941 friend auto
942 operator<=>(const _Self& __lhs, const _Self& __rhs) noexcept
943 {
944 _GLIBCXX_DEBUG_VERIFY_REL_OPERANDS(__lhs, __rhs);
945 return __lhs.base() <=> __rhs.base();
946 }
947
948 [[nodiscard]]
949 _GLIBCXX20_CONSTEXPR
950 friend auto
951 operator<=>(const _Self& __lhs, const _OtherSelf& __rhs) noexcept
952 {
953 _GLIBCXX_DEBUG_VERIFY_REL_OPERANDS(__lhs, __rhs);
954 return __lhs.base() <=> __rhs.base();
955 }
956#else
957 _GLIBCXX_NODISCARD
958 friend bool
959 operator<(const _Self& __lhs, const _Self& __rhs) _GLIBCXX_NOEXCEPT
960 {
961 _GLIBCXX_DEBUG_VERIFY_REL_OPERANDS(__lhs, __rhs);
962 return __lhs.base() < __rhs.base();
963 }
964
965 _GLIBCXX_NODISCARD
966 friend bool
967 operator<(const _Self& __lhs, const _OtherSelf& __rhs) _GLIBCXX_NOEXCEPT
968 {
969 _GLIBCXX_DEBUG_VERIFY_REL_OPERANDS(__lhs, __rhs);
970 return __lhs.base() < __rhs.base();
971 }
972
973 _GLIBCXX_NODISCARD
974 friend bool
975 operator<=(const _Self& __lhs, const _Self& __rhs) _GLIBCXX_NOEXCEPT
976 {
977 _GLIBCXX_DEBUG_VERIFY_REL_OPERANDS(__lhs, __rhs);
978 return __lhs.base() <= __rhs.base();
979 }
980
981 _GLIBCXX_NODISCARD
982 friend bool
983 operator<=(const _Self& __lhs, const _OtherSelf& __rhs) _GLIBCXX_NOEXCEPT
984 {
985 _GLIBCXX_DEBUG_VERIFY_REL_OPERANDS(__lhs, __rhs);
986 return __lhs.base() <= __rhs.base();
987 }
988
989 _GLIBCXX_NODISCARD
990 friend bool
991 operator>(const _Self& __lhs, const _Self& __rhs) _GLIBCXX_NOEXCEPT
992 {
993 _GLIBCXX_DEBUG_VERIFY_REL_OPERANDS(__lhs, __rhs);
994 return __lhs.base() > __rhs.base();
995 }
996
997 _GLIBCXX_NODISCARD
998 friend bool
999 operator>(const _Self& __lhs, const _OtherSelf& __rhs) _GLIBCXX_NOEXCEPT
1000 {
1001 _GLIBCXX_DEBUG_VERIFY_REL_OPERANDS(__lhs, __rhs);
1002 return __lhs.base() > __rhs.base();
1003 }
1004
1005 _GLIBCXX_NODISCARD
1006 friend bool
1007 operator>=(const _Self& __lhs, const _Self& __rhs) _GLIBCXX_NOEXCEPT
1008 {
1009 _GLIBCXX_DEBUG_VERIFY_REL_OPERANDS(__lhs, __rhs);
1010 return __lhs.base() >= __rhs.base();
1011 }
1012
1013 _GLIBCXX_NODISCARD
1014 friend bool
1015 operator>=(const _Self& __lhs, const _OtherSelf& __rhs) _GLIBCXX_NOEXCEPT
1016 {
1017 _GLIBCXX_DEBUG_VERIFY_REL_OPERANDS(__lhs, __rhs);
1018 return __lhs.base() >= __rhs.base();
1019 }
1020#endif // three-way comparison
1021
1022 // _GLIBCXX_RESOLVE_LIB_DEFECTS
1023 // According to the resolution of DR179 not only the various comparison
1024 // operators but also operator- must accept mixed iterator/const_iterator
1025 // parameters.
1026 _GLIBCXX_NODISCARD
1027 _GLIBCXX20_CONSTEXPR
1028 friend difference_type
1029 operator-(const _Self& __lhs, const _OtherSelf& __rhs) _GLIBCXX_NOEXCEPT
1030 {
1031 _GLIBCXX_DEBUG_VERIFY_DIST_OPERANDS(__lhs, __rhs);
1032 return __lhs.base() - __rhs.base();
1033 }
1034
1035 _GLIBCXX_NODISCARD
1036 _GLIBCXX20_CONSTEXPR
1037 friend difference_type
1038 operator-(const _Self& __lhs, const _Self& __rhs) _GLIBCXX_NOEXCEPT
1039 {
1040 _GLIBCXX_DEBUG_VERIFY_DIST_OPERANDS(__lhs, __rhs);
1041 return __lhs.base() - __rhs.base();
1042 }
1043
1044 _GLIBCXX_NODISCARD
1045 _GLIBCXX20_CONSTEXPR
1046 friend _Self
1047 operator+(const _Self& __x, difference_type __n) _GLIBCXX_NOEXCEPT
1048 {
1049 if (!std::__is_constant_evaluated())
1050 {
1051 _GLIBCXX_DEBUG_VERIFY(__x._M_can_advance(__n),
1052 _M_message(__msg_advance_oob)
1053 ._M_iterator(__x)._M_integer(__n));
1054 }
1055 return _Safe_iterator(__x.base() + __n, __x._M_sequence);
1056 }
1057
1058 _GLIBCXX_NODISCARD
1059 _GLIBCXX20_CONSTEXPR
1060 friend _Self
1061 operator+(difference_type __n, const _Self& __x) _GLIBCXX_NOEXCEPT
1062 {
1063 if (!std::__is_constant_evaluated())
1064 {
1065 _GLIBCXX_DEBUG_VERIFY(__x._M_can_advance(__n),
1066 _M_message(__msg_advance_oob)
1067 ._M_iterator(__x)._M_integer(__n));
1068 }
1069 return _Safe_iterator(__n + __x.base(), __x._M_sequence);
1070 }
1071
1072 _GLIBCXX_NODISCARD
1073 _GLIBCXX20_CONSTEXPR
1074 friend _Self
1075 operator-(const _Self& __x, difference_type __n) _GLIBCXX_NOEXCEPT
1076 {
1077 if (!std::__is_constant_evaluated())
1078 {
1079 _GLIBCXX_DEBUG_VERIFY(__x._M_can_advance(-__n),
1080 _M_message(__msg_retreat_oob)
1081 ._M_iterator(__x)._M_integer(__n));
1082 }
1083 return _Safe_iterator(__x.base() - __n, __x._M_sequence);
1084 }
1085 };
1086
1087 /** Safe iterators know how to check if they form a valid range. */
1088 template<typename _Iterator, typename _Sequence, typename _Category>
1089 inline bool
1090 __valid_range(const _Safe_iterator<_Iterator, _Sequence,
1091 _Category>& __first,
1092 const _Safe_iterator<_Iterator, _Sequence,
1093 _Category>& __last,
1094 typename _Distance_traits<_Iterator>::__type& __dist)
1095 { return __first._M_valid_range(__last, __dist); }
1096
1097 template<typename _Iterator, typename _Sequence, typename _Category>
1098 inline bool
1099 __valid_range(const _Safe_iterator<_Iterator, _Sequence,
1100 _Category>& __first,
1101 const _Safe_iterator<_Iterator, _Sequence,
1102 _Category>& __last)
1103 {
1104 typename _Distance_traits<_Iterator>::__type __dist;
1105 return __first._M_valid_range(__last, __dist);
1106 }
1107
1108 template<typename _Iterator, typename _Sequence, typename _Category,
1109 typename _Size>
1110 inline bool
1111 __can_advance(const _Safe_iterator<_Iterator, _Sequence, _Category>& __it,
1112 _Size __n)
1113 { return __it._M_can_advance(__n); }
1114
1115 template<typename _Iterator, typename _Sequence, typename _Category,
1116 typename _Diff>
1117 inline bool
1118 __can_advance(const _Safe_iterator<_Iterator, _Sequence, _Category>& __it,
1120 int __way)
1121 { return __it._M_can_advance(__dist, __way); }
1122
1123 template<typename _Iterator, typename _Sequence>
1124 _Iterator
1125 __base(const _Safe_iterator<_Iterator, _Sequence,
1127 { return __it.base(); }
1128
1129#if __cplusplus < 201103L
1130 template<typename _Iterator, typename _Sequence>
1131 struct _Unsafe_type<_Safe_iterator<_Iterator, _Sequence> >
1132 { typedef _Iterator _Type; };
1133#endif
1134
1135 template<typename _Iterator, typename _Sequence>
1136 inline _Iterator
1137 __unsafe(const _Safe_iterator<_Iterator, _Sequence>& __it)
1138 { return __it.base(); }
1139
1140} // namespace __gnu_debug
1141
1142#if __cplusplus >= 201103L && __cplusplus <= 201703L
1143namespace std _GLIBCXX_VISIBILITY(default)
1144{
1145_GLIBCXX_BEGIN_NAMESPACE_VERSION
1146
1147 template<typename _Iterator, typename _Container, typename _Sequence>
1148 constexpr auto
1149 __to_address(const __gnu_debug::_Safe_iterator<
1150 __gnu_cxx::__normal_iterator<_Iterator, _Container>,
1151 _Sequence>& __it) noexcept
1152 -> decltype(std::__to_address(__it.base().base()))
1153 { return std::__to_address(__it.base().base()); }
1154
1155_GLIBCXX_END_NAMESPACE_VERSION
1156}
1157#endif
1158
1159#undef _GLIBCXX_DEBUG_VERIFY_DIST_OPERANDS
1160#undef _GLIBCXX_DEBUG_VERIFY_REL_OPERANDS
1161#undef _GLIBCXX_DEBUG_VERIFY_EQ_OPERANDS
1162#undef _GLIBCXX_DEBUG_VERIFY_OPERANDS
1163
1164#include <debug/safe_iterator.tcc>
1165
1166#endif
constexpr bool operator<=(const duration< _Rep1, _Period1 > &__lhs, const duration< _Rep2, _Period2 > &__rhs)
Definition chrono.h:855
constexpr bool operator>=(const duration< _Rep1, _Period1 > &__lhs, const duration< _Rep2, _Period2 > &__rhs)
Definition chrono.h:869
constexpr bool operator<(const duration< _Rep1, _Period1 > &__lhs, const duration< _Rep2, _Period2 > &__rhs)
Definition chrono.h:822
constexpr bool operator>(const duration< _Rep1, _Period1 > &__lhs, const duration< _Rep2, _Period2 > &__rhs)
Definition chrono.h:862
constexpr complex< _Tp > operator-(const complex< _Tp > &__x, const complex< _Tp > &__y)
Return new complex value x minus y.
Definition complex:370
constexpr complex< _Tp > operator+(const complex< _Tp > &__x, const complex< _Tp > &__y)
Return new complex value x plus y.
Definition complex:340
constexpr _Tp * __addressof(_Tp &__r) noexcept
Same as C++11 std::addressof.
Definition move.h:51
ISO C++ entities toplevel namespace is std.
GNU debug classes for public use.
constexpr bool __valid_range(_InputIterator __first, _InputIterator __last, typename _Distance_traits< _InputIterator >::__type &__dist)
constexpr _Iterator __base(_Iterator __it)
Safe iterator wrapper.
bool _M_incrementable() const
Is the iterator incrementable?
constexpr _Iterator & base() noexcept
Return the underlying iterator.
bool _M_dereferenceable() const
Is the iterator dereferenceable?
constexpr bool _M_is_begin() const
Is this iterator equal to the sequence's begin() iterator?
constexpr _Safe_iterator(const _Safe_iterator< _MutableIterator, _Sequence, typename __gnu_cxx::__enable_if< _IsConstant::__value &&std::__are_same< _MutableIterator, _OtherIterator >::__value, _Category >::__type > &__x) noexcept
Converting constructor from a mutable iterator to a constant iterator.
void _M_attach_single(_Safe_sequence_base *__seq)
constexpr _Safe_iterator & operator++() noexcept
Iterator preincrement.
bool _M_before_dereferenceable() const
Is the iterator before a dereferenceable one?
constexpr _Safe_iterator & operator=(_Safe_iterator &&__x) noexcept
Move assignment.
constexpr _Safe_iterator(_Iterator __i, const _Safe_sequence_base *__seq) noexcept
Safe iterator construction from an unsafe iterator and its sequence.
constexpr pointer operator->() const noexcept
Iterator dereference.
constexpr _Safe_iterator(const _Safe_iterator &__x) noexcept
Copy construction.
constexpr reference operator*() const noexcept
Iterator dereference.
constexpr _Safe_iterator() noexcept
bool _M_is_beginnest() const
Is this iterator equal to the sequence's before_begin() iterator if any or begin() otherwise?
bool _M_value_initialized() const
Is the iterator value-initialized?
bool _M_is_end() const
Is this iterator equal to the sequence's end() iterator?
constexpr _Safe_iterator operator++(int) noexcept
Iterator postincrement.
void _M_attach(_Safe_sequence_base *__seq)
bool _M_is_before_begin() const
Is this iterator equal to the sequence's before_begin() iterator if any?
constexpr _Safe_iterator(_Safe_iterator &&__x) noexcept
Move construction.
static constexpr bool _S_constant()
Determine if this is a constant iterator.
constexpr _Safe_iterator & operator=(const _Safe_iterator &__x) noexcept
Copy assignment.
Traits class for iterators.
Struct holding two objects of arbitrary type.
Definition stl_pair.h:188
Forward iterators support a superset of input iterator operations.
Bidirectional iterators support a superset of forward iterator operations.
Random-access iterators support a superset of bidirectional iterator operations.
Basic functionality for a safe iterator.
Definition safe_base.h:51
_Safe_sequence_base * _M_sequence
Definition safe_base.h:57
__gnu_cxx::__mutex & _M_get_mutex()
void _M_attach_single(_Safe_sequence_base *__seq, bool __constant)
void _M_attach(_Safe_sequence_base *__seq, bool __constant)
Base class that supports tracking of iterators that reference a sequence.
Definition safe_base.h:203
unsigned int _M_version
The container version number. This number may never be 0.
Definition safe_base.h:214
Scoped lock idiom.