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
113  : private _Iterator,
114  public _Safe_iterator_base
115  {
116  typedef _Iterator _Iter_base;
118 
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  // Can we advance the iterator using @p __dist in @p __way direction.
409  template<typename _Diff>
410  bool
411  _M_can_advance(const std::pair<_Diff, _Distance_precision>& __dist,
412  int __way) const;
413 
414  // Is the iterator range [*this, __rhs) valid?
415  bool
416  _M_valid_range(const _Safe_iterator& __rhs,
418  bool __check_dereferenceable = true) const;
419 
420  // The sequence this iterator references.
421  typename __gnu_cxx::__conditional_type<
422  _IsConstant::__value, const _Sequence*, _Sequence*>::__type
423  _M_get_sequence() const
424  { return static_cast<_Sequence*>(_M_sequence); }
425 
426  // Get distance to __rhs.
427  typename _Distance_traits<_Iterator>::__type
428  _M_get_distance_to(const _Safe_iterator& __rhs) const;
429 
430  // Get distance from sequence begin up to *this.
431  typename _Distance_traits<_Iterator>::__type
432  _M_get_distance_from_begin() const;
433 
434  // Get distance from *this to sequence end.
435  typename _Distance_traits<_Iterator>::__type
436  _M_get_distance_to_end() const;
437 
438  /// Is this iterator equal to the sequence's begin() iterator?
439  bool
440  _M_is_begin() const
441  { return base() == _M_get_sequence()->_M_base().begin(); }
442 
443  /// Is this iterator equal to the sequence's end() iterator?
444  bool
445  _M_is_end() const
446  { return base() == _M_get_sequence()->_M_base().end(); }
447 
448  /// Is this iterator equal to the sequence's before_begin() iterator if
449  /// any?
450  bool
452  { return _BeforeBeginHelper<_Sequence>::_S_Is(*this); }
453 
454  /// Is this iterator equal to the sequence's before_begin() iterator if
455  /// any or begin() otherwise?
456  bool
459 
460  // ------ Operators ------
461 
463 
464  friend bool
465  operator==(const _Self& __lhs, const _Self& __rhs) _GLIBCXX_NOEXCEPT
466  {
467  _GLIBCXX_DEBUG_VERIFY_EQ_OPERANDS(__lhs, __rhs);
468  return __lhs.base() == __rhs.base();
469  }
470 
471  template<typename _IteR>
472  friend bool
473  operator==(const _Self& __lhs,
474  const _Safe_iterator<_IteR, _Sequence, iterator_category>& __rhs)
475  _GLIBCXX_NOEXCEPT
476  {
477  _GLIBCXX_DEBUG_VERIFY_EQ_OPERANDS(__lhs, __rhs);
478  return __lhs.base() == __rhs.base();
479  }
480 
481 #if ! __cpp_lib_three_way_comparison
482  friend bool
483  operator!=(const _Self& __lhs, const _Self& __rhs) _GLIBCXX_NOEXCEPT
484  {
485  _GLIBCXX_DEBUG_VERIFY_EQ_OPERANDS(__lhs, __rhs);
486  return __lhs.base() != __rhs.base();
487  }
488 
489  template<typename _IteR>
490  friend bool
491  operator!=(const _Self& __lhs,
492  const _Safe_iterator<_IteR, _Sequence, iterator_category>& __rhs)
493  _GLIBCXX_NOEXCEPT
494  {
495  _GLIBCXX_DEBUG_VERIFY_EQ_OPERANDS(__lhs, __rhs);
496  return __lhs.base() != __rhs.base();
497  }
498 #endif // three-way comparison
499  };
500 
501  template<typename _Iterator, typename _Sequence>
502  class _Safe_iterator<_Iterator, _Sequence, std::bidirectional_iterator_tag>
503  : public _Safe_iterator<_Iterator, _Sequence, std::forward_iterator_tag>
504  {
505  typedef _Safe_iterator<_Iterator, _Sequence,
506  std::forward_iterator_tag> _Safe_base;
507 
508  protected:
509  typedef typename _Safe_base::_OtherIterator _OtherIterator;
510  typedef typename _Safe_base::_Attach_single _Attach_single;
511 
512  _Safe_iterator(_Iterator __i, _Safe_sequence_base* __seq, _Attach_single)
513  _GLIBCXX_NOEXCEPT
514  : _Safe_base(__i, __seq, _Attach_single())
515  { }
516 
517  public:
518  /// @post the iterator is singular and unattached
519  _Safe_iterator() _GLIBCXX_NOEXCEPT { }
520 
521  /**
522  * @brief Safe iterator construction from an unsafe iterator and
523  * its sequence.
524  *
525  * @pre @p seq is not NULL
526  * @post this is not singular
527  */
528  _Safe_iterator(_Iterator __i, const _Safe_sequence_base* __seq)
529  _GLIBCXX_NOEXCEPT
530  : _Safe_base(__i, __seq)
531  { }
532 
533  /**
534  * @brief Copy construction.
535  */
536  _Safe_iterator(const _Safe_iterator& __x) _GLIBCXX_NOEXCEPT
537  : _Safe_base(__x)
538  { }
539 
540 #if __cplusplus >= 201103L
541  /** @brief Move construction. */
542  _Safe_iterator(_Safe_iterator&&) = default;
543 #endif
544 
545  /**
546  * @brief Converting constructor from a mutable iterator to a
547  * constant iterator.
548  */
549  template<typename _MutableIterator>
551  const _Safe_iterator<_MutableIterator, _Sequence,
552  typename __gnu_cxx::__enable_if<_Safe_base::_IsConstant::__value &&
553  std::__are_same<_MutableIterator, _OtherIterator>::__value,
554  std::bidirectional_iterator_tag>::__type>& __x)
555  _GLIBCXX_NOEXCEPT
556  : _Safe_base(__x)
557  { }
558 
559 #if __cplusplus >= 201103L
560  /** @brief Copy assignment. */
562  operator=(const _Safe_iterator&) = default;
563 
564  /** @brief Move assignment. */
566  operator=(_Safe_iterator&&) = default;
567 #else
568  /** @brief Copy assignment. */
570  operator=(const _Safe_iterator& __x)
571  {
572  _Safe_base::operator=(__x);
573  return *this;
574  }
575 #endif
576 
577  // ------ Input iterator requirements ------
578  /**
579  * @brief Iterator preincrement
580  * @pre iterator is incrementable
581  */
583  operator++() _GLIBCXX_NOEXCEPT
584  {
585  _Safe_base::operator++();
586  return *this;
587  }
588 
589  /**
590  * @brief Iterator postincrement
591  * @pre iterator is incrementable
592  */
594  operator++(int) _GLIBCXX_NOEXCEPT
595  {
596  _GLIBCXX_DEBUG_VERIFY(this->_M_incrementable(),
597  _M_message(__msg_bad_inc)
598  ._M_iterator(*this, "this"));
600  return _Safe_iterator(this->base()++, this->_M_sequence,
601  _Attach_single());
602  }
603 
604  // ------ Bidirectional iterator requirements ------
605  /**
606  * @brief Iterator predecrement
607  * @pre iterator is decrementable
608  */
610  operator--() _GLIBCXX_NOEXCEPT
611  {
612  _GLIBCXX_DEBUG_VERIFY(this->_M_decrementable(),
613  _M_message(__msg_bad_dec)
614  ._M_iterator(*this, "this"));
616  --this->base();
617  return *this;
618  }
619 
620  /**
621  * @brief Iterator postdecrement
622  * @pre iterator is decrementable
623  */
625  operator--(int) _GLIBCXX_NOEXCEPT
626  {
627  _GLIBCXX_DEBUG_VERIFY(this->_M_decrementable(),
628  _M_message(__msg_bad_dec)
629  ._M_iterator(*this, "this"));
631  return _Safe_iterator(this->base()--, this->_M_sequence,
632  _Attach_single());
633  }
634 
635  // ------ Utilities ------
636 
637  // Is the iterator decrementable?
638  bool
639  _M_decrementable() const
640  { return !this->_M_singular() && !this->_M_is_begin(); }
641  };
642 
643  template<typename _Iterator, typename _Sequence>
644  class _Safe_iterator<_Iterator, _Sequence, std::random_access_iterator_tag>
645  : public _Safe_iterator<_Iterator, _Sequence,
646  std::bidirectional_iterator_tag>
647  {
648  typedef _Safe_iterator<_Iterator, _Sequence,
650  typedef typename _Safe_base::_OtherIterator _OtherIterator;
651 
652  typedef typename _Safe_base::_Self _Self;
653  typedef _Safe_iterator<_OtherIterator, _Sequence,
655 
656  typedef typename _Safe_base::_Attach_single _Attach_single;
657 
658  _Safe_iterator(_Iterator __i, _Safe_sequence_base* __seq, _Attach_single)
659  _GLIBCXX_NOEXCEPT
660  : _Safe_base(__i, __seq, _Attach_single())
661  { }
662 
663  public:
664  typedef typename _Safe_base::difference_type difference_type;
665  typedef typename _Safe_base::reference reference;
666 
667  /// @post the iterator is singular and unattached
668  _Safe_iterator() _GLIBCXX_NOEXCEPT { }
669 
670  /**
671  * @brief Safe iterator construction from an unsafe iterator and
672  * its sequence.
673  *
674  * @pre @p seq is not NULL
675  * @post this is not singular
676  */
677  _Safe_iterator(_Iterator __i, const _Safe_sequence_base* __seq)
678  _GLIBCXX_NOEXCEPT
679  : _Safe_base(__i, __seq)
680  { }
681 
682  /**
683  * @brief Copy construction.
684  */
685  _Safe_iterator(const _Safe_iterator& __x) _GLIBCXX_NOEXCEPT
686  : _Safe_base(__x)
687  { }
688 
689 #if __cplusplus >= 201103L
690  /** @brief Move construction. */
691  _Safe_iterator(_Safe_iterator&&) = default;
692 #endif
693 
694  /**
695  * @brief Converting constructor from a mutable iterator to a
696  * constant iterator.
697  */
698  template<typename _MutableIterator>
700  const _Safe_iterator<_MutableIterator, _Sequence,
701  typename __gnu_cxx::__enable_if<_Safe_base::_IsConstant::__value &&
702  std::__are_same<_MutableIterator, _OtherIterator>::__value,
703  std::random_access_iterator_tag>::__type>& __x)
704  _GLIBCXX_NOEXCEPT
705  : _Safe_base(__x)
706  { }
707 
708 #if __cplusplus >= 201103L
709  /** @brief Copy assignment. */
711  operator=(const _Safe_iterator&) = default;
712 
713  /** @brief Move assignment. */
715  operator=(_Safe_iterator&&) = default;
716 #else
717  /** @brief Copy assignment. */
719  operator=(const _Safe_iterator& __x)
720  {
721  _Safe_base::operator=(__x);
722  return *this;
723  }
724 #endif
725 
726  // Is the iterator range [*this, __rhs) valid?
727  bool
728  _M_valid_range(const _Safe_iterator& __rhs,
729  std::pair<difference_type,
730  _Distance_precision>& __dist) const;
731 
732  // ------ Input iterator requirements ------
733  /**
734  * @brief Iterator preincrement
735  * @pre iterator is incrementable
736  */
738  operator++() _GLIBCXX_NOEXCEPT
739  {
740  _Safe_base::operator++();
741  return *this;
742  }
743 
744  /**
745  * @brief Iterator postincrement
746  * @pre iterator is incrementable
747  */
749  operator++(int) _GLIBCXX_NOEXCEPT
750  {
751  _GLIBCXX_DEBUG_VERIFY(this->_M_incrementable(),
752  _M_message(__msg_bad_inc)
753  ._M_iterator(*this, "this"));
755  return _Safe_iterator(this->base()++, this->_M_sequence,
756  _Attach_single());
757  }
758 
759  // ------ Bidirectional iterator requirements ------
760  /**
761  * @brief Iterator predecrement
762  * @pre iterator is decrementable
763  */
765  operator--() _GLIBCXX_NOEXCEPT
766  {
767  _Safe_base::operator--();
768  return *this;
769  }
770 
771  /**
772  * @brief Iterator postdecrement
773  * @pre iterator is decrementable
774  */
776  operator--(int) _GLIBCXX_NOEXCEPT
777  {
778  _GLIBCXX_DEBUG_VERIFY(this->_M_decrementable(),
779  _M_message(__msg_bad_dec)
780  ._M_iterator(*this, "this"));
782  return _Safe_iterator(this->base()--, this->_M_sequence,
783  _Attach_single());
784  }
785 
786  // ------ Random access iterator requirements ------
787  reference
788  operator[](difference_type __n) const _GLIBCXX_NOEXCEPT
789  {
790  _GLIBCXX_DEBUG_VERIFY(this->_M_can_advance(__n)
791  && this->_M_can_advance(__n + 1),
792  _M_message(__msg_iter_subscript_oob)
793  ._M_iterator(*this)._M_integer(__n));
794  return this->base()[__n];
795  }
796 
798  operator+=(difference_type __n) _GLIBCXX_NOEXCEPT
799  {
800  _GLIBCXX_DEBUG_VERIFY(this->_M_can_advance(__n),
801  _M_message(__msg_advance_oob)
802  ._M_iterator(*this)._M_integer(__n));
804  this->base() += __n;
805  return *this;
806  }
807 
809  operator-=(difference_type __n) _GLIBCXX_NOEXCEPT
810  {
811  _GLIBCXX_DEBUG_VERIFY(this->_M_can_advance(-__n),
812  _M_message(__msg_retreat_oob)
813  ._M_iterator(*this)._M_integer(__n));
815  this->base() -= __n;
816  return *this;
817  }
818 
819 #if __cpp_lib_three_way_comparison
820  friend auto
821  operator<=>(const _Self& __lhs, const _Self& __rhs) noexcept
822  {
823  _GLIBCXX_DEBUG_VERIFY_REL_OPERANDS(__lhs, __rhs);
824  return __lhs.base() <=> __rhs.base();
825  }
826 
827  friend auto
828  operator<=>(const _Self& __lhs, const _OtherSelf& __rhs) noexcept
829  {
830  _GLIBCXX_DEBUG_VERIFY_REL_OPERANDS(__lhs, __rhs);
831  return __lhs.base() <=> __rhs.base();
832  }
833 #else
834  friend bool
835  operator<(const _Self& __lhs, const _Self& __rhs) _GLIBCXX_NOEXCEPT
836  {
837  _GLIBCXX_DEBUG_VERIFY_REL_OPERANDS(__lhs, __rhs);
838  return __lhs.base() < __rhs.base();
839  }
840 
841  friend bool
842  operator<(const _Self& __lhs, const _OtherSelf& __rhs) _GLIBCXX_NOEXCEPT
843  {
844  _GLIBCXX_DEBUG_VERIFY_REL_OPERANDS(__lhs, __rhs);
845  return __lhs.base() < __rhs.base();
846  }
847 
848  friend bool
849  operator<=(const _Self& __lhs, const _Self& __rhs) _GLIBCXX_NOEXCEPT
850  {
851  _GLIBCXX_DEBUG_VERIFY_REL_OPERANDS(__lhs, __rhs);
852  return __lhs.base() <= __rhs.base();
853  }
854 
855  friend bool
856  operator<=(const _Self& __lhs, const _OtherSelf& __rhs) _GLIBCXX_NOEXCEPT
857  {
858  _GLIBCXX_DEBUG_VERIFY_REL_OPERANDS(__lhs, __rhs);
859  return __lhs.base() <= __rhs.base();
860  }
861 
862  friend bool
863  operator>(const _Self& __lhs, const _Self& __rhs) _GLIBCXX_NOEXCEPT
864  {
865  _GLIBCXX_DEBUG_VERIFY_REL_OPERANDS(__lhs, __rhs);
866  return __lhs.base() > __rhs.base();
867  }
868 
869  friend bool
870  operator>(const _Self& __lhs, const _OtherSelf& __rhs) _GLIBCXX_NOEXCEPT
871  {
872  _GLIBCXX_DEBUG_VERIFY_REL_OPERANDS(__lhs, __rhs);
873  return __lhs.base() > __rhs.base();
874  }
875 
876  friend bool
877  operator>=(const _Self& __lhs, const _Self& __rhs) _GLIBCXX_NOEXCEPT
878  {
879  _GLIBCXX_DEBUG_VERIFY_REL_OPERANDS(__lhs, __rhs);
880  return __lhs.base() >= __rhs.base();
881  }
882 
883  friend bool
884  operator>=(const _Self& __lhs, const _OtherSelf& __rhs) _GLIBCXX_NOEXCEPT
885  {
886  _GLIBCXX_DEBUG_VERIFY_REL_OPERANDS(__lhs, __rhs);
887  return __lhs.base() >= __rhs.base();
888  }
889 #endif // three-way comparison
890 
891  // _GLIBCXX_RESOLVE_LIB_DEFECTS
892  // According to the resolution of DR179 not only the various comparison
893  // operators but also operator- must accept mixed iterator/const_iterator
894  // parameters.
895  friend difference_type
896  operator-(const _Self& __lhs, const _OtherSelf& __rhs) _GLIBCXX_NOEXCEPT
897  {
898  _GLIBCXX_DEBUG_VERIFY_DIST_OPERANDS(__lhs, __rhs);
899  return __lhs.base() - __rhs.base();
900  }
901 
902  friend difference_type
903  operator-(const _Self& __lhs, const _Self& __rhs) _GLIBCXX_NOEXCEPT
904  {
905  _GLIBCXX_DEBUG_VERIFY_DIST_OPERANDS(__lhs, __rhs);
906  return __lhs.base() - __rhs.base();
907  }
908 
909  friend _Self
910  operator+(const _Self& __x, difference_type __n) _GLIBCXX_NOEXCEPT
911  {
912  _GLIBCXX_DEBUG_VERIFY(__x._M_can_advance(__n),
913  _M_message(__msg_advance_oob)
914  ._M_iterator(__x)._M_integer(__n));
915  return _Safe_iterator(__x.base() + __n, __x._M_sequence);
916  }
917 
918  friend _Self
919  operator+(difference_type __n, const _Self& __x) _GLIBCXX_NOEXCEPT
920  {
921  _GLIBCXX_DEBUG_VERIFY(__x._M_can_advance(__n),
922  _M_message(__msg_advance_oob)
923  ._M_iterator(__x)._M_integer(__n));
924  return _Safe_iterator(__n + __x.base(), __x._M_sequence);
925  }
926 
927  friend _Self
928  operator-(const _Self& __x, difference_type __n) _GLIBCXX_NOEXCEPT
929  {
930  _GLIBCXX_DEBUG_VERIFY(__x._M_can_advance(-__n),
931  _M_message(__msg_retreat_oob)
932  ._M_iterator(__x)._M_integer(__n));
933  return _Safe_iterator(__x.base() - __n, __x._M_sequence);
934  }
935  };
936 
937  /** Safe iterators know how to check if they form a valid range. */
938  template<typename _Iterator, typename _Sequence, typename _Category>
939  inline bool
940  __valid_range(const _Safe_iterator<_Iterator, _Sequence,
941  _Category>& __first,
942  const _Safe_iterator<_Iterator, _Sequence,
943  _Category>& __last,
944  typename _Distance_traits<_Iterator>::__type& __dist)
945  { return __first._M_valid_range(__last, __dist); }
946 
947  template<typename _Iterator, typename _Sequence, typename _Category>
948  inline bool
949  __valid_range(const _Safe_iterator<_Iterator, _Sequence,
950  _Category>& __first,
951  const _Safe_iterator<_Iterator, _Sequence,
952  _Category>& __last)
953  {
954  typename _Distance_traits<_Iterator>::__type __dist;
955  return __first._M_valid_range(__last, __dist);
956  }
957 
958  template<typename _Iterator, typename _Sequence, typename _Category,
959  typename _Size>
960  inline bool
961  __can_advance(const _Safe_iterator<_Iterator, _Sequence, _Category>& __it,
962  _Size __n)
963  { return __it._M_can_advance(__n); }
964 
965  template<typename _Iterator, typename _Sequence, typename _Category,
966  typename _Diff>
967  inline bool
968  __can_advance(const _Safe_iterator<_Iterator, _Sequence, _Category>& __it,
970  int __way)
971  { return __it._M_can_advance(__dist, __way); }
972 
973  template<typename _Iterator, typename _Sequence>
974  _Iterator
975  __base(const _Safe_iterator<_Iterator, _Sequence,
977  { return __it.base(); }
978 
979 #if __cplusplus < 201103L
980  template<typename _Iterator, typename _Sequence>
981  struct _Unsafe_type<_Safe_iterator<_Iterator, _Sequence> >
982  { typedef _Iterator _Type; };
983 #endif
984 
985  template<typename _Iterator, typename _Sequence>
986  inline _Iterator
987  __unsafe(const _Safe_iterator<_Iterator, _Sequence>& __it)
988  { return __it.base(); }
989 
990 } // namespace __gnu_debug
991 
992 #undef _GLIBCXX_DEBUG_VERIFY_DIST_OPERANDS
993 #undef _GLIBCXX_DEBUG_VERIFY_REL_OPERANDS
994 #undef _GLIBCXX_DEBUG_VERIFY_EQ_OPERANDS
995 #undef _GLIBCXX_DEBUG_VERIFY_OPERANDS
996 
997 #include <debug/safe_iterator.tcc>
998 
999 #endif
constexpr complex< _Tp > operator-(const complex< _Tp > &__x, const complex< _Tp > &__y)
Return new complex value x minus y.
Definition: complex:361
constexpr complex< _Tp > operator+(const complex< _Tp > &__x, const complex< _Tp > &__y)
Return new complex value x plus y.
Definition: complex:331
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)
Traits class for iterators.
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.
Struct holding two objects of arbitrary type.
Definition: stl_pair.h:213
Safe iterator wrapper.
bool _M_incrementable() const
Is the iterator incrementable?
reference operator*() const noexcept
Iterator dereference.
_Safe_iterator operator++(int) noexcept
Iterator postincrement.
_Safe_iterator(const _Safe_iterator &__x) noexcept
Copy construction.
_Safe_iterator(_Safe_iterator &&__x) noexcept
Move construction.
bool _M_dereferenceable() const
Is the iterator dereferenceable?
void _M_attach_single(_Safe_sequence_base *__seq)
_Iterator & base() noexcept
Return the underlying iterator.
bool _M_before_dereferenceable() const
Is the iterator before a dereferenceable one?
_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_beginnest() const
Is this iterator equal to the sequence's before_begin() iterator if any or begin() otherwise?
_Safe_iterator & operator=(_Safe_iterator &&__x) noexcept
Move assignment.
bool _M_is_begin() const
Is this iterator equal to the sequence's begin() iterator?
_Safe_iterator(_Iterator __i, const _Safe_sequence_base *__seq) noexcept
Safe iterator construction from an unsafe iterator and its sequence.
bool _M_is_end() const
Is this iterator equal to the sequence's end() iterator?
void _M_attach(_Safe_sequence_base *__seq)
_Safe_iterator & operator=(const _Safe_iterator &__x) noexcept
Copy assignment.
bool _M_is_before_begin() const
Is this iterator equal to the sequence's before_begin() iterator if any?
static constexpr bool _S_constant()
Determine if this is a constant iterator.
_Safe_iterator & operator++() noexcept
Iterator preincrement.
pointer operator->() const noexcept
Iterator dereference.
Basic functionality for a safe iterator.
Definition: safe_base.h:51
_Safe_sequence_base * _M_sequence
Definition: safe_base.h:57
void _M_attach_single(_Safe_sequence_base *__seq, bool __constant)
void _M_attach(_Safe_sequence_base *__seq, bool __constant)
__gnu_cxx::__mutex & _M_get_mutex()
Base class that supports tracking of iterators that reference a sequence.
Definition: safe_base.h:189
Scoped lock idiom.
Definition: concurrence.h:229