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