libstdc++
safe_iterator.h
Go to the documentation of this file.
1 // Safe iterator implementation -*- C++ -*-
2 
3 // Copyright (C) 2003-2014 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  template<typename _Iterator, typename _Sequence>
114  class _Safe_iterator : public _Safe_iterator_base
115  {
116  typedef _Safe_iterator _Self;
117  typedef typename _Sequence::const_iterator _Const_iterator;
118 
119  /// The underlying iterator
120  _Iterator _M_current;
121 
122  /// Determine if this is a constant iterator.
123  bool
124  _M_constant() const
125  { return std::__are_same<_Const_iterator, _Safe_iterator>::__value; }
126 
127  typedef std::iterator_traits<_Iterator> _Traits;
128 
129  public:
130  typedef _Iterator iterator_type;
131  typedef typename _Traits::iterator_category iterator_category;
132  typedef typename _Traits::value_type value_type;
133  typedef typename _Traits::difference_type difference_type;
134  typedef typename _Traits::reference reference;
135  typedef typename _Traits::pointer pointer;
136 
137  /// @post the iterator is singular and unattached
138  _Safe_iterator() _GLIBCXX_NOEXCEPT : _M_current() { }
139 
140  /**
141  * @brief Safe iterator construction from an unsafe iterator and
142  * its sequence.
143  *
144  * @pre @p seq is not NULL
145  * @post this is not singular
146  */
147  _Safe_iterator(const _Iterator& __i, const _Sequence* __seq)
148  _GLIBCXX_NOEXCEPT
149  : _Safe_iterator_base(__seq, _M_constant()), _M_current(__i)
150  {
151  _GLIBCXX_DEBUG_VERIFY(! this->_M_singular(),
152  _M_message(__msg_init_singular)
153  ._M_iterator(*this, "this"));
154  }
155 
156  /**
157  * @brief Copy construction.
158  */
159  _Safe_iterator(const _Safe_iterator& __x) _GLIBCXX_NOEXCEPT
160  : _Safe_iterator_base(__x, _M_constant()), _M_current(__x._M_current)
161  {
162  // _GLIBCXX_RESOLVE_LIB_DEFECTS
163  // DR 408. Is vector<reverse_iterator<char*> > forbidden?
164  _GLIBCXX_DEBUG_VERIFY(!__x._M_singular()
165  || __x._M_current == _Iterator(),
166  _M_message(__msg_init_copy_singular)
167  ._M_iterator(*this, "this")
168  ._M_iterator(__x, "other"));
169  }
170 
171 #if __cplusplus >= 201103L
172  /**
173  * @brief Move construction.
174  * @post __x is singular and unattached
175  */
176  _Safe_iterator(_Safe_iterator&& __x) noexcept : _M_current()
177  {
178  _GLIBCXX_DEBUG_VERIFY(!__x._M_singular()
179  || __x._M_current == _Iterator(),
180  _M_message(__msg_init_copy_singular)
181  ._M_iterator(*this, "this")
182  ._M_iterator(__x, "other"));
183  std::swap(_M_current, __x._M_current);
184  this->_M_attach(__x._M_sequence);
185  __x._M_detach();
186  }
187 #endif
188 
189  /**
190  * @brief Converting constructor from a mutable iterator to a
191  * constant iterator.
192  */
193  template<typename _MutableIterator>
195  const _Safe_iterator<_MutableIterator,
196  typename __gnu_cxx::__enable_if<(std::__are_same<_MutableIterator,
197  typename _Sequence::iterator::iterator_type>::__value),
198  _Sequence>::__type>& __x) _GLIBCXX_NOEXCEPT
199  : _Safe_iterator_base(__x, _M_constant()), _M_current(__x.base())
200  {
201  // _GLIBCXX_RESOLVE_LIB_DEFECTS
202  // DR 408. Is vector<reverse_iterator<char*> > forbidden?
203  _GLIBCXX_DEBUG_VERIFY(!__x._M_singular()
204  || __x.base() == _Iterator(),
205  _M_message(__msg_init_const_singular)
206  ._M_iterator(*this, "this")
207  ._M_iterator(__x, "other"));
208  }
209 
210  /**
211  * @brief Copy assignment.
212  */
214  operator=(const _Safe_iterator& __x) _GLIBCXX_NOEXCEPT
215  {
216  // _GLIBCXX_RESOLVE_LIB_DEFECTS
217  // DR 408. Is vector<reverse_iterator<char*> > forbidden?
218  _GLIBCXX_DEBUG_VERIFY(!__x._M_singular()
219  || __x._M_current == _Iterator(),
220  _M_message(__msg_copy_singular)
221  ._M_iterator(*this, "this")
222  ._M_iterator(__x, "other"));
223  _M_current = __x._M_current;
224  this->_M_attach(__x._M_sequence);
225  return *this;
226  }
227 
228 #if __cplusplus >= 201103L
229  /**
230  * @brief Move assignment.
231  * @post __x is singular and unattached
232  */
234  operator=(_Safe_iterator&& __x) noexcept
235  {
236  _GLIBCXX_DEBUG_VERIFY(this != &__x,
237  _M_message(__msg_self_move_assign)
238  ._M_iterator(*this, "this"));
239  _GLIBCXX_DEBUG_VERIFY(!__x._M_singular()
240  || __x._M_current == _Iterator(),
241  _M_message(__msg_copy_singular)
242  ._M_iterator(*this, "this")
243  ._M_iterator(__x, "other"));
244  _M_current = __x._M_current;
245  _M_attach(__x._M_sequence);
246  __x._M_detach();
247  __x._M_current = _Iterator();
248  return *this;
249  }
250 #endif
251 
252  /**
253  * @brief Iterator dereference.
254  * @pre iterator is dereferenceable
255  */
256  reference
257  operator*() const _GLIBCXX_NOEXCEPT
258  {
259  _GLIBCXX_DEBUG_VERIFY(this->_M_dereferenceable(),
260  _M_message(__msg_bad_deref)
261  ._M_iterator(*this, "this"));
262  return *_M_current;
263  }
264 
265  /**
266  * @brief Iterator dereference.
267  * @pre iterator is dereferenceable
268  * @todo Make this correct w.r.t. iterators that return proxies
269  */
270  pointer
271  operator->() const _GLIBCXX_NOEXCEPT
272  {
273  _GLIBCXX_DEBUG_VERIFY(this->_M_dereferenceable(),
274  _M_message(__msg_bad_deref)
275  ._M_iterator(*this, "this"));
276  return std::__addressof(*_M_current);
277  }
278 
279  // ------ Input iterator requirements ------
280  /**
281  * @brief Iterator preincrement
282  * @pre iterator is incrementable
283  */
285  operator++() _GLIBCXX_NOEXCEPT
286  {
287  _GLIBCXX_DEBUG_VERIFY(this->_M_incrementable(),
288  _M_message(__msg_bad_inc)
289  ._M_iterator(*this, "this"));
290  ++_M_current;
291  return *this;
292  }
293 
294  /**
295  * @brief Iterator postincrement
296  * @pre iterator is incrementable
297  */
299  operator++(int) _GLIBCXX_NOEXCEPT
300  {
301  _GLIBCXX_DEBUG_VERIFY(this->_M_incrementable(),
302  _M_message(__msg_bad_inc)
303  ._M_iterator(*this, "this"));
304  _Safe_iterator __tmp(*this);
305  ++_M_current;
306  return __tmp;
307  }
308 
309  // ------ Bidirectional iterator requirements ------
310  /**
311  * @brief Iterator predecrement
312  * @pre iterator is decrementable
313  */
315  operator--() _GLIBCXX_NOEXCEPT
316  {
317  _GLIBCXX_DEBUG_VERIFY(this->_M_decrementable(),
318  _M_message(__msg_bad_dec)
319  ._M_iterator(*this, "this"));
320  --_M_current;
321  return *this;
322  }
323 
324  /**
325  * @brief Iterator postdecrement
326  * @pre iterator is decrementable
327  */
329  operator--(int) _GLIBCXX_NOEXCEPT
330  {
331  _GLIBCXX_DEBUG_VERIFY(this->_M_decrementable(),
332  _M_message(__msg_bad_dec)
333  ._M_iterator(*this, "this"));
334  _Safe_iterator __tmp(*this);
335  --_M_current;
336  return __tmp;
337  }
338 
339  // ------ Random access iterator requirements ------
340  reference
341  operator[](const difference_type& __n) const _GLIBCXX_NOEXCEPT
342  {
343  _GLIBCXX_DEBUG_VERIFY(this->_M_can_advance(__n)
344  && this->_M_can_advance(__n+1),
345  _M_message(__msg_iter_subscript_oob)
346  ._M_iterator(*this)._M_integer(__n));
347 
348  return _M_current[__n];
349  }
350 
352  operator+=(const difference_type& __n) _GLIBCXX_NOEXCEPT
353  {
354  _GLIBCXX_DEBUG_VERIFY(this->_M_can_advance(__n),
355  _M_message(__msg_advance_oob)
356  ._M_iterator(*this)._M_integer(__n));
357  _M_current += __n;
358  return *this;
359  }
360 
362  operator+(const difference_type& __n) const _GLIBCXX_NOEXCEPT
363  {
364  _Safe_iterator __tmp(*this);
365  __tmp += __n;
366  return __tmp;
367  }
368 
370  operator-=(const difference_type& __n) _GLIBCXX_NOEXCEPT
371  {
372  _GLIBCXX_DEBUG_VERIFY(this->_M_can_advance(-__n),
373  _M_message(__msg_retreat_oob)
374  ._M_iterator(*this)._M_integer(__n));
375  _M_current += -__n;
376  return *this;
377  }
378 
380  operator-(const difference_type& __n) const _GLIBCXX_NOEXCEPT
381  {
382  _Safe_iterator __tmp(*this);
383  __tmp -= __n;
384  return __tmp;
385  }
386 
387  // ------ Utilities ------
388  /**
389  * @brief Return the underlying iterator
390  */
391  _Iterator
392  base() const _GLIBCXX_NOEXCEPT { return _M_current; }
393 
394  /**
395  * @brief Conversion to underlying non-debug iterator to allow
396  * better interaction with non-debug containers.
397  */
398  operator _Iterator() const _GLIBCXX_NOEXCEPT { return _M_current; }
399 
400  /** Attach iterator to the given sequence. */
401  void
403  {
404  _Safe_iterator_base::_M_attach(__seq, _M_constant());
405  }
406 
407  /** Likewise, but not thread-safe. */
408  void
410  {
411  _Safe_iterator_base::_M_attach_single(__seq, _M_constant());
412  }
413 
414  /// Is the iterator dereferenceable?
415  bool
417  { return !this->_M_singular() && !_M_is_end() && !_M_is_before_begin(); }
418 
419  /// Is the iterator before a dereferenceable one?
420  bool
422  {
423  if (this->_M_incrementable())
424  {
425  _Iterator __base = base();
426  return ++__base != _M_get_sequence()->_M_base().end();
427  }
428  return false;
429  }
430 
431  /// Is the iterator incrementable?
432  bool
434  { return !this->_M_singular() && !_M_is_end(); }
435 
436  // Is the iterator decrementable?
437  bool
438  _M_decrementable() const { return !_M_singular() && !_M_is_begin(); }
439 
440  // Can we advance the iterator @p __n steps (@p __n may be negative)
441  bool
442  _M_can_advance(const difference_type& __n) const;
443 
444  // Is the iterator range [*this, __rhs) valid?
445  bool
446  _M_valid_range(const _Safe_iterator& __rhs) const;
447 
448  // The sequence this iterator references.
449  typename
450  __gnu_cxx::__conditional_type<std::__are_same<_Const_iterator,
451  _Safe_iterator>::__value,
452  const _Sequence*,
453  _Sequence*>::__type
454  _M_get_sequence() const
455  { return static_cast<_Sequence*>(_M_sequence); }
456 
457  /// Is this iterator equal to the sequence's begin() iterator?
458  bool
459  _M_is_begin() const
460  { return base() == _M_get_sequence()->_M_base().begin(); }
461 
462  /// Is this iterator equal to the sequence's end() iterator?
463  bool
464  _M_is_end() const
465  { return base() == _M_get_sequence()->_M_base().end(); }
466 
467  /// Is this iterator equal to the sequence's before_begin() iterator if
468  /// any?
469  bool
471  { return _BeforeBeginHelper<_Sequence>::_S_Is(*this); }
472 
473  /// Is this iterator equal to the sequence's before_begin() iterator if
474  /// any or begin() otherwise?
475  bool
478  };
479 
480  template<typename _IteratorL, typename _IteratorR, typename _Sequence>
481  inline bool
482  operator==(const _Safe_iterator<_IteratorL, _Sequence>& __lhs,
483  const _Safe_iterator<_IteratorR, _Sequence>& __rhs)
484  _GLIBCXX_NOEXCEPT
485  {
486  _GLIBCXX_DEBUG_VERIFY(! __lhs._M_singular() && ! __rhs._M_singular(),
487  _M_message(__msg_iter_compare_bad)
488  ._M_iterator(__lhs, "lhs")
489  ._M_iterator(__rhs, "rhs"));
490  _GLIBCXX_DEBUG_VERIFY(__lhs._M_can_compare(__rhs),
491  _M_message(__msg_compare_different)
492  ._M_iterator(__lhs, "lhs")
493  ._M_iterator(__rhs, "rhs"));
494  return __lhs.base() == __rhs.base();
495  }
496 
497  template<typename _Iterator, typename _Sequence>
498  inline bool
499  operator==(const _Safe_iterator<_Iterator, _Sequence>& __lhs,
500  const _Safe_iterator<_Iterator, _Sequence>& __rhs)
501  _GLIBCXX_NOEXCEPT
502  {
503  _GLIBCXX_DEBUG_VERIFY(! __lhs._M_singular() && ! __rhs._M_singular(),
504  _M_message(__msg_iter_compare_bad)
505  ._M_iterator(__lhs, "lhs")
506  ._M_iterator(__rhs, "rhs"));
507  _GLIBCXX_DEBUG_VERIFY(__lhs._M_can_compare(__rhs),
508  _M_message(__msg_compare_different)
509  ._M_iterator(__lhs, "lhs")
510  ._M_iterator(__rhs, "rhs"));
511  return __lhs.base() == __rhs.base();
512  }
513 
514  template<typename _IteratorL, typename _IteratorR, typename _Sequence>
515  inline bool
516  operator!=(const _Safe_iterator<_IteratorL, _Sequence>& __lhs,
517  const _Safe_iterator<_IteratorR, _Sequence>& __rhs)
518  _GLIBCXX_NOEXCEPT
519  {
520  _GLIBCXX_DEBUG_VERIFY(! __lhs._M_singular() && ! __rhs._M_singular(),
521  _M_message(__msg_iter_compare_bad)
522  ._M_iterator(__lhs, "lhs")
523  ._M_iterator(__rhs, "rhs"));
524  _GLIBCXX_DEBUG_VERIFY(__lhs._M_can_compare(__rhs),
525  _M_message(__msg_compare_different)
526  ._M_iterator(__lhs, "lhs")
527  ._M_iterator(__rhs, "rhs"));
528  return __lhs.base() != __rhs.base();
529  }
530 
531  template<typename _Iterator, typename _Sequence>
532  inline bool
533  operator!=(const _Safe_iterator<_Iterator, _Sequence>& __lhs,
534  const _Safe_iterator<_Iterator, _Sequence>& __rhs)
535  _GLIBCXX_NOEXCEPT
536  {
537  _GLIBCXX_DEBUG_VERIFY(! __lhs._M_singular() && ! __rhs._M_singular(),
538  _M_message(__msg_iter_compare_bad)
539  ._M_iterator(__lhs, "lhs")
540  ._M_iterator(__rhs, "rhs"));
541  _GLIBCXX_DEBUG_VERIFY(__lhs._M_can_compare(__rhs),
542  _M_message(__msg_compare_different)
543  ._M_iterator(__lhs, "lhs")
544  ._M_iterator(__rhs, "rhs"));
545  return __lhs.base() != __rhs.base();
546  }
547 
548  template<typename _IteratorL, typename _IteratorR, typename _Sequence>
549  inline bool
550  operator<(const _Safe_iterator<_IteratorL, _Sequence>& __lhs,
551  const _Safe_iterator<_IteratorR, _Sequence>& __rhs)
552  _GLIBCXX_NOEXCEPT
553  {
554  _GLIBCXX_DEBUG_VERIFY(! __lhs._M_singular() && ! __rhs._M_singular(),
555  _M_message(__msg_iter_order_bad)
556  ._M_iterator(__lhs, "lhs")
557  ._M_iterator(__rhs, "rhs"));
558  _GLIBCXX_DEBUG_VERIFY(__lhs._M_can_compare(__rhs),
559  _M_message(__msg_order_different)
560  ._M_iterator(__lhs, "lhs")
561  ._M_iterator(__rhs, "rhs"));
562  return __lhs.base() < __rhs.base();
563  }
564 
565  template<typename _Iterator, typename _Sequence>
566  inline bool
567  operator<(const _Safe_iterator<_Iterator, _Sequence>& __lhs,
568  const _Safe_iterator<_Iterator, _Sequence>& __rhs)
569  _GLIBCXX_NOEXCEPT
570  {
571  _GLIBCXX_DEBUG_VERIFY(! __lhs._M_singular() && ! __rhs._M_singular(),
572  _M_message(__msg_iter_order_bad)
573  ._M_iterator(__lhs, "lhs")
574  ._M_iterator(__rhs, "rhs"));
575  _GLIBCXX_DEBUG_VERIFY(__lhs._M_can_compare(__rhs),
576  _M_message(__msg_order_different)
577  ._M_iterator(__lhs, "lhs")
578  ._M_iterator(__rhs, "rhs"));
579  return __lhs.base() < __rhs.base();
580  }
581 
582  template<typename _IteratorL, typename _IteratorR, typename _Sequence>
583  inline bool
584  operator<=(const _Safe_iterator<_IteratorL, _Sequence>& __lhs,
585  const _Safe_iterator<_IteratorR, _Sequence>& __rhs)
586  _GLIBCXX_NOEXCEPT
587  {
588  _GLIBCXX_DEBUG_VERIFY(! __lhs._M_singular() && ! __rhs._M_singular(),
589  _M_message(__msg_iter_order_bad)
590  ._M_iterator(__lhs, "lhs")
591  ._M_iterator(__rhs, "rhs"));
592  _GLIBCXX_DEBUG_VERIFY(__lhs._M_can_compare(__rhs),
593  _M_message(__msg_order_different)
594  ._M_iterator(__lhs, "lhs")
595  ._M_iterator(__rhs, "rhs"));
596  return __lhs.base() <= __rhs.base();
597  }
598 
599  template<typename _Iterator, typename _Sequence>
600  inline bool
601  operator<=(const _Safe_iterator<_Iterator, _Sequence>& __lhs,
602  const _Safe_iterator<_Iterator, _Sequence>& __rhs)
603  _GLIBCXX_NOEXCEPT
604  {
605  _GLIBCXX_DEBUG_VERIFY(! __lhs._M_singular() && ! __rhs._M_singular(),
606  _M_message(__msg_iter_order_bad)
607  ._M_iterator(__lhs, "lhs")
608  ._M_iterator(__rhs, "rhs"));
609  _GLIBCXX_DEBUG_VERIFY(__lhs._M_can_compare(__rhs),
610  _M_message(__msg_order_different)
611  ._M_iterator(__lhs, "lhs")
612  ._M_iterator(__rhs, "rhs"));
613  return __lhs.base() <= __rhs.base();
614  }
615 
616  template<typename _IteratorL, typename _IteratorR, typename _Sequence>
617  inline bool
618  operator>(const _Safe_iterator<_IteratorL, _Sequence>& __lhs,
619  const _Safe_iterator<_IteratorR, _Sequence>& __rhs)
620  _GLIBCXX_NOEXCEPT
621  {
622  _GLIBCXX_DEBUG_VERIFY(! __lhs._M_singular() && ! __rhs._M_singular(),
623  _M_message(__msg_iter_order_bad)
624  ._M_iterator(__lhs, "lhs")
625  ._M_iterator(__rhs, "rhs"));
626  _GLIBCXX_DEBUG_VERIFY(__lhs._M_can_compare(__rhs),
627  _M_message(__msg_order_different)
628  ._M_iterator(__lhs, "lhs")
629  ._M_iterator(__rhs, "rhs"));
630  return __lhs.base() > __rhs.base();
631  }
632 
633  template<typename _Iterator, typename _Sequence>
634  inline bool
635  operator>(const _Safe_iterator<_Iterator, _Sequence>& __lhs,
636  const _Safe_iterator<_Iterator, _Sequence>& __rhs)
637  _GLIBCXX_NOEXCEPT
638  {
639  _GLIBCXX_DEBUG_VERIFY(! __lhs._M_singular() && ! __rhs._M_singular(),
640  _M_message(__msg_iter_order_bad)
641  ._M_iterator(__lhs, "lhs")
642  ._M_iterator(__rhs, "rhs"));
643  _GLIBCXX_DEBUG_VERIFY(__lhs._M_can_compare(__rhs),
644  _M_message(__msg_order_different)
645  ._M_iterator(__lhs, "lhs")
646  ._M_iterator(__rhs, "rhs"));
647  return __lhs.base() > __rhs.base();
648  }
649 
650  template<typename _IteratorL, typename _IteratorR, typename _Sequence>
651  inline bool
652  operator>=(const _Safe_iterator<_IteratorL, _Sequence>& __lhs,
653  const _Safe_iterator<_IteratorR, _Sequence>& __rhs)
654  _GLIBCXX_NOEXCEPT
655  {
656  _GLIBCXX_DEBUG_VERIFY(! __lhs._M_singular() && ! __rhs._M_singular(),
657  _M_message(__msg_iter_order_bad)
658  ._M_iterator(__lhs, "lhs")
659  ._M_iterator(__rhs, "rhs"));
660  _GLIBCXX_DEBUG_VERIFY(__lhs._M_can_compare(__rhs),
661  _M_message(__msg_order_different)
662  ._M_iterator(__lhs, "lhs")
663  ._M_iterator(__rhs, "rhs"));
664  return __lhs.base() >= __rhs.base();
665  }
666 
667  template<typename _Iterator, typename _Sequence>
668  inline bool
669  operator>=(const _Safe_iterator<_Iterator, _Sequence>& __lhs,
670  const _Safe_iterator<_Iterator, _Sequence>& __rhs)
671  _GLIBCXX_NOEXCEPT
672  {
673  _GLIBCXX_DEBUG_VERIFY(! __lhs._M_singular() && ! __rhs._M_singular(),
674  _M_message(__msg_iter_order_bad)
675  ._M_iterator(__lhs, "lhs")
676  ._M_iterator(__rhs, "rhs"));
677  _GLIBCXX_DEBUG_VERIFY(__lhs._M_can_compare(__rhs),
678  _M_message(__msg_order_different)
679  ._M_iterator(__lhs, "lhs")
680  ._M_iterator(__rhs, "rhs"));
681  return __lhs.base() >= __rhs.base();
682  }
683 
684  // _GLIBCXX_RESOLVE_LIB_DEFECTS
685  // According to the resolution of DR179 not only the various comparison
686  // operators but also operator- must accept mixed iterator/const_iterator
687  // parameters.
688  template<typename _IteratorL, typename _IteratorR, typename _Sequence>
689  inline typename _Safe_iterator<_IteratorL, _Sequence>::difference_type
690  operator-(const _Safe_iterator<_IteratorL, _Sequence>& __lhs,
691  const _Safe_iterator<_IteratorR, _Sequence>& __rhs)
692  _GLIBCXX_NOEXCEPT
693  {
694  _GLIBCXX_DEBUG_VERIFY(! __lhs._M_singular() && ! __rhs._M_singular(),
695  _M_message(__msg_distance_bad)
696  ._M_iterator(__lhs, "lhs")
697  ._M_iterator(__rhs, "rhs"));
698  _GLIBCXX_DEBUG_VERIFY(__lhs._M_can_compare(__rhs),
699  _M_message(__msg_distance_different)
700  ._M_iterator(__lhs, "lhs")
701  ._M_iterator(__rhs, "rhs"));
702  return __lhs.base() - __rhs.base();
703  }
704 
705  template<typename _Iterator, typename _Sequence>
706  inline typename _Safe_iterator<_Iterator, _Sequence>::difference_type
707  operator-(const _Safe_iterator<_Iterator, _Sequence>& __lhs,
708  const _Safe_iterator<_Iterator, _Sequence>& __rhs)
709  _GLIBCXX_NOEXCEPT
710  {
711  _GLIBCXX_DEBUG_VERIFY(! __lhs._M_singular() && ! __rhs._M_singular(),
712  _M_message(__msg_distance_bad)
713  ._M_iterator(__lhs, "lhs")
714  ._M_iterator(__rhs, "rhs"));
715  _GLIBCXX_DEBUG_VERIFY(__lhs._M_can_compare(__rhs),
716  _M_message(__msg_distance_different)
717  ._M_iterator(__lhs, "lhs")
718  ._M_iterator(__rhs, "rhs"));
719  return __lhs.base() - __rhs.base();
720  }
721 
722  template<typename _Iterator, typename _Sequence>
723  inline _Safe_iterator<_Iterator, _Sequence>
724  operator+(typename _Safe_iterator<_Iterator,_Sequence>::difference_type __n,
725  const _Safe_iterator<_Iterator, _Sequence>& __i) _GLIBCXX_NOEXCEPT
726  { return __i + __n; }
727 } // namespace __gnu_debug
728 
729 #include <debug/safe_iterator.tcc>
730 
731 #endif
_Safe_iterator & operator++() noexcept
Iterator preincrement.
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
_Safe_iterator & operator=(_Safe_iterator &&__x) noexcept
Move assignment.
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
bool _M_is_end() const
Is this iterator equal to the sequence's end() iterator?
_Safe_iterator operator--(int) noexcept
Iterator postdecrement.
void _M_attach(_Safe_sequence_base *__seq, bool __constant)
Forward iterators support a superset of input iterator operations.
void _M_attach(_Safe_sequence_base *__seq)
Basic functionality for a safe iterator.
Definition: safe_base.h:50
pointer operator->() const noexcept
Iterator dereference.
bool _M_incrementable() const
Is the iterator incrementable?
reference operator*() const noexcept
Iterator dereference.
bool _M_is_beginnest() const
Is this iterator equal to the sequence's before_begin() iterator if any or begin() otherwise...
_Safe_iterator(const _Safe_iterator &__x) noexcept
Copy construction.
_Siter_base< _Iterator >::iterator_type __base(_Iterator __it)
Definition: functions.h:558
bool _M_is_begin() const
Is this iterator equal to the sequence's begin() iterator?
_Safe_sequence_base * _M_sequence
Definition: safe_base.h:55
_Safe_iterator(_Safe_iterator &&__x) noexcept
Move construction.
_Safe_iterator & operator=(const _Safe_iterator &__x) noexcept
Copy assignment.
void _M_attach_single(_Safe_sequence_base *__seq, bool __constant)
Safe iterator wrapper.
Definition: formatter.h:46
bool _M_before_dereferenceable() const
Is the iterator before a dereferenceable one?
bool operator>=(const basic_string< _CharT, _Traits, _Alloc > &__lhs, const basic_string< _CharT, _Traits, _Alloc > &__rhs)
Test if string doesn't precede string.
GNU debug classes for public use.
_Safe_iterator(const _Iterator &__i, const _Sequence *__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's before_begin() iterator if any?
_Tp * __addressof(_Tp &__r) noexcept
Same as C++11 std::addressof.
Definition: move.h:47
basic_string< _CharT, _Traits, _Alloc > operator+(const basic_string< _CharT, _Traits, _Alloc > &__lhs, const basic_string< _CharT, _Traits, _Alloc > &__rhs)
Concatenate two strings.
_Safe_iterator & operator--() noexcept
Iterator predecrement.
_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.
Random-access iterators support a superset of bidirectional iterator operations.
bool operator>(const basic_string< _CharT, _Traits, _Alloc > &__lhs, const basic_string< _CharT, _Traits, _Alloc > &__rhs)
Test if string follows string.
_Safe_iterator operator++(int) noexcept
Iterator postincrement.
Struct holding two objects of arbitrary type.
Definition: stl_pair.h:96
void swap(_Tp &, _Tp &) noexcept(__and_< is_nothrow_move_constructible< _Tp >, is_nothrow_move_assignable< _Tp >>::value)
Swaps two values.
Definition: move.h:166
_Iterator base() const noexcept
Return the underlying iterator.
bool _M_dereferenceable() const
Is the iterator dereferenceable?
void _M_attach_single(_Safe_sequence_base *__seq)
Base class that supports tracking of iterators that reference a sequence.
Definition: safe_base.h:177