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