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