libstdc++
safe_iterator.h
Go to the documentation of this file.
1 // Safe iterator implementation -*- C++ -*-
2 
3 // Copyright (C) 2003-2015 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/debug.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 namespace __gnu_debug
40 {
41  /** Helper struct to deal with sequence offering a before_begin
42  * iterator.
43  **/
44  template <typename _Sequence>
46  {
47  template<typename _Iterator>
48  static bool
50  { return false; }
51 
52  template<typename _Iterator>
53  static bool
54  _S_Is_Beginnest(const _Safe_iterator<_Iterator, _Sequence>& __it)
55  { return __it.base() == __it._M_get_sequence()->_M_base().begin(); }
56  };
57 
58  /** Iterators that derive from _Safe_iterator_base can be determined singular
59  * or non-singular.
60  **/
61  inline bool
62  __check_singular_aux(const _Safe_iterator_base* __x)
63  { return __x->_M_singular(); }
64 
65  /** The precision to which we can calculate the distance between
66  * two iterators.
67  */
69  {
70  __dp_equality, //< Can compare iterator equality, only
71  __dp_sign, //< Can determine equality and ordering
72  __dp_exact //< Can determine distance precisely
73  };
74 
75  /** Determine the distance between two iterators with some known
76  * precision.
77  */
78  template<typename _Iterator>
81  __get_distance(const _Iterator& __lhs, const _Iterator& __rhs,
83  { return std::make_pair(__rhs - __lhs, __dp_exact); }
84 
85  template<typename _Iterator>
88  __get_distance(const _Iterator& __lhs, const _Iterator& __rhs,
90  { return std::make_pair(__lhs == __rhs? 0 : 1, __dp_equality); }
91 
92  template<typename _Iterator>
95  __get_distance(const _Iterator& __lhs, const _Iterator& __rhs)
96  {
97  typedef typename std::iterator_traits<_Iterator>::iterator_category
98  _Category;
99  return __get_distance(__lhs, __rhs, _Category());
100  }
101 
102  /** \brief Safe iterator wrapper.
103  *
104  * The class template %_Safe_iterator is a wrapper around an
105  * iterator that tracks the iterator's movement among sequences and
106  * checks that operations performed on the "safe" iterator are
107  * legal. In additional to the basic iterator operations (which are
108  * validated, and then passed to the underlying iterator),
109  * %_Safe_iterator has member functions for iterator invalidation,
110  * attaching/detaching the iterator from sequences, and querying
111  * the iterator's state.
112  *
113  * Note that _Iterator must be the first base class so that it gets
114  * initialized before the iterator is being attached to the container's list
115  * of iterators and it is being detached before _Iterator get
116  * destroyed. Otherwise it would result in a data race.
117  */
118  template<typename _Iterator, typename _Sequence>
119  class _Safe_iterator
120  : private _Iterator,
121  public _Safe_iterator_base
122  {
123  typedef _Iterator _Iter_base;
124  typedef _Safe_iterator_base _Safe_base;
125  typedef typename _Sequence::const_iterator _Const_iterator;
126 
127  /// Determine if this is a constant iterator.
128  bool
129  _M_constant() const
130  { return std::__are_same<_Const_iterator, _Safe_iterator>::__value; }
131 
132  typedef std::iterator_traits<_Iterator> _Traits;
133 
134  struct _Attach_single
135  { };
136 
137  _Safe_iterator(const _Iterator& __i, _Safe_sequence_base* __seq,
138  _Attach_single)
139  _GLIBCXX_NOEXCEPT
140  : _Iter_base(__i)
141  { _M_attach_single(__seq); }
142 
143  public:
144  typedef _Iterator iterator_type;
145  typedef typename _Traits::iterator_category iterator_category;
146  typedef typename _Traits::value_type value_type;
147  typedef typename _Traits::difference_type difference_type;
148  typedef typename _Traits::reference reference;
149  typedef typename _Traits::pointer pointer;
150 
151  /// @post the iterator is singular and unattached
152  _Safe_iterator() _GLIBCXX_NOEXCEPT : _Iter_base() { }
153 
154  /**
155  * @brief Safe iterator construction from an unsafe iterator and
156  * its sequence.
157  *
158  * @pre @p seq is not NULL
159  * @post this is not singular
160  */
161  _Safe_iterator(const _Iterator& __i, const _Safe_sequence_base* __seq)
162  _GLIBCXX_NOEXCEPT
163  : _Iter_base(__i), _Safe_base(__seq, _M_constant())
164  {
165  _GLIBCXX_DEBUG_VERIFY(!this->_M_singular(),
166  _M_message(__msg_init_singular)
167  ._M_iterator(*this, "this"));
168  }
169 
170  /**
171  * @brief Copy construction.
172  */
173  _Safe_iterator(const _Safe_iterator& __x) _GLIBCXX_NOEXCEPT
174  : _Iter_base(__x.base())
175  {
176  // _GLIBCXX_RESOLVE_LIB_DEFECTS
177  // DR 408. Is vector<reverse_iterator<char*> > forbidden?
178  _GLIBCXX_DEBUG_VERIFY(!__x._M_singular()
179  || __x.base() == _Iterator(),
180  _M_message(__msg_init_copy_singular)
181  ._M_iterator(*this, "this")
182  ._M_iterator(__x, "other"));
183  _M_attach(__x._M_sequence);
184  }
185 
186 #if __cplusplus >= 201103L
187  /**
188  * @brief Move construction.
189  * @post __x is singular and unattached
190  */
192  : _Iter_base()
193  {
194  _GLIBCXX_DEBUG_VERIFY(!__x._M_singular()
195  || __x.base() == _Iterator(),
196  _M_message(__msg_init_copy_singular)
197  ._M_iterator(*this, "this")
198  ._M_iterator(__x, "other"));
199  _Safe_sequence_base* __seq = __x._M_sequence;
200  __x._M_detach();
201  std::swap(base(), __x.base());
202  _M_attach(__seq);
203  }
204 #endif
205 
206  /**
207  * @brief Converting constructor from a mutable iterator to a
208  * constant iterator.
209  */
210  template<typename _MutableIterator>
212  const _Safe_iterator<_MutableIterator,
213  typename __gnu_cxx::__enable_if<(std::__are_same<_MutableIterator,
214  typename _Sequence::iterator::iterator_type>::__value),
215  _Sequence>::__type>& __x) _GLIBCXX_NOEXCEPT
216  : _Iter_base(__x.base())
217  {
218  // _GLIBCXX_RESOLVE_LIB_DEFECTS
219  // DR 408. Is vector<reverse_iterator<char*> > forbidden?
220  _GLIBCXX_DEBUG_VERIFY(!__x._M_singular()
221  || __x.base() == _Iterator(),
222  _M_message(__msg_init_const_singular)
223  ._M_iterator(*this, "this")
224  ._M_iterator(__x, "other"));
225  _M_attach(__x._M_sequence);
226  }
227 
228  /**
229  * @brief Copy assignment.
230  */
232  operator=(const _Safe_iterator& __x) _GLIBCXX_NOEXCEPT
233  {
234  // _GLIBCXX_RESOLVE_LIB_DEFECTS
235  // DR 408. Is vector<reverse_iterator<char*> > forbidden?
236  _GLIBCXX_DEBUG_VERIFY(!__x._M_singular()
237  || __x.base() == _Iterator(),
238  _M_message(__msg_copy_singular)
239  ._M_iterator(*this, "this")
240  ._M_iterator(__x, "other"));
241 
242  if (this->_M_sequence && this->_M_sequence == __x._M_sequence)
243  {
244  __gnu_cxx::__scoped_lock __l(this->_M_get_mutex());
245  base() = __x.base();
246  _M_version = __x._M_sequence->_M_version;
247  }
248  else
249  {
250  _M_detach();
251  base() = __x.base();
252  _M_attach(__x._M_sequence);
253  }
254 
255  return *this;
256  }
257 
258 #if __cplusplus >= 201103L
259  /**
260  * @brief Move assignment.
261  * @post __x is singular and unattached
262  */
264  operator=(_Safe_iterator&& __x) noexcept
265  {
266  _GLIBCXX_DEBUG_VERIFY(this != &__x,
267  _M_message(__msg_self_move_assign)
268  ._M_iterator(*this, "this"));
269  _GLIBCXX_DEBUG_VERIFY(!__x._M_singular()
270  || __x.base() == _Iterator(),
271  _M_message(__msg_copy_singular)
272  ._M_iterator(*this, "this")
273  ._M_iterator(__x, "other"));
274 
275  if (this->_M_sequence && this->_M_sequence == __x._M_sequence)
276  {
277  __gnu_cxx::__scoped_lock __l(this->_M_get_mutex());
278  base() = __x.base();
279  _M_version = __x._M_sequence->_M_version;
280  }
281  else
282  {
283  _M_detach();
284  base() = __x.base();
285  _M_attach(__x._M_sequence);
286  }
287 
288  __x._M_detach();
289  __x.base() = _Iterator();
290  return *this;
291  }
292 #endif
293 
294  /**
295  * @brief Iterator dereference.
296  * @pre iterator is dereferenceable
297  */
298  reference
299  operator*() const _GLIBCXX_NOEXCEPT
300  {
301  _GLIBCXX_DEBUG_VERIFY(this->_M_dereferenceable(),
302  _M_message(__msg_bad_deref)
303  ._M_iterator(*this, "this"));
304  return *base();
305  }
306 
307  /**
308  * @brief Iterator dereference.
309  * @pre iterator is dereferenceable
310  * @todo Make this correct w.r.t. iterators that return proxies
311  */
312  pointer
313  operator->() const _GLIBCXX_NOEXCEPT
314  {
315  _GLIBCXX_DEBUG_VERIFY(this->_M_dereferenceable(),
316  _M_message(__msg_bad_deref)
317  ._M_iterator(*this, "this"));
318  return std::__addressof(*base());
319  }
320 
321  // ------ Input iterator requirements ------
322  /**
323  * @brief Iterator preincrement
324  * @pre iterator is incrementable
325  */
327  operator++() _GLIBCXX_NOEXCEPT
328  {
329  _GLIBCXX_DEBUG_VERIFY(this->_M_incrementable(),
330  _M_message(__msg_bad_inc)
331  ._M_iterator(*this, "this"));
332  __gnu_cxx::__scoped_lock(this->_M_get_mutex());
333  ++base();
334  return *this;
335  }
336 
337  /**
338  * @brief Iterator postincrement
339  * @pre iterator is incrementable
340  */
342  operator++(int) _GLIBCXX_NOEXCEPT
343  {
344  _GLIBCXX_DEBUG_VERIFY(this->_M_incrementable(),
345  _M_message(__msg_bad_inc)
346  ._M_iterator(*this, "this"));
347  __gnu_cxx::__scoped_lock __l(this->_M_get_mutex());
348  return _Safe_iterator(base()++, this->_M_sequence, _Attach_single());
349  }
350 
351  // ------ Bidirectional iterator requirements ------
352  /**
353  * @brief Iterator predecrement
354  * @pre iterator is decrementable
355  */
357  operator--() _GLIBCXX_NOEXCEPT
358  {
359  _GLIBCXX_DEBUG_VERIFY(this->_M_decrementable(),
360  _M_message(__msg_bad_dec)
361  ._M_iterator(*this, "this"));
362  __gnu_cxx::__scoped_lock __l(this->_M_get_mutex());
363  --base();
364  return *this;
365  }
366 
367  /**
368  * @brief Iterator postdecrement
369  * @pre iterator is decrementable
370  */
372  operator--(int) _GLIBCXX_NOEXCEPT
373  {
374  _GLIBCXX_DEBUG_VERIFY(this->_M_decrementable(),
375  _M_message(__msg_bad_dec)
376  ._M_iterator(*this, "this"));
377  __gnu_cxx::__scoped_lock __l(this->_M_get_mutex());
378  return _Safe_iterator(base()--, this->_M_sequence, _Attach_single());
379  }
380 
381  // ------ Random access iterator requirements ------
382  reference
383  operator[](const difference_type& __n) const _GLIBCXX_NOEXCEPT
384  {
385  _GLIBCXX_DEBUG_VERIFY(this->_M_can_advance(__n)
386  && this->_M_can_advance(__n+1),
387  _M_message(__msg_iter_subscript_oob)
388  ._M_iterator(*this)._M_integer(__n));
389  return base()[__n];
390  }
391 
393  operator+=(const difference_type& __n) _GLIBCXX_NOEXCEPT
394  {
395  _GLIBCXX_DEBUG_VERIFY(this->_M_can_advance(__n),
396  _M_message(__msg_advance_oob)
397  ._M_iterator(*this)._M_integer(__n));
398  __gnu_cxx::__scoped_lock __l(this->_M_get_mutex());
399  base() += __n;
400  return *this;
401  }
402 
404  operator+(const difference_type& __n) const _GLIBCXX_NOEXCEPT
405  {
406  _GLIBCXX_DEBUG_VERIFY(this->_M_can_advance(__n),
407  _M_message(__msg_advance_oob)
408  ._M_iterator(*this)._M_integer(__n));
409  return _Safe_iterator(base() + __n, this->_M_sequence);
410  }
411 
413  operator-=(const difference_type& __n) _GLIBCXX_NOEXCEPT
414  {
415  _GLIBCXX_DEBUG_VERIFY(this->_M_can_advance(-__n),
416  _M_message(__msg_retreat_oob)
417  ._M_iterator(*this)._M_integer(__n));
418  __gnu_cxx::__scoped_lock __l(this->_M_get_mutex());
419  base() -= __n;
420  return *this;
421  }
422 
424  operator-(const difference_type& __n) const _GLIBCXX_NOEXCEPT
425  {
426  _GLIBCXX_DEBUG_VERIFY(this->_M_can_advance(-__n),
427  _M_message(__msg_retreat_oob)
428  ._M_iterator(*this)._M_integer(__n));
429  return _Safe_iterator(base() - __n, this->_M_sequence);
430  }
431 
432  // ------ Utilities ------
433  /**
434  * @brief Return the underlying iterator
435  */
436  _Iterator&
437  base() _GLIBCXX_NOEXCEPT { return *this; }
438 
439  const _Iterator&
440  base() const _GLIBCXX_NOEXCEPT { return *this; }
441 
442  /**
443  * @brief Conversion to underlying non-debug iterator to allow
444  * better interaction with non-debug containers.
445  */
446  operator _Iterator() const _GLIBCXX_NOEXCEPT { return *this; }
447 
448  /** Attach iterator to the given sequence. */
449  void
451  { _Safe_base::_M_attach(__seq, _M_constant()); }
452 
453  /** Likewise, but not thread-safe. */
454  void
456  { _Safe_base::_M_attach_single(__seq, _M_constant()); }
457 
458  /// Is the iterator dereferenceable?
459  bool
461  { return !this->_M_singular() && !_M_is_end() && !_M_is_before_begin(); }
462 
463  /// Is the iterator before a dereferenceable one?
464  bool
466  {
467  if (this->_M_incrementable())
468  {
469  _Iterator __base = base();
470  return ++__base != _M_get_sequence()->_M_base().end();
471  }
472  return false;
473  }
474 
475  /// Is the iterator incrementable?
476  bool
478  { return !this->_M_singular() && !_M_is_end(); }
479 
480  // Is the iterator decrementable?
481  bool
482  _M_decrementable() const { return !_M_singular() && !_M_is_begin(); }
483 
484  // Can we advance the iterator @p __n steps (@p __n may be negative)
485  bool
486  _M_can_advance(const difference_type& __n) const;
487 
488  // Is the iterator range [*this, __rhs) valid?
489  bool
490  _M_valid_range(const _Safe_iterator& __rhs) const;
491 
492  // The sequence this iterator references.
493  typename
494  __gnu_cxx::__conditional_type<std::__are_same<_Const_iterator,
495  _Safe_iterator>::__value,
496  const _Sequence*,
497  _Sequence*>::__type
498  _M_get_sequence() const
499  { return static_cast<_Sequence*>(_M_sequence); }
500 
501  /// Is this iterator equal to the sequence's begin() iterator?
502  bool
503  _M_is_begin() const
504  { return base() == _M_get_sequence()->_M_base().begin(); }
505 
506  /// Is this iterator equal to the sequence's end() iterator?
507  bool
508  _M_is_end() const
509  { return base() == _M_get_sequence()->_M_base().end(); }
510 
511  /// Is this iterator equal to the sequence's before_begin() iterator if
512  /// any?
513  bool
515  { return _BeforeBeginHelper<_Sequence>::_S_Is(*this); }
516 
517  /// Is this iterator equal to the sequence's before_begin() iterator if
518  /// any or begin() otherwise?
519  bool
522  };
523 
524  template<typename _IteratorL, typename _IteratorR, typename _Sequence>
525  inline bool
526  operator==(const _Safe_iterator<_IteratorL, _Sequence>& __lhs,
528  _GLIBCXX_NOEXCEPT
529  {
530  _GLIBCXX_DEBUG_VERIFY(! __lhs._M_singular() && ! __rhs._M_singular(),
531  _M_message(__msg_iter_compare_bad)
532  ._M_iterator(__lhs, "lhs")
533  ._M_iterator(__rhs, "rhs"));
534  _GLIBCXX_DEBUG_VERIFY(__lhs._M_can_compare(__rhs),
535  _M_message(__msg_compare_different)
536  ._M_iterator(__lhs, "lhs")
537  ._M_iterator(__rhs, "rhs"));
538  return __lhs.base() == __rhs.base();
539  }
540 
541  template<typename _Iterator, typename _Sequence>
542  inline bool
543  operator==(const _Safe_iterator<_Iterator, _Sequence>& __lhs,
545  _GLIBCXX_NOEXCEPT
546  {
547  _GLIBCXX_DEBUG_VERIFY(! __lhs._M_singular() && ! __rhs._M_singular(),
548  _M_message(__msg_iter_compare_bad)
549  ._M_iterator(__lhs, "lhs")
550  ._M_iterator(__rhs, "rhs"));
551  _GLIBCXX_DEBUG_VERIFY(__lhs._M_can_compare(__rhs),
552  _M_message(__msg_compare_different)
553  ._M_iterator(__lhs, "lhs")
554  ._M_iterator(__rhs, "rhs"));
555  return __lhs.base() == __rhs.base();
556  }
557 
558  template<typename _IteratorL, typename _IteratorR, typename _Sequence>
559  inline bool
560  operator!=(const _Safe_iterator<_IteratorL, _Sequence>& __lhs,
562  _GLIBCXX_NOEXCEPT
563  {
564  _GLIBCXX_DEBUG_VERIFY(! __lhs._M_singular() && ! __rhs._M_singular(),
565  _M_message(__msg_iter_compare_bad)
566  ._M_iterator(__lhs, "lhs")
567  ._M_iterator(__rhs, "rhs"));
568  _GLIBCXX_DEBUG_VERIFY(__lhs._M_can_compare(__rhs),
569  _M_message(__msg_compare_different)
570  ._M_iterator(__lhs, "lhs")
571  ._M_iterator(__rhs, "rhs"));
572  return __lhs.base() != __rhs.base();
573  }
574 
575  template<typename _Iterator, typename _Sequence>
576  inline bool
577  operator!=(const _Safe_iterator<_Iterator, _Sequence>& __lhs,
579  _GLIBCXX_NOEXCEPT
580  {
581  _GLIBCXX_DEBUG_VERIFY(! __lhs._M_singular() && ! __rhs._M_singular(),
582  _M_message(__msg_iter_compare_bad)
583  ._M_iterator(__lhs, "lhs")
584  ._M_iterator(__rhs, "rhs"));
585  _GLIBCXX_DEBUG_VERIFY(__lhs._M_can_compare(__rhs),
586  _M_message(__msg_compare_different)
587  ._M_iterator(__lhs, "lhs")
588  ._M_iterator(__rhs, "rhs"));
589  return __lhs.base() != __rhs.base();
590  }
591 
592  template<typename _IteratorL, typename _IteratorR, typename _Sequence>
593  inline bool
594  operator<(const _Safe_iterator<_IteratorL, _Sequence>& __lhs,
596  _GLIBCXX_NOEXCEPT
597  {
598  _GLIBCXX_DEBUG_VERIFY(! __lhs._M_singular() && ! __rhs._M_singular(),
599  _M_message(__msg_iter_order_bad)
600  ._M_iterator(__lhs, "lhs")
601  ._M_iterator(__rhs, "rhs"));
602  _GLIBCXX_DEBUG_VERIFY(__lhs._M_can_compare(__rhs),
603  _M_message(__msg_order_different)
604  ._M_iterator(__lhs, "lhs")
605  ._M_iterator(__rhs, "rhs"));
606  return __lhs.base() < __rhs.base();
607  }
608 
609  template<typename _Iterator, typename _Sequence>
610  inline bool
611  operator<(const _Safe_iterator<_Iterator, _Sequence>& __lhs,
613  _GLIBCXX_NOEXCEPT
614  {
615  _GLIBCXX_DEBUG_VERIFY(! __lhs._M_singular() && ! __rhs._M_singular(),
616  _M_message(__msg_iter_order_bad)
617  ._M_iterator(__lhs, "lhs")
618  ._M_iterator(__rhs, "rhs"));
619  _GLIBCXX_DEBUG_VERIFY(__lhs._M_can_compare(__rhs),
620  _M_message(__msg_order_different)
621  ._M_iterator(__lhs, "lhs")
622  ._M_iterator(__rhs, "rhs"));
623  return __lhs.base() < __rhs.base();
624  }
625 
626  template<typename _IteratorL, typename _IteratorR, typename _Sequence>
627  inline bool
628  operator<=(const _Safe_iterator<_IteratorL, _Sequence>& __lhs,
630  _GLIBCXX_NOEXCEPT
631  {
632  _GLIBCXX_DEBUG_VERIFY(! __lhs._M_singular() && ! __rhs._M_singular(),
633  _M_message(__msg_iter_order_bad)
634  ._M_iterator(__lhs, "lhs")
635  ._M_iterator(__rhs, "rhs"));
636  _GLIBCXX_DEBUG_VERIFY(__lhs._M_can_compare(__rhs),
637  _M_message(__msg_order_different)
638  ._M_iterator(__lhs, "lhs")
639  ._M_iterator(__rhs, "rhs"));
640  return __lhs.base() <= __rhs.base();
641  }
642 
643  template<typename _Iterator, typename _Sequence>
644  inline bool
645  operator<=(const _Safe_iterator<_Iterator, _Sequence>& __lhs,
647  _GLIBCXX_NOEXCEPT
648  {
649  _GLIBCXX_DEBUG_VERIFY(! __lhs._M_singular() && ! __rhs._M_singular(),
650  _M_message(__msg_iter_order_bad)
651  ._M_iterator(__lhs, "lhs")
652  ._M_iterator(__rhs, "rhs"));
653  _GLIBCXX_DEBUG_VERIFY(__lhs._M_can_compare(__rhs),
654  _M_message(__msg_order_different)
655  ._M_iterator(__lhs, "lhs")
656  ._M_iterator(__rhs, "rhs"));
657  return __lhs.base() <= __rhs.base();
658  }
659 
660  template<typename _IteratorL, typename _IteratorR, typename _Sequence>
661  inline bool
662  operator>(const _Safe_iterator<_IteratorL, _Sequence>& __lhs,
664  _GLIBCXX_NOEXCEPT
665  {
666  _GLIBCXX_DEBUG_VERIFY(! __lhs._M_singular() && ! __rhs._M_singular(),
667  _M_message(__msg_iter_order_bad)
668  ._M_iterator(__lhs, "lhs")
669  ._M_iterator(__rhs, "rhs"));
670  _GLIBCXX_DEBUG_VERIFY(__lhs._M_can_compare(__rhs),
671  _M_message(__msg_order_different)
672  ._M_iterator(__lhs, "lhs")
673  ._M_iterator(__rhs, "rhs"));
674  return __lhs.base() > __rhs.base();
675  }
676 
677  template<typename _Iterator, typename _Sequence>
678  inline bool
679  operator>(const _Safe_iterator<_Iterator, _Sequence>& __lhs,
681  _GLIBCXX_NOEXCEPT
682  {
683  _GLIBCXX_DEBUG_VERIFY(! __lhs._M_singular() && ! __rhs._M_singular(),
684  _M_message(__msg_iter_order_bad)
685  ._M_iterator(__lhs, "lhs")
686  ._M_iterator(__rhs, "rhs"));
687  _GLIBCXX_DEBUG_VERIFY(__lhs._M_can_compare(__rhs),
688  _M_message(__msg_order_different)
689  ._M_iterator(__lhs, "lhs")
690  ._M_iterator(__rhs, "rhs"));
691  return __lhs.base() > __rhs.base();
692  }
693 
694  template<typename _IteratorL, typename _IteratorR, typename _Sequence>
695  inline bool
696  operator>=(const _Safe_iterator<_IteratorL, _Sequence>& __lhs,
698  _GLIBCXX_NOEXCEPT
699  {
700  _GLIBCXX_DEBUG_VERIFY(! __lhs._M_singular() && ! __rhs._M_singular(),
701  _M_message(__msg_iter_order_bad)
702  ._M_iterator(__lhs, "lhs")
703  ._M_iterator(__rhs, "rhs"));
704  _GLIBCXX_DEBUG_VERIFY(__lhs._M_can_compare(__rhs),
705  _M_message(__msg_order_different)
706  ._M_iterator(__lhs, "lhs")
707  ._M_iterator(__rhs, "rhs"));
708  return __lhs.base() >= __rhs.base();
709  }
710 
711  template<typename _Iterator, typename _Sequence>
712  inline bool
713  operator>=(const _Safe_iterator<_Iterator, _Sequence>& __lhs,
715  _GLIBCXX_NOEXCEPT
716  {
717  _GLIBCXX_DEBUG_VERIFY(! __lhs._M_singular() && ! __rhs._M_singular(),
718  _M_message(__msg_iter_order_bad)
719  ._M_iterator(__lhs, "lhs")
720  ._M_iterator(__rhs, "rhs"));
721  _GLIBCXX_DEBUG_VERIFY(__lhs._M_can_compare(__rhs),
722  _M_message(__msg_order_different)
723  ._M_iterator(__lhs, "lhs")
724  ._M_iterator(__rhs, "rhs"));
725  return __lhs.base() >= __rhs.base();
726  }
727 
728  // _GLIBCXX_RESOLVE_LIB_DEFECTS
729  // According to the resolution of DR179 not only the various comparison
730  // operators but also operator- must accept mixed iterator/const_iterator
731  // parameters.
732  template<typename _IteratorL, typename _IteratorR, typename _Sequence>
733  inline typename _Safe_iterator<_IteratorL, _Sequence>::difference_type
734  operator-(const _Safe_iterator<_IteratorL, _Sequence>& __lhs,
736  _GLIBCXX_NOEXCEPT
737  {
738  _GLIBCXX_DEBUG_VERIFY(! __lhs._M_singular() && ! __rhs._M_singular(),
739  _M_message(__msg_distance_bad)
740  ._M_iterator(__lhs, "lhs")
741  ._M_iterator(__rhs, "rhs"));
742  _GLIBCXX_DEBUG_VERIFY(__lhs._M_can_compare(__rhs),
743  _M_message(__msg_distance_different)
744  ._M_iterator(__lhs, "lhs")
745  ._M_iterator(__rhs, "rhs"));
746  return __lhs.base() - __rhs.base();
747  }
748 
749  template<typename _Iterator, typename _Sequence>
750  inline typename _Safe_iterator<_Iterator, _Sequence>::difference_type
751  operator-(const _Safe_iterator<_Iterator, _Sequence>& __lhs,
753  _GLIBCXX_NOEXCEPT
754  {
755  _GLIBCXX_DEBUG_VERIFY(! __lhs._M_singular() && ! __rhs._M_singular(),
756  _M_message(__msg_distance_bad)
757  ._M_iterator(__lhs, "lhs")
758  ._M_iterator(__rhs, "rhs"));
759  _GLIBCXX_DEBUG_VERIFY(__lhs._M_can_compare(__rhs),
760  _M_message(__msg_distance_different)
761  ._M_iterator(__lhs, "lhs")
762  ._M_iterator(__rhs, "rhs"));
763  return __lhs.base() - __rhs.base();
764  }
765 
766  template<typename _Iterator, typename _Sequence>
768  operator+(typename _Safe_iterator<_Iterator,_Sequence>::difference_type __n,
769  const _Safe_iterator<_Iterator, _Sequence>& __i) _GLIBCXX_NOEXCEPT
770  { return __i + __n; }
771 } // namespace __gnu_debug
772 
773 #include <debug/safe_iterator.tcc>
774 
775 #endif
Scoped lock idiom.
Definition: concurrence.h:231
_Safe_iterator(const _Safe_iterator &__x) noexcept
Copy construction.
_Safe_iterator(_Safe_iterator &&__x) noexcept
Move construction.
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:276
void _M_attach_single(_Safe_sequence_base *__seq)
_Tp * __addressof(_Tp &__r) noexcept
Same as C++11 std::addressof.
Definition: move.h:47
_Safe_iterator & operator=(const _Safe_iterator &__x) noexcept
Copy assignment.
bool _M_dereferenceable() const
Is the iterator dereferenceable?
bool _M_can_compare(const _Safe_iterator_base &__x) const
_Safe_iterator operator++(int) noexcept
Iterator postincrement.
_Iterator & base() noexcept
Return the underlying iterator.
void _M_attach(_Safe_sequence_base *__seq)
reference operator*() const noexcept
Iterator dereference.
bool _M_is_begin() const
Is this iterator equal to the sequence&#39;s begin() iterator?
_Safe_iterator operator--(int) noexcept
Iterator postdecrement.
Basic functionality for a safe iterator.
Definition: safe_base.h:50
bool _M_incrementable() const
Is the iterator incrementable?
Base class that supports tracking of iterators that reference a sequence.
Definition: safe_base.h:179
GNU debug classes for public use.
Random-access iterators support a superset of bidirectional iterator operations.
std::pair< typename std::iterator_traits< _Iterator >::difference_type, _Distance_precision > __get_distance(const _Iterator &__lhs, const _Iterator &__rhs, std::random_access_iterator_tag)
Definition: safe_iterator.h:81
_Safe_iterator & operator=(_Safe_iterator &&__x) noexcept
Move assignment.
_Safe_iterator(const _Iterator &__i, const _Safe_sequence_base *__seq) noexcept
Safe iterator construction from an unsafe iterator and its sequence.
bool _M_is_before_begin() const
Is this iterator equal to the sequence&#39;s before_begin() iterator if any?
bool _M_before_dereferenceable() const
Is the iterator before a dereferenceable one?
_Siter_base< _Iterator >::iterator_type __base(_Iterator __it)
Definition: functions.h:558
Safe iterator wrapper.
Definition: formatter.h:46
_Safe_iterator(const _Safe_iterator< _MutableIterator, typename __gnu_cxx::__enable_if<(std::__are_same< _MutableIterator, typename _Sequence::iterator::iterator_type >::__value), _Sequence >::__type > &__x) noexcept
Converting constructor from a mutable iterator to a constant iterator.
_Safe_iterator & operator--() noexcept
Iterator predecrement.
Struct holding two objects of arbitrary type.
Definition: stl_pair.h:96
bool _M_is_end() const
Is this iterator equal to the sequence&#39;s end() iterator?
bool _M_is_beginnest() const
Is this iterator equal to the sequence&#39;s before_begin() iterator if any or begin() otherwise...
Forward iterators support a superset of input iterator operations.
_Safe_iterator & operator++() noexcept
Iterator preincrement.
pointer operator->() const noexcept
Iterator dereference.
void _M_detach(_Safe_iterator_base *__it)