libstdc++
safe_iterator.h
Go to the documentation of this file.
1 // Safe iterator implementation -*- C++ -*-
2 
3 // Copyright (C) 2003-2020 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  _GLIBCXX_DEBUG_VERIFY(!_Lhs._M_singular() && !_Rhs._M_singular(), \
44  _M_message(_BadMsgId) \
45  ._M_iterator(_Lhs, #_Lhs) \
46  ._M_iterator(_Rhs, #_Rhs)); \
47  _GLIBCXX_DEBUG_VERIFY(_Lhs._M_can_compare(_Rhs), \
48  _M_message(_DiffMsgId) \
49  ._M_iterator(_Lhs, #_Lhs) \
50  ._M_iterator(_Rhs, #_Rhs))
51 
52 #define _GLIBCXX_DEBUG_VERIFY_EQ_OPERANDS(_Lhs, _Rhs) \
53  _GLIBCXX_DEBUG_VERIFY_OPERANDS(_Lhs, _Rhs, __msg_iter_compare_bad, \
54  __msg_compare_different)
55 
56 #define _GLIBCXX_DEBUG_VERIFY_REL_OPERANDS(_Lhs, _Rhs) \
57  _GLIBCXX_DEBUG_VERIFY_OPERANDS(_Lhs, _Rhs, __msg_iter_order_bad, \
58  __msg_order_different)
59 
60 #define _GLIBCXX_DEBUG_VERIFY_DIST_OPERANDS(_Lhs, _Rhs) \
61  _GLIBCXX_DEBUG_VERIFY_OPERANDS(_Lhs, _Rhs, __msg_distance_bad, \
62  __msg_distance_different)
63 
64 namespace __gnu_debug
65 {
66  /** Helper struct to deal with sequence offering a before_begin
67  * iterator.
68  **/
69  template<typename _Sequence>
71  {
72  template<typename _Iterator, typename _Category>
73  static bool
75  { return false; }
76 
77  template<typename _Iterator, typename _Category>
78  static bool
79  _S_Is_Beginnest(const _Safe_iterator<_Iterator, _Sequence, _Category>& __it)
80  { return __it.base() == __it._M_get_sequence()->_M_base().begin(); }
81  };
82 
83  /** Sequence traits giving the size of a container if possible. */
84  template<typename _Sequence>
86  {
87  typedef _Distance_traits<typename _Sequence::iterator> _DistTraits;
88 
89  static typename _DistTraits::__type
90  _S_size(const _Sequence& __seq)
91  { return std::make_pair(__seq.size(), __dp_exact); }
92  };
93 
94  /** \brief Safe iterator wrapper.
95  *
96  * The class template %_Safe_iterator is a wrapper around an
97  * iterator that tracks the iterator's movement among sequences and
98  * checks that operations performed on the "safe" iterator are
99  * legal. In additional to the basic iterator operations (which are
100  * validated, and then passed to the underlying iterator),
101  * %_Safe_iterator has member functions for iterator invalidation,
102  * attaching/detaching the iterator from sequences, and querying
103  * the iterator's state.
104  *
105  * Note that _Iterator must be the first base class so that it gets
106  * initialized before the iterator is being attached to the container's list
107  * of iterators and it is being detached before _Iterator get
108  * destroyed. Otherwise it would result in a data race.
109  */
110  template<typename _Iterator, typename _Sequence, typename _Category
112  class _Safe_iterator
113  : private _Iterator,
114  public _Safe_iterator_base
115  {
116  typedef _Iterator _Iter_base;
117  typedef _Safe_iterator_base _Safe_base;
118 
119  typedef std::iterator_traits<_Iterator> _Traits;
120 
121  protected:
122  typedef std::__are_same<typename _Sequence::_Base::const_iterator,
123  _Iterator> _IsConstant;
124 
125  typedef typename __gnu_cxx::__conditional_type<
126  _IsConstant::__value,
127  typename _Sequence::_Base::iterator,
128  typename _Sequence::_Base::const_iterator>::__type _OtherIterator;
129 
130  struct _Attach_single
131  { };
132 
133  _Safe_iterator(_Iterator __i, _Safe_sequence_base* __seq, _Attach_single)
134  _GLIBCXX_NOEXCEPT
135  : _Iter_base(__i)
136  { _M_attach_single(__seq); }
137 
138  public:
139  typedef _Iterator iterator_type;
140  typedef typename _Traits::iterator_category iterator_category;
141  typedef typename _Traits::value_type value_type;
142  typedef typename _Traits::difference_type difference_type;
143  typedef typename _Traits::reference reference;
144  typedef typename _Traits::pointer pointer;
145 
146 #if __cplusplus > 201703L && __cpp_lib_concepts
147  using iterator_concept = std::__detail::__iter_concept<_Iterator>;
148 #endif
149 
150  /// @post the iterator is singular and unattached
151  _Safe_iterator() _GLIBCXX_NOEXCEPT : _Iter_base() { }
152 
153  /**
154  * @brief Safe iterator construction from an unsafe iterator and
155  * its sequence.
156  *
157  * @pre @p seq is not NULL
158  * @post this is not singular
159  */
160  _Safe_iterator(_Iterator __i, const _Safe_sequence_base* __seq)
161  _GLIBCXX_NOEXCEPT
162  : _Iter_base(__i), _Safe_base(__seq, _S_constant())
163  {
164  _GLIBCXX_DEBUG_VERIFY(!this->_M_singular(),
165  _M_message(__msg_init_singular)
166  ._M_iterator(*this, "this"));
167  }
168 
169  /**
170  * @brief Copy construction.
171  */
172  _Safe_iterator(const _Safe_iterator& __x) _GLIBCXX_NOEXCEPT
173  : _Iter_base(__x.base())
174  {
175  // _GLIBCXX_RESOLVE_LIB_DEFECTS
176  // DR 408. Is vector<reverse_iterator<char*> > forbidden?
177  _GLIBCXX_DEBUG_VERIFY(!__x._M_singular()
178  || __x.base() == _Iterator(),
179  _M_message(__msg_init_copy_singular)
180  ._M_iterator(*this, "this")
181  ._M_iterator(__x, "other"));
182  _M_attach(__x._M_sequence);
183  }
184 
185 #if __cplusplus >= 201103L
186  /**
187  * @brief Move construction.
188  * @post __x is singular and unattached
189  */
191  : _Iter_base()
192  {
193  _GLIBCXX_DEBUG_VERIFY(!__x._M_singular()
194  || __x.base() == _Iterator(),
195  _M_message(__msg_init_copy_singular)
196  ._M_iterator(*this, "this")
197  ._M_iterator(__x, "other"));
198  _Safe_sequence_base* __seq = __x._M_sequence;
199  __x._M_detach();
200  std::swap(base(), __x.base());
201  _M_attach(__seq);
202  }
203 #endif
204 
205  /**
206  * @brief Converting constructor from a mutable iterator to a
207  * constant iterator.
208  */
209  template<typename _MutableIterator>
211  const _Safe_iterator<_MutableIterator, _Sequence,
212  typename __gnu_cxx::__enable_if<_IsConstant::__value &&
213  std::__are_same<_MutableIterator, _OtherIterator>::__value,
214  _Category>::__type>& __x)
215  _GLIBCXX_NOEXCEPT
216  : _Iter_base(__x.base())
217  {
218  // _GLIBCXX_RESOLVE_LIB_DEFECTS
219  // DR 408. Is vector<reverse_iterator<char*> > forbidden?
220  _GLIBCXX_DEBUG_VERIFY(!__x._M_singular()
221  || __x.base() == _MutableIterator(),
222  _M_message(__msg_init_const_singular)
223  ._M_iterator(*this, "this")
224  ._M_iterator(__x, "other"));
225  _M_attach(__x._M_sequence);
226  }
227 
228  /**
229  * @brief Copy assignment.
230  */
232  operator=(const _Safe_iterator& __x) _GLIBCXX_NOEXCEPT
233  {
234  // _GLIBCXX_RESOLVE_LIB_DEFECTS
235  // DR 408. Is vector<reverse_iterator<char*> > forbidden?
236  _GLIBCXX_DEBUG_VERIFY(!__x._M_singular()
237  || __x.base() == _Iterator(),
238  _M_message(__msg_copy_singular)
239  ._M_iterator(*this, "this")
240  ._M_iterator(__x, "other"));
241 
242  if (this->_M_sequence && this->_M_sequence == __x._M_sequence)
243  {
245  base() = __x.base();
246  _M_version = __x._M_sequence->_M_version;
247  }
248  else
249  {
250  _M_detach();
251  base() = __x.base();
252  _M_attach(__x._M_sequence);
253  }
254 
255  return *this;
256  }
257 
258 #if __cplusplus >= 201103L
259  /**
260  * @brief Move assignment.
261  * @post __x is singular and unattached
262  */
264  operator=(_Safe_iterator&& __x) noexcept
265  {
266  _GLIBCXX_DEBUG_VERIFY(this != &__x,
267  _M_message(__msg_self_move_assign)
268  ._M_iterator(*this, "this"));
269  _GLIBCXX_DEBUG_VERIFY(!__x._M_singular()
270  || __x.base() == _Iterator(),
271  _M_message(__msg_copy_singular)
272  ._M_iterator(*this, "this")
273  ._M_iterator(__x, "other"));
274 
275  if (this->_M_sequence && this->_M_sequence == __x._M_sequence)
276  {
278  base() = __x.base();
279  _M_version = __x._M_sequence->_M_version;
280  }
281  else
282  {
283  _M_detach();
284  base() = __x.base();
285  _M_attach(__x._M_sequence);
286  }
287 
288  __x._M_detach();
289  __x.base() = _Iterator();
290  return *this;
291  }
292 #endif
293 
294  /**
295  * @brief Iterator dereference.
296  * @pre iterator is dereferenceable
297  */
298  reference
299  operator*() const _GLIBCXX_NOEXCEPT
300  {
301  _GLIBCXX_DEBUG_VERIFY(this->_M_dereferenceable(),
302  _M_message(__msg_bad_deref)
303  ._M_iterator(*this, "this"));
304  return *base();
305  }
306 
307  /**
308  * @brief Iterator dereference.
309  * @pre iterator is dereferenceable
310  */
311  pointer
312  operator->() const _GLIBCXX_NOEXCEPT
313  {
314  _GLIBCXX_DEBUG_VERIFY(this->_M_dereferenceable(),
315  _M_message(__msg_bad_deref)
316  ._M_iterator(*this, "this"));
317  return base().operator->();
318  }
319 
320  // ------ Input iterator requirements ------
321  /**
322  * @brief Iterator preincrement
323  * @pre iterator is incrementable
324  */
326  operator++() _GLIBCXX_NOEXCEPT
327  {
328  _GLIBCXX_DEBUG_VERIFY(this->_M_incrementable(),
329  _M_message(__msg_bad_inc)
330  ._M_iterator(*this, "this"));
332  ++base();
333  return *this;
334  }
335 
336  /**
337  * @brief Iterator postincrement
338  * @pre iterator is incrementable
339  */
341  operator++(int) _GLIBCXX_NOEXCEPT
342  {
343  _GLIBCXX_DEBUG_VERIFY(this->_M_incrementable(),
344  _M_message(__msg_bad_inc)
345  ._M_iterator(*this, "this"));
347  return _Safe_iterator(base()++, this->_M_sequence, _Attach_single());
348  }
349 
350  // ------ Utilities ------
351 
352  /// Determine if this is a constant iterator.
353  static _GLIBCXX_CONSTEXPR bool
355  { return _IsConstant::__value; }
356 
357  /**
358  * @brief Return the underlying iterator
359  */
360  _Iterator&
361  base() _GLIBCXX_NOEXCEPT { return *this; }
362 
363  const _Iterator&
364  base() const _GLIBCXX_NOEXCEPT { return *this; }
365 
366  /**
367  * @brief Conversion to underlying non-debug iterator to allow
368  * better interaction with non-debug containers.
369  */
370  operator _Iterator() const _GLIBCXX_NOEXCEPT { return *this; }
371 
372  /** Attach iterator to the given sequence. */
373  void
375  { _Safe_base::_M_attach(__seq, _S_constant()); }
376 
377  /** Likewise, but not thread-safe. */
378  void
381 
382  /// Is the iterator dereferenceable?
383  bool
385  { return !this->_M_singular() && !_M_is_end() && !_M_is_before_begin(); }
386 
387  /// Is the iterator before a dereferenceable one?
388  bool
390  {
391  if (this->_M_incrementable())
392  {
393  _Iterator __base = base();
394  return ++__base != _M_get_sequence()->_M_base().end();
395  }
396  return false;
397  }
398 
399  /// Is the iterator incrementable?
400  bool
402  { return !this->_M_singular() && !_M_is_end(); }
403 
404  // Can we advance the iterator @p __n steps (@p __n may be negative)
405  bool
406  _M_can_advance(difference_type __n, bool __strict = false) const;
407 
408  // Is the iterator range [*this, __rhs) valid?
409  bool
410  _M_valid_range(const _Safe_iterator& __rhs,
412  bool __check_dereferenceable = true) const;
413 
414  // The sequence this iterator references.
415  typename __gnu_cxx::__conditional_type<
416  _IsConstant::__value, const _Sequence*, _Sequence*>::__type
417  _M_get_sequence() const
418  { return static_cast<_Sequence*>(_M_sequence); }
419 
420  // Get distance to __rhs.
421  typename _Distance_traits<_Iterator>::__type
422  _M_get_distance_to(const _Safe_iterator& __rhs) const;
423 
424  // Get distance from sequence begin up to *this.
425  typename _Distance_traits<_Iterator>::__type
426  _M_get_distance_from_begin() const;
427 
428  // Get distance from *this to sequence end.
429  typename _Distance_traits<_Iterator>::__type
430  _M_get_distance_to_end() const;
431 
432  /// Is this iterator equal to the sequence's begin() iterator?
433  bool
434  _M_is_begin() const
435  { return base() == _M_get_sequence()->_M_base().begin(); }
436 
437  /// Is this iterator equal to the sequence's end() iterator?
438  bool
439  _M_is_end() const
440  { return base() == _M_get_sequence()->_M_base().end(); }
441 
442  /// Is this iterator equal to the sequence's before_begin() iterator if
443  /// any?
444  bool
446  { return _BeforeBeginHelper<_Sequence>::_S_Is(*this); }
447 
448  /// Is this iterator equal to the sequence's before_begin() iterator if
449  /// any or begin() otherwise?
450  bool
453 
454  // ------ Operators ------
455 
457 
458  friend bool
459  operator==(const _Self& __lhs, const _Self& __rhs) _GLIBCXX_NOEXCEPT
460  {
461  _GLIBCXX_DEBUG_VERIFY_EQ_OPERANDS(__lhs, __rhs);
462  return __lhs.base() == __rhs.base();
463  }
464 
465  template<typename _IteR>
466  friend bool
467  operator==(const _Self& __lhs,
468  const _Safe_iterator<_IteR, _Sequence, iterator_category>& __rhs)
469  _GLIBCXX_NOEXCEPT
470  {
471  _GLIBCXX_DEBUG_VERIFY_EQ_OPERANDS(__lhs, __rhs);
472  return __lhs.base() == __rhs.base();
473  }
474 
475 #if ! __cpp_lib_three_way_comparison
476  friend bool
477  operator!=(const _Self& __lhs, const _Self& __rhs) _GLIBCXX_NOEXCEPT
478  {
479  _GLIBCXX_DEBUG_VERIFY_EQ_OPERANDS(__lhs, __rhs);
480  return __lhs.base() != __rhs.base();
481  }
482 
483  template<typename _IteR>
484  friend bool
485  operator!=(const _Self& __lhs,
486  const _Safe_iterator<_IteR, _Sequence, iterator_category>& __rhs)
487  _GLIBCXX_NOEXCEPT
488  {
489  _GLIBCXX_DEBUG_VERIFY_EQ_OPERANDS(__lhs, __rhs);
490  return __lhs.base() != __rhs.base();
491  }
492 #endif // three-way comparison
493  };
494 
495  template<typename _Iterator, typename _Sequence>
496  class _Safe_iterator<_Iterator, _Sequence, std::bidirectional_iterator_tag>
497  : public _Safe_iterator<_Iterator, _Sequence, std::forward_iterator_tag>
498  {
499  typedef _Safe_iterator<_Iterator, _Sequence,
500  std::forward_iterator_tag> _Safe_base;
501 
502  protected:
503  typedef typename _Safe_base::_OtherIterator _OtherIterator;
504  typedef typename _Safe_base::_Attach_single _Attach_single;
505 
506  _Safe_iterator(_Iterator __i, _Safe_sequence_base* __seq, _Attach_single)
507  _GLIBCXX_NOEXCEPT
508  : _Safe_base(__i, __seq, _Attach_single())
509  { }
510 
511  public:
512  /// @post the iterator is singular and unattached
513  _Safe_iterator() _GLIBCXX_NOEXCEPT { }
514 
515  /**
516  * @brief Safe iterator construction from an unsafe iterator and
517  * its sequence.
518  *
519  * @pre @p seq is not NULL
520  * @post this is not singular
521  */
522  _Safe_iterator(_Iterator __i, const _Safe_sequence_base* __seq)
523  _GLIBCXX_NOEXCEPT
524  : _Safe_base(__i, __seq)
525  { }
526 
527  /**
528  * @brief Copy construction.
529  */
530  _Safe_iterator(const _Safe_iterator& __x) _GLIBCXX_NOEXCEPT
531  : _Safe_base(__x)
532  { }
533 
534 #if __cplusplus >= 201103L
535  /** @brief Move construction. */
536  _Safe_iterator(_Safe_iterator&&) = default;
537 #endif
538 
539  /**
540  * @brief Converting constructor from a mutable iterator to a
541  * constant iterator.
542  */
543  template<typename _MutableIterator>
545  const _Safe_iterator<_MutableIterator, _Sequence,
546  typename __gnu_cxx::__enable_if<_Safe_base::_IsConstant::__value &&
547  std::__are_same<_MutableIterator, _OtherIterator>::__value,
548  std::bidirectional_iterator_tag>::__type>& __x)
549  _GLIBCXX_NOEXCEPT
550  : _Safe_base(__x)
551  { }
552 
553 #if __cplusplus >= 201103L
554  /** @brief Copy assignment. */
556  operator=(const _Safe_iterator&) = default;
557 
558  /** @brief Move assignment. */
560  operator=(_Safe_iterator&&) = default;
561 #else
562  /** @brief Copy assignment. */
564  operator=(const _Safe_iterator& __x)
565  {
566  _Safe_base::operator=(__x);
567  return *this;
568  }
569 #endif
570 
571  // ------ Input iterator requirements ------
572  /**
573  * @brief Iterator preincrement
574  * @pre iterator is incrementable
575  */
577  operator++() _GLIBCXX_NOEXCEPT
578  {
579  _Safe_base::operator++();
580  return *this;
581  }
582 
583  /**
584  * @brief Iterator postincrement
585  * @pre iterator is incrementable
586  */
588  operator++(int) _GLIBCXX_NOEXCEPT
589  {
590  _GLIBCXX_DEBUG_VERIFY(this->_M_incrementable(),
591  _M_message(__msg_bad_inc)
592  ._M_iterator(*this, "this"));
594  return _Safe_iterator(this->base()++, this->_M_sequence,
595  _Attach_single());
596  }
597 
598  // ------ Bidirectional iterator requirements ------
599  /**
600  * @brief Iterator predecrement
601  * @pre iterator is decrementable
602  */
604  operator--() _GLIBCXX_NOEXCEPT
605  {
606  _GLIBCXX_DEBUG_VERIFY(this->_M_decrementable(),
607  _M_message(__msg_bad_dec)
608  ._M_iterator(*this, "this"));
610  --this->base();
611  return *this;
612  }
613 
614  /**
615  * @brief Iterator postdecrement
616  * @pre iterator is decrementable
617  */
619  operator--(int) _GLIBCXX_NOEXCEPT
620  {
621  _GLIBCXX_DEBUG_VERIFY(this->_M_decrementable(),
622  _M_message(__msg_bad_dec)
623  ._M_iterator(*this, "this"));
625  return _Safe_iterator(this->base()--, this->_M_sequence,
626  _Attach_single());
627  }
628 
629  // ------ Utilities ------
630 
631  // Is the iterator decrementable?
632  bool
633  _M_decrementable() const
634  { return !this->_M_singular() && !this->_M_is_begin(); }
635  };
636 
637  template<typename _Iterator, typename _Sequence>
638  class _Safe_iterator<_Iterator, _Sequence, std::random_access_iterator_tag>
639  : public _Safe_iterator<_Iterator, _Sequence,
640  std::bidirectional_iterator_tag>
641  {
642  typedef _Safe_iterator<_Iterator, _Sequence,
644  typedef typename _Safe_base::_OtherIterator _OtherIterator;
645 
646  typedef typename _Safe_base::_Self _Self;
647  typedef _Safe_iterator<_OtherIterator, _Sequence,
649 
650  typedef typename _Safe_base::_Attach_single _Attach_single;
651 
652  _Safe_iterator(_Iterator __i, _Safe_sequence_base* __seq, _Attach_single)
653  _GLIBCXX_NOEXCEPT
654  : _Safe_base(__i, __seq, _Attach_single())
655  { }
656 
657  public:
658  typedef typename _Safe_base::difference_type difference_type;
659  typedef typename _Safe_base::reference reference;
660 
661  /// @post the iterator is singular and unattached
662  _Safe_iterator() _GLIBCXX_NOEXCEPT { }
663 
664  /**
665  * @brief Safe iterator construction from an unsafe iterator and
666  * its sequence.
667  *
668  * @pre @p seq is not NULL
669  * @post this is not singular
670  */
671  _Safe_iterator(_Iterator __i, const _Safe_sequence_base* __seq)
672  _GLIBCXX_NOEXCEPT
673  : _Safe_base(__i, __seq)
674  { }
675 
676  /**
677  * @brief Copy construction.
678  */
679  _Safe_iterator(const _Safe_iterator& __x) _GLIBCXX_NOEXCEPT
680  : _Safe_base(__x)
681  { }
682 
683 #if __cplusplus >= 201103L
684  /** @brief Move construction. */
685  _Safe_iterator(_Safe_iterator&&) = default;
686 #endif
687 
688  /**
689  * @brief Converting constructor from a mutable iterator to a
690  * constant iterator.
691  */
692  template<typename _MutableIterator>
694  const _Safe_iterator<_MutableIterator, _Sequence,
695  typename __gnu_cxx::__enable_if<_Safe_base::_IsConstant::__value &&
696  std::__are_same<_MutableIterator, _OtherIterator>::__value,
697  std::random_access_iterator_tag>::__type>& __x)
698  _GLIBCXX_NOEXCEPT
699  : _Safe_base(__x)
700  { }
701 
702 #if __cplusplus >= 201103L
703  /** @brief Copy assignment. */
705  operator=(const _Safe_iterator&) = default;
706 
707  /** @brief Move assignment. */
709  operator=(_Safe_iterator&&) = default;
710 #else
711  /** @brief Copy assignment. */
713  operator=(const _Safe_iterator& __x)
714  {
715  _Safe_base::operator=(__x);
716  return *this;
717  }
718 #endif
719 
720  // Is the iterator range [*this, __rhs) valid?
721  bool
722  _M_valid_range(const _Safe_iterator& __rhs,
723  std::pair<difference_type,
724  _Distance_precision>& __dist) const;
725 
726  // ------ Input iterator requirements ------
727  /**
728  * @brief Iterator preincrement
729  * @pre iterator is incrementable
730  */
732  operator++() _GLIBCXX_NOEXCEPT
733  {
734  _Safe_base::operator++();
735  return *this;
736  }
737 
738  /**
739  * @brief Iterator postincrement
740  * @pre iterator is incrementable
741  */
743  operator++(int) _GLIBCXX_NOEXCEPT
744  {
745  _GLIBCXX_DEBUG_VERIFY(this->_M_incrementable(),
746  _M_message(__msg_bad_inc)
747  ._M_iterator(*this, "this"));
749  return _Safe_iterator(this->base()++, this->_M_sequence,
750  _Attach_single());
751  }
752 
753  // ------ Bidirectional iterator requirements ------
754  /**
755  * @brief Iterator predecrement
756  * @pre iterator is decrementable
757  */
759  operator--() _GLIBCXX_NOEXCEPT
760  {
761  _Safe_base::operator--();
762  return *this;
763  }
764 
765  /**
766  * @brief Iterator postdecrement
767  * @pre iterator is decrementable
768  */
770  operator--(int) _GLIBCXX_NOEXCEPT
771  {
772  _GLIBCXX_DEBUG_VERIFY(this->_M_decrementable(),
773  _M_message(__msg_bad_dec)
774  ._M_iterator(*this, "this"));
776  return _Safe_iterator(this->base()--, this->_M_sequence,
777  _Attach_single());
778  }
779 
780  // ------ Random access iterator requirements ------
781  reference
782  operator[](difference_type __n) const _GLIBCXX_NOEXCEPT
783  {
784  _GLIBCXX_DEBUG_VERIFY(this->_M_can_advance(__n)
785  && this->_M_can_advance(__n + 1),
786  _M_message(__msg_iter_subscript_oob)
787  ._M_iterator(*this)._M_integer(__n));
788  return this->base()[__n];
789  }
790 
792  operator+=(difference_type __n) _GLIBCXX_NOEXCEPT
793  {
794  _GLIBCXX_DEBUG_VERIFY(this->_M_can_advance(__n),
795  _M_message(__msg_advance_oob)
796  ._M_iterator(*this)._M_integer(__n));
798  this->base() += __n;
799  return *this;
800  }
801 
803  operator-=(difference_type __n) _GLIBCXX_NOEXCEPT
804  {
805  _GLIBCXX_DEBUG_VERIFY(this->_M_can_advance(-__n),
806  _M_message(__msg_retreat_oob)
807  ._M_iterator(*this)._M_integer(__n));
809  this->base() -= __n;
810  return *this;
811  }
812 
813 #if __cpp_lib_three_way_comparison
814  friend auto
815  operator<=>(const _Self& __lhs, const _Self& __rhs) noexcept
816  {
817  _GLIBCXX_DEBUG_VERIFY_REL_OPERANDS(__lhs, __rhs);
818  return __lhs.base() <=> __rhs.base();
819  }
820 
821  friend auto
822  operator<=>(const _Self& __lhs, const _OtherSelf& __rhs) noexcept
823  {
824  _GLIBCXX_DEBUG_VERIFY_REL_OPERANDS(__lhs, __rhs);
825  return __lhs.base() <=> __rhs.base();
826  }
827 #else
828  friend bool
829  operator<(const _Self& __lhs, const _Self& __rhs) _GLIBCXX_NOEXCEPT
830  {
831  _GLIBCXX_DEBUG_VERIFY_REL_OPERANDS(__lhs, __rhs);
832  return __lhs.base() < __rhs.base();
833  }
834 
835  friend bool
836  operator<(const _Self& __lhs, const _OtherSelf& __rhs) _GLIBCXX_NOEXCEPT
837  {
838  _GLIBCXX_DEBUG_VERIFY_REL_OPERANDS(__lhs, __rhs);
839  return __lhs.base() < __rhs.base();
840  }
841 
842  friend bool
843  operator<=(const _Self& __lhs, const _Self& __rhs) _GLIBCXX_NOEXCEPT
844  {
845  _GLIBCXX_DEBUG_VERIFY_REL_OPERANDS(__lhs, __rhs);
846  return __lhs.base() <= __rhs.base();
847  }
848 
849  friend bool
850  operator<=(const _Self& __lhs, const _OtherSelf& __rhs) _GLIBCXX_NOEXCEPT
851  {
852  _GLIBCXX_DEBUG_VERIFY_REL_OPERANDS(__lhs, __rhs);
853  return __lhs.base() <= __rhs.base();
854  }
855 
856  friend bool
857  operator>(const _Self& __lhs, const _Self& __rhs) _GLIBCXX_NOEXCEPT
858  {
859  _GLIBCXX_DEBUG_VERIFY_REL_OPERANDS(__lhs, __rhs);
860  return __lhs.base() > __rhs.base();
861  }
862 
863  friend bool
864  operator>(const _Self& __lhs, const _OtherSelf& __rhs) _GLIBCXX_NOEXCEPT
865  {
866  _GLIBCXX_DEBUG_VERIFY_REL_OPERANDS(__lhs, __rhs);
867  return __lhs.base() > __rhs.base();
868  }
869 
870  friend bool
871  operator>=(const _Self& __lhs, const _Self& __rhs) _GLIBCXX_NOEXCEPT
872  {
873  _GLIBCXX_DEBUG_VERIFY_REL_OPERANDS(__lhs, __rhs);
874  return __lhs.base() >= __rhs.base();
875  }
876 
877  friend bool
878  operator>=(const _Self& __lhs, const _OtherSelf& __rhs) _GLIBCXX_NOEXCEPT
879  {
880  _GLIBCXX_DEBUG_VERIFY_REL_OPERANDS(__lhs, __rhs);
881  return __lhs.base() >= __rhs.base();
882  }
883 #endif // three-way comparison
884 
885  // _GLIBCXX_RESOLVE_LIB_DEFECTS
886  // According to the resolution of DR179 not only the various comparison
887  // operators but also operator- must accept mixed iterator/const_iterator
888  // parameters.
889  friend difference_type
890  operator-(const _Self& __lhs, const _OtherSelf& __rhs) _GLIBCXX_NOEXCEPT
891  {
892  _GLIBCXX_DEBUG_VERIFY_DIST_OPERANDS(__lhs, __rhs);
893  return __lhs.base() - __rhs.base();
894  }
895 
896  friend difference_type
897  operator-(const _Self& __lhs, const _Self& __rhs) _GLIBCXX_NOEXCEPT
898  {
899  _GLIBCXX_DEBUG_VERIFY_DIST_OPERANDS(__lhs, __rhs);
900  return __lhs.base() - __rhs.base();
901  }
902 
903  friend _Self
904  operator+(const _Self& __x, difference_type __n) _GLIBCXX_NOEXCEPT
905  {
906  _GLIBCXX_DEBUG_VERIFY(__x._M_can_advance(__n),
907  _M_message(__msg_advance_oob)
908  ._M_iterator(__x)._M_integer(__n));
909  return _Safe_iterator(__x.base() + __n, __x._M_sequence);
910  }
911 
912  friend _Self
913  operator+(difference_type __n, const _Self& __x) _GLIBCXX_NOEXCEPT
914  {
915  _GLIBCXX_DEBUG_VERIFY(__x._M_can_advance(__n),
916  _M_message(__msg_advance_oob)
917  ._M_iterator(__x)._M_integer(__n));
918  return _Safe_iterator(__n + __x.base(), __x._M_sequence);
919  }
920 
921  friend _Self
922  operator-(const _Self& __x, difference_type __n) _GLIBCXX_NOEXCEPT
923  {
924  _GLIBCXX_DEBUG_VERIFY(__x._M_can_advance(-__n),
925  _M_message(__msg_retreat_oob)
926  ._M_iterator(__x)._M_integer(__n));
927  return _Safe_iterator(__x.base() - __n, __x._M_sequence);
928  }
929  };
930 
931  /** Safe iterators know how to check if they form a valid range. */
932  template<typename _Iterator, typename _Sequence, typename _Category>
933  inline bool
934  __valid_range(const _Safe_iterator<_Iterator, _Sequence,
935  _Category>& __first,
936  const _Safe_iterator<_Iterator, _Sequence,
937  _Category>& __last,
938  typename _Distance_traits<_Iterator>::__type& __dist)
939  { return __first._M_valid_range(__last, __dist); }
940 
941  template<typename _Iterator, typename _Sequence, typename _Category>
942  inline bool
943  __valid_range(const _Safe_iterator<_Iterator, _Sequence,
944  _Category>& __first,
945  const _Safe_iterator<_Iterator, _Sequence,
946  _Category>& __last)
947  {
948  typename _Distance_traits<_Iterator>::__type __dist;
949  return __first._M_valid_range(__last, __dist);
950  }
951 
952  template<typename _Iterator, typename _Sequence, typename _Category,
953  typename _Size>
954  inline bool
955  __can_advance(const _Safe_iterator<_Iterator, _Sequence, _Category>& __it,
956  _Size __n)
957  { return __it._M_can_advance(__n); }
958 
959  template<typename _Iterator, typename _Sequence>
960  _Iterator
961  __base(const _Safe_iterator<_Iterator, _Sequence,
963  { return __it.base(); }
964 
965 #if __cplusplus < 201103L
966  template<typename _Iterator, typename _Sequence>
967  struct _Unsafe_type<_Safe_iterator<_Iterator, _Sequence> >
968  { typedef _Iterator _Type; };
969 #endif
970 
971  template<typename _Iterator, typename _Sequence>
972  inline _Iterator
973  __unsafe(const _Safe_iterator<_Iterator, _Sequence>& __it)
974  { return __it.base(); }
975 
976 } // namespace __gnu_debug
977 
978 #undef _GLIBCXX_DEBUG_VERIFY_DIST_OPERANDS
979 #undef _GLIBCXX_DEBUG_VERIFY_REL_OPERANDS
980 #undef _GLIBCXX_DEBUG_VERIFY_EQ_OPERANDS
981 #undef _GLIBCXX_DEBUG_VERIFY_OPERANDS
982 
983 #include <debug/safe_iterator.tcc>
984 
985 #endif
constexpr complex< _Tp > operator-(const complex< _Tp > &__x, const complex< _Tp > &__y)
Return new complex value x minus y.
Definition: complex:361
Safe iterator wrapper.
Definition: debug.h:61
_Safe_iterator(_Safe_iterator &&__x) noexcept
Move construction.
_Safe_iterator & operator++() noexcept
Iterator preincrement.
bool _M_is_begin() const
Is this iterator equal to the sequence&#39;s begin() iterator?
_Iterator & base() noexcept
Return the underlying iterator.
Scoped lock idiom.
Definition: concurrence.h:228
constexpr bool __valid_range(_InputIterator __first, _InputIterator __last, typename _Distance_traits< _InputIterator >::__type &__dist)
void _M_attach_single(_Safe_sequence_base *__seq, bool __constant)
bool _M_is_beginnest() const
Is this iterator equal to the sequence&#39;s before_begin() iterator if any or begin() otherwise...
bool _M_before_dereferenceable() const
Is the iterator before a dereferenceable one?
void _M_attach(_Safe_sequence_base *__seq, bool __constant)
Bidirectional iterators support a superset of forward iterator operations.
reference operator*() const noexcept
Iterator dereference.
_Safe_sequence_base * _M_sequence
Definition: safe_base.h:57
_Safe_iterator & operator=(const _Safe_iterator &__x) noexcept
Copy assignment.
__gnu_cxx::__mutex & _M_get_mutex()
constexpr _Iterator __base(_Iterator __it)
bool _M_incrementable() const
Is the iterator incrementable?
Basic functionality for a safe iterator.
Definition: safe_base.h:50
void _M_attach_single(_Safe_sequence_base *__seq)
_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.
bool _M_is_before_begin() const
Is this iterator equal to the sequence&#39;s before_begin() iterator if any?
Random-access iterators support a superset of bidirectional iterator operations.
Traits class for iterators.
bool _M_is_end() const
Is this iterator equal to the sequence&#39;s end() iterator?
bool _M_dereferenceable() const
Is the iterator dereferenceable?
_Safe_iterator(const _Safe_iterator &__x) noexcept
Copy construction.
constexpr complex< _Tp > operator+(const complex< _Tp > &__x, const complex< _Tp > &__y)
Return new complex value x plus y.
Definition: complex:331
void _M_attach(_Safe_sequence_base *__seq)
Struct holding two objects of arbitrary type.
Definition: stl_pair.h:211
_Safe_iterator operator++(int) noexcept
Iterator postincrement.
pointer operator->() const noexcept
Iterator dereference.
Base class that supports tracking of iterators that reference a sequence.
Definition: safe_base.h:188
_Safe_iterator & operator=(_Safe_iterator &&__x) noexcept
Move assignment.
Forward iterators support a superset of input iterator operations.
static constexpr bool _S_constant()
Determine if this is a constant iterator.