libstdc++
safe_iterator.h
Go to the documentation of this file.
1 // Safe iterator implementation -*- C++ -*-
2 
3 // Copyright (C) 2003, 2004, 2005, 2006, 2009, 2010, 2011, 2012
4 // Free Software Foundation, Inc.
5 //
6 // This file is part of the GNU ISO C++ Library. This library is free
7 // software; you can redistribute it and/or modify it under the
8 // terms of the GNU General Public License as published by the
9 // Free Software Foundation; either version 3, or (at your option)
10 // any later version.
11 
12 // This library is distributed in the hope that it will be useful,
13 // but WITHOUT ANY WARRANTY; without even the implied warranty of
14 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 // GNU General Public License for more details.
16 
17 // Under Section 7 of GPL version 3, you are granted additional
18 // permissions described in the GCC Runtime Library Exception, version
19 // 3.1, as published by the Free Software Foundation.
20 
21 // You should have received a copy of the GNU General Public License and
22 // a copy of the GCC Runtime Library Exception along with this program;
23 // see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
24 // <http://www.gnu.org/licenses/>.
25 
26 /** @file debug/safe_iterator.h
27  * This file is a GNU debug extension to the Standard C++ Library.
28  */
29 
30 #ifndef _GLIBCXX_DEBUG_SAFE_ITERATOR_H
31 #define _GLIBCXX_DEBUG_SAFE_ITERATOR_H 1
32 
33 #include <debug/debug.h>
34 #include <debug/macros.h>
35 #include <debug/functions.h>
36 #include <debug/safe_base.h>
37 #include <bits/stl_pair.h>
38 #include <bits/stl_iterator_base_types.h> // for _Iter_base
39 #include <ext/type_traits.h>
40 
41 namespace __gnu_debug
42 {
43  /** Helper struct to deal with sequence offering a before_begin
44  * iterator.
45  **/
46  template <typename _Sequence>
48  {
49  typedef typename _Sequence::const_iterator _It;
50  typedef typename _It::iterator_type _BaseIt;
51 
52  static bool
53  _S_Is(_BaseIt, const _Sequence*)
54  { return false; }
55 
56  static bool
57  _S_Is_Beginnest(_BaseIt __it, const _Sequence* __seq)
58  { return __it == __seq->_M_base().begin(); }
59  };
60 
61  /** Iterators that derive from _Safe_iterator_base but that aren't
62  * _Safe_iterators can be determined singular or non-singular via
63  * _Safe_iterator_base.
64  */
65  inline bool
66  __check_singular_aux(const _Safe_iterator_base* __x)
67  { return __x->_M_singular(); }
68 
69  /** The precision to which we can calculate the distance between
70  * two iterators.
71  */
73  {
74  __dp_equality, //< Can compare iterator equality, only
75  __dp_sign, //< Can determine equality and ordering
76  __dp_exact //< Can determine distance precisely
77  };
78 
79  /** Determine the distance between two iterators with some known
80  * precision.
81  */
82  template<typename _Iterator1, typename _Iterator2>
85  __get_distance(const _Iterator1& __lhs, const _Iterator2& __rhs,
87  { return std::make_pair(__rhs - __lhs, __dp_exact); }
88 
89  template<typename _Iterator1, typename _Iterator2>
92  __get_distance(const _Iterator1& __lhs, const _Iterator2& __rhs,
94  { return std::make_pair(__lhs == __rhs? 0 : 1, __dp_equality); }
95 
96  template<typename _Iterator1, typename _Iterator2>
99  __get_distance(const _Iterator1& __lhs, const _Iterator2& __rhs)
100  {
101  typedef typename std::iterator_traits<_Iterator1>::iterator_category
102  _Category;
103  return __get_distance(__lhs, __rhs, _Category());
104  }
105 
106  /** \brief Safe iterator wrapper.
107  *
108  * The class template %_Safe_iterator is a wrapper around an
109  * iterator that tracks the iterator's movement among sequences and
110  * checks that operations performed on the "safe" iterator are
111  * legal. In additional to the basic iterator operations (which are
112  * validated, and then passed to the underlying iterator),
113  * %_Safe_iterator has member functions for iterator invalidation,
114  * attaching/detaching the iterator from sequences, and querying
115  * the iterator's state.
116  */
117  template<typename _Iterator, typename _Sequence>
119  {
120  typedef _Safe_iterator _Self;
121 
122  /// The underlying iterator
123  _Iterator _M_current;
124 
125  /// Determine if this is a constant iterator.
126  bool
127  _M_constant() const
128  {
129  typedef typename _Sequence::const_iterator const_iterator;
130  return std::__are_same<const_iterator, _Safe_iterator>::__value;
131  }
132 
133  typedef std::iterator_traits<_Iterator> _Traits;
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() : _M_current() { }
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(const _Iterator& __i, const _Sequence* __seq)
154  : _Safe_iterator_base(__seq, _M_constant()), _M_current(__i)
155  {
156  _GLIBCXX_DEBUG_VERIFY(! this->_M_singular(),
157  _M_message(__msg_init_singular)
158  ._M_iterator(*this, "this"));
159  }
160 
161  /**
162  * @brief Copy construction.
163  */
165  : _Safe_iterator_base(__x, _M_constant()), _M_current(__x._M_current)
166  {
167  // _GLIBCXX_RESOLVE_LIB_DEFECTS
168  // DR 408. Is vector<reverse_iterator<char*> > forbidden?
169  _GLIBCXX_DEBUG_VERIFY(!__x._M_singular()
170  || __x._M_current == _Iterator(),
171  _M_message(__msg_init_copy_singular)
172  ._M_iterator(*this, "this")
173  ._M_iterator(__x, "other"));
174  }
175 
176 #ifdef __GXX_EXPERIMENTAL_CXX0X__
177  /**
178  * @brief Move construction.
179  * @post __x is singular and unattached
180  */
181  _Safe_iterator(_Safe_iterator&& __x) : _M_current()
182  {
183  _GLIBCXX_DEBUG_VERIFY(!__x._M_singular()
184  || __x._M_current == _Iterator(),
185  _M_message(__msg_init_copy_singular)
186  ._M_iterator(*this, "this")
187  ._M_iterator(__x, "other"));
188  std::swap(_M_current, __x._M_current);
189  this->_M_attach(__x._M_sequence);
190  __x._M_detach();
191  }
192 #endif
193 
194  /**
195  * @brief Converting constructor from a mutable iterator to a
196  * constant iterator.
197  */
198  template<typename _MutableIterator>
200  const _Safe_iterator<_MutableIterator,
201  typename __gnu_cxx::__enable_if<(std::__are_same<_MutableIterator,
202  typename _Sequence::iterator::iterator_type>::__value),
203  _Sequence>::__type>& __x)
204  : _Safe_iterator_base(__x, _M_constant()), _M_current(__x.base())
205  {
206  // _GLIBCXX_RESOLVE_LIB_DEFECTS
207  // DR 408. Is vector<reverse_iterator<char*> > forbidden?
208  _GLIBCXX_DEBUG_VERIFY(!__x._M_singular()
209  || __x.base() == _Iterator(),
210  _M_message(__msg_init_const_singular)
211  ._M_iterator(*this, "this")
212  ._M_iterator(__x, "other"));
213  }
214 
215  /**
216  * @brief Copy assignment.
217  */
220  {
221  // _GLIBCXX_RESOLVE_LIB_DEFECTS
222  // DR 408. Is vector<reverse_iterator<char*> > forbidden?
223  _GLIBCXX_DEBUG_VERIFY(!__x._M_singular()
224  || __x._M_current == _Iterator(),
225  _M_message(__msg_copy_singular)
226  ._M_iterator(*this, "this")
227  ._M_iterator(__x, "other"));
228  _M_current = __x._M_current;
229  this->_M_attach(__x._M_sequence);
230  return *this;
231  }
232 
233 #ifdef __GXX_EXPERIMENTAL_CXX0X__
234  /**
235  * @brief Move assignment.
236  * @post __x is singular and unattached
237  */
240  {
241  _GLIBCXX_DEBUG_VERIFY(!__x._M_singular()
242  || __x._M_current == _Iterator(),
243  _M_message(__msg_copy_singular)
244  ._M_iterator(*this, "this")
245  ._M_iterator(__x, "other"));
246  _M_current = __x._M_current;
247  _M_attach(__x._M_sequence);
248  __x._M_detach();
249  __x._M_current = _Iterator();
250  return *this;
251  }
252 #endif
253 
254  /**
255  * @brief Iterator dereference.
256  * @pre iterator is dereferenceable
257  */
258  reference
259  operator*() const
260  {
261  _GLIBCXX_DEBUG_VERIFY(this->_M_dereferenceable(),
262  _M_message(__msg_bad_deref)
263  ._M_iterator(*this, "this"));
264  return *_M_current;
265  }
266 
267  /**
268  * @brief Iterator dereference.
269  * @pre iterator is dereferenceable
270  * @todo Make this correct w.r.t. iterators that return proxies
271  * @todo Use addressof() instead of & operator
272  */
273  pointer
274  operator->() const
275  {
276  _GLIBCXX_DEBUG_VERIFY(this->_M_dereferenceable(),
277  _M_message(__msg_bad_deref)
278  ._M_iterator(*this, "this"));
279  return &*_M_current;
280  }
281 
282  // ------ Input iterator requirements ------
283  /**
284  * @brief Iterator preincrement
285  * @pre iterator is incrementable
286  */
289  {
290  _GLIBCXX_DEBUG_VERIFY(this->_M_incrementable(),
291  _M_message(__msg_bad_inc)
292  ._M_iterator(*this, "this"));
293  ++_M_current;
294  return *this;
295  }
296 
297  /**
298  * @brief Iterator postincrement
299  * @pre iterator is incrementable
300  */
303  {
304  _GLIBCXX_DEBUG_VERIFY(this->_M_incrementable(),
305  _M_message(__msg_bad_inc)
306  ._M_iterator(*this, "this"));
307  _Safe_iterator __tmp(*this);
308  ++_M_current;
309  return __tmp;
310  }
311 
312  // ------ Bidirectional iterator requirements ------
313  /**
314  * @brief Iterator predecrement
315  * @pre iterator is decrementable
316  */
319  {
320  _GLIBCXX_DEBUG_VERIFY(this->_M_decrementable(),
321  _M_message(__msg_bad_dec)
322  ._M_iterator(*this, "this"));
323  --_M_current;
324  return *this;
325  }
326 
327  /**
328  * @brief Iterator postdecrement
329  * @pre iterator is decrementable
330  */
333  {
334  _GLIBCXX_DEBUG_VERIFY(this->_M_decrementable(),
335  _M_message(__msg_bad_dec)
336  ._M_iterator(*this, "this"));
337  _Safe_iterator __tmp(*this);
338  --_M_current;
339  return __tmp;
340  }
341 
342  // ------ Random access iterator requirements ------
343  reference
344  operator[](const difference_type& __n) const
345  {
346  _GLIBCXX_DEBUG_VERIFY(this->_M_can_advance(__n)
347  && this->_M_can_advance(__n+1),
348  _M_message(__msg_iter_subscript_oob)
349  ._M_iterator(*this)._M_integer(__n));
350 
351  return _M_current[__n];
352  }
353 
355  operator+=(const difference_type& __n)
356  {
357  _GLIBCXX_DEBUG_VERIFY(this->_M_can_advance(__n),
358  _M_message(__msg_advance_oob)
359  ._M_iterator(*this)._M_integer(__n));
360  _M_current += __n;
361  return *this;
362  }
363 
365  operator+(const difference_type& __n) const
366  {
367  _Safe_iterator __tmp(*this);
368  __tmp += __n;
369  return __tmp;
370  }
371 
373  operator-=(const difference_type& __n)
374  {
375  _GLIBCXX_DEBUG_VERIFY(this->_M_can_advance(-__n),
376  _M_message(__msg_retreat_oob)
377  ._M_iterator(*this)._M_integer(__n));
378  _M_current += -__n;
379  return *this;
380  }
381 
383  operator-(const difference_type& __n) const
384  {
385  _Safe_iterator __tmp(*this);
386  __tmp -= __n;
387  return __tmp;
388  }
389 
390  // ------ Utilities ------
391  /**
392  * @brief Return the underlying iterator
393  */
394  _Iterator
395  base() const { return _M_current; }
396 
397  /**
398  * @brief Conversion to underlying non-debug iterator to allow
399  * better interaction with non-debug containers.
400  */
401  operator _Iterator() const { return _M_current; }
402 
403  /** Attach iterator to the given sequence. */
404  void
406  {
407  _Safe_iterator_base::_M_attach(__seq, _M_constant());
408  }
409 
410  /** Likewise, but not thread-safe. */
411  void
413  {
414  _Safe_iterator_base::_M_attach_single(__seq, _M_constant());
415  }
416 
417  /// Is the iterator dereferenceable?
418  bool
420  { return !this->_M_singular() && !_M_is_end() && !_M_is_before_begin(); }
421 
422  /// Is the iterator before a dereferenceable one?
423  bool
425  {
426  if (this->_M_incrementable())
427  {
428  _Iterator __base = base();
429  return ++__base != _M_get_sequence()->_M_base().end();
430  }
431  return false;
432  }
433 
434  /// Is the iterator incrementable?
435  bool
437  { return !this->_M_singular() && !_M_is_end(); }
438 
439  // Is the iterator decrementable?
440  bool
441  _M_decrementable() const { return !_M_singular() && !_M_is_begin(); }
442 
443  // Can we advance the iterator @p __n steps (@p __n may be negative)
444  bool
445  _M_can_advance(const difference_type& __n) const;
446 
447  // Is the iterator range [*this, __rhs) valid?
448  template<typename _Other>
449  bool
450  _M_valid_range(const _Safe_iterator<_Other, _Sequence>& __rhs) const;
451 
452  // The sequence this iterator references.
453  const _Sequence*
454  _M_get_sequence() const
455  { return static_cast<const _Sequence*>(_M_sequence); }
456 
457  /// Is this iterator equal to the sequence's begin() iterator?
458  bool _M_is_begin() const
459  { return base() == _M_get_sequence()->_M_base().begin(); }
460 
461  /// Is this iterator equal to the sequence's end() iterator?
462  bool _M_is_end() const
463  { return base() == _M_get_sequence()->_M_base().end(); }
464 
465  /// Is this iterator equal to the sequence's before_begin() iterator if
466  /// any?
467  bool _M_is_before_begin() const
468  {
469  return _BeforeBeginHelper<_Sequence>::_S_Is(base(), _M_get_sequence());
470  }
471 
472  /// Is this iterator equal to the sequence's before_begin() iterator if
473  /// any or begin() otherwise?
474  bool _M_is_beginnest() const
475  {
477  _M_get_sequence());
478  }
479  };
480 
481  template<typename _IteratorL, typename _IteratorR, typename _Sequence>
482  inline bool
483  operator==(const _Safe_iterator<_IteratorL, _Sequence>& __lhs,
484  const _Safe_iterator<_IteratorR, _Sequence>& __rhs)
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  {
502  _GLIBCXX_DEBUG_VERIFY(! __lhs._M_singular() && ! __rhs._M_singular(),
503  _M_message(__msg_iter_compare_bad)
504  ._M_iterator(__lhs, "lhs")
505  ._M_iterator(__rhs, "rhs"));
506  _GLIBCXX_DEBUG_VERIFY(__lhs._M_can_compare(__rhs),
507  _M_message(__msg_compare_different)
508  ._M_iterator(__lhs, "lhs")
509  ._M_iterator(__rhs, "rhs"));
510  return __lhs.base() == __rhs.base();
511  }
512 
513  template<typename _IteratorL, typename _IteratorR, typename _Sequence>
514  inline bool
515  operator!=(const _Safe_iterator<_IteratorL, _Sequence>& __lhs,
516  const _Safe_iterator<_IteratorR, _Sequence>& __rhs)
517  {
518  _GLIBCXX_DEBUG_VERIFY(! __lhs._M_singular() && ! __rhs._M_singular(),
519  _M_message(__msg_iter_compare_bad)
520  ._M_iterator(__lhs, "lhs")
521  ._M_iterator(__rhs, "rhs"));
522  _GLIBCXX_DEBUG_VERIFY(__lhs._M_can_compare(__rhs),
523  _M_message(__msg_compare_different)
524  ._M_iterator(__lhs, "lhs")
525  ._M_iterator(__rhs, "rhs"));
526  return __lhs.base() != __rhs.base();
527  }
528 
529  template<typename _Iterator, typename _Sequence>
530  inline bool
531  operator!=(const _Safe_iterator<_Iterator, _Sequence>& __lhs,
532  const _Safe_iterator<_Iterator, _Sequence>& __rhs)
533  {
534  _GLIBCXX_DEBUG_VERIFY(! __lhs._M_singular() && ! __rhs._M_singular(),
535  _M_message(__msg_iter_compare_bad)
536  ._M_iterator(__lhs, "lhs")
537  ._M_iterator(__rhs, "rhs"));
538  _GLIBCXX_DEBUG_VERIFY(__lhs._M_can_compare(__rhs),
539  _M_message(__msg_compare_different)
540  ._M_iterator(__lhs, "lhs")
541  ._M_iterator(__rhs, "rhs"));
542  return __lhs.base() != __rhs.base();
543  }
544 
545  template<typename _IteratorL, typename _IteratorR, typename _Sequence>
546  inline bool
547  operator<(const _Safe_iterator<_IteratorL, _Sequence>& __lhs,
548  const _Safe_iterator<_IteratorR, _Sequence>& __rhs)
549  {
550  _GLIBCXX_DEBUG_VERIFY(! __lhs._M_singular() && ! __rhs._M_singular(),
551  _M_message(__msg_iter_order_bad)
552  ._M_iterator(__lhs, "lhs")
553  ._M_iterator(__rhs, "rhs"));
554  _GLIBCXX_DEBUG_VERIFY(__lhs._M_can_compare(__rhs),
555  _M_message(__msg_order_different)
556  ._M_iterator(__lhs, "lhs")
557  ._M_iterator(__rhs, "rhs"));
558  return __lhs.base() < __rhs.base();
559  }
560 
561  template<typename _Iterator, typename _Sequence>
562  inline bool
563  operator<(const _Safe_iterator<_Iterator, _Sequence>& __lhs,
564  const _Safe_iterator<_Iterator, _Sequence>& __rhs)
565  {
566  _GLIBCXX_DEBUG_VERIFY(! __lhs._M_singular() && ! __rhs._M_singular(),
567  _M_message(__msg_iter_order_bad)
568  ._M_iterator(__lhs, "lhs")
569  ._M_iterator(__rhs, "rhs"));
570  _GLIBCXX_DEBUG_VERIFY(__lhs._M_can_compare(__rhs),
571  _M_message(__msg_order_different)
572  ._M_iterator(__lhs, "lhs")
573  ._M_iterator(__rhs, "rhs"));
574  return __lhs.base() < __rhs.base();
575  }
576 
577  template<typename _IteratorL, typename _IteratorR, typename _Sequence>
578  inline bool
579  operator<=(const _Safe_iterator<_IteratorL, _Sequence>& __lhs,
580  const _Safe_iterator<_IteratorR, _Sequence>& __rhs)
581  {
582  _GLIBCXX_DEBUG_VERIFY(! __lhs._M_singular() && ! __rhs._M_singular(),
583  _M_message(__msg_iter_order_bad)
584  ._M_iterator(__lhs, "lhs")
585  ._M_iterator(__rhs, "rhs"));
586  _GLIBCXX_DEBUG_VERIFY(__lhs._M_can_compare(__rhs),
587  _M_message(__msg_order_different)
588  ._M_iterator(__lhs, "lhs")
589  ._M_iterator(__rhs, "rhs"));
590  return __lhs.base() <= __rhs.base();
591  }
592 
593  template<typename _Iterator, typename _Sequence>
594  inline bool
595  operator<=(const _Safe_iterator<_Iterator, _Sequence>& __lhs,
596  const _Safe_iterator<_Iterator, _Sequence>& __rhs)
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 _IteratorL, typename _IteratorR, typename _Sequence>
610  inline bool
611  operator>(const _Safe_iterator<_IteratorL, _Sequence>& __lhs,
612  const _Safe_iterator<_IteratorR, _Sequence>& __rhs)
613  {
614  _GLIBCXX_DEBUG_VERIFY(! __lhs._M_singular() && ! __rhs._M_singular(),
615  _M_message(__msg_iter_order_bad)
616  ._M_iterator(__lhs, "lhs")
617  ._M_iterator(__rhs, "rhs"));
618  _GLIBCXX_DEBUG_VERIFY(__lhs._M_can_compare(__rhs),
619  _M_message(__msg_order_different)
620  ._M_iterator(__lhs, "lhs")
621  ._M_iterator(__rhs, "rhs"));
622  return __lhs.base() > __rhs.base();
623  }
624 
625  template<typename _Iterator, typename _Sequence>
626  inline bool
627  operator>(const _Safe_iterator<_Iterator, _Sequence>& __lhs,
628  const _Safe_iterator<_Iterator, _Sequence>& __rhs)
629  {
630  _GLIBCXX_DEBUG_VERIFY(! __lhs._M_singular() && ! __rhs._M_singular(),
631  _M_message(__msg_iter_order_bad)
632  ._M_iterator(__lhs, "lhs")
633  ._M_iterator(__rhs, "rhs"));
634  _GLIBCXX_DEBUG_VERIFY(__lhs._M_can_compare(__rhs),
635  _M_message(__msg_order_different)
636  ._M_iterator(__lhs, "lhs")
637  ._M_iterator(__rhs, "rhs"));
638  return __lhs.base() > __rhs.base();
639  }
640 
641  template<typename _IteratorL, typename _IteratorR, typename _Sequence>
642  inline bool
643  operator>=(const _Safe_iterator<_IteratorL, _Sequence>& __lhs,
644  const _Safe_iterator<_IteratorR, _Sequence>& __rhs)
645  {
646  _GLIBCXX_DEBUG_VERIFY(! __lhs._M_singular() && ! __rhs._M_singular(),
647  _M_message(__msg_iter_order_bad)
648  ._M_iterator(__lhs, "lhs")
649  ._M_iterator(__rhs, "rhs"));
650  _GLIBCXX_DEBUG_VERIFY(__lhs._M_can_compare(__rhs),
651  _M_message(__msg_order_different)
652  ._M_iterator(__lhs, "lhs")
653  ._M_iterator(__rhs, "rhs"));
654  return __lhs.base() >= __rhs.base();
655  }
656 
657  template<typename _Iterator, typename _Sequence>
658  inline bool
659  operator>=(const _Safe_iterator<_Iterator, _Sequence>& __lhs,
660  const _Safe_iterator<_Iterator, _Sequence>& __rhs)
661  {
662  _GLIBCXX_DEBUG_VERIFY(! __lhs._M_singular() && ! __rhs._M_singular(),
663  _M_message(__msg_iter_order_bad)
664  ._M_iterator(__lhs, "lhs")
665  ._M_iterator(__rhs, "rhs"));
666  _GLIBCXX_DEBUG_VERIFY(__lhs._M_can_compare(__rhs),
667  _M_message(__msg_order_different)
668  ._M_iterator(__lhs, "lhs")
669  ._M_iterator(__rhs, "rhs"));
670  return __lhs.base() >= __rhs.base();
671  }
672 
673  // _GLIBCXX_RESOLVE_LIB_DEFECTS
674  // According to the resolution of DR179 not only the various comparison
675  // operators but also operator- must accept mixed iterator/const_iterator
676  // parameters.
677  template<typename _IteratorL, typename _IteratorR, typename _Sequence>
678  inline typename _Safe_iterator<_IteratorL, _Sequence>::difference_type
679  operator-(const _Safe_iterator<_IteratorL, _Sequence>& __lhs,
680  const _Safe_iterator<_IteratorR, _Sequence>& __rhs)
681  {
682  _GLIBCXX_DEBUG_VERIFY(! __lhs._M_singular() && ! __rhs._M_singular(),
683  _M_message(__msg_distance_bad)
684  ._M_iterator(__lhs, "lhs")
685  ._M_iterator(__rhs, "rhs"));
686  _GLIBCXX_DEBUG_VERIFY(__lhs._M_can_compare(__rhs),
687  _M_message(__msg_distance_different)
688  ._M_iterator(__lhs, "lhs")
689  ._M_iterator(__rhs, "rhs"));
690  return __lhs.base() - __rhs.base();
691  }
692 
693  template<typename _Iterator, typename _Sequence>
694  inline typename _Safe_iterator<_Iterator, _Sequence>::difference_type
695  operator-(const _Safe_iterator<_Iterator, _Sequence>& __lhs,
696  const _Safe_iterator<_Iterator, _Sequence>& __rhs)
697  {
698  _GLIBCXX_DEBUG_VERIFY(! __lhs._M_singular() && ! __rhs._M_singular(),
699  _M_message(__msg_distance_bad)
700  ._M_iterator(__lhs, "lhs")
701  ._M_iterator(__rhs, "rhs"));
702  _GLIBCXX_DEBUG_VERIFY(__lhs._M_can_compare(__rhs),
703  _M_message(__msg_distance_different)
704  ._M_iterator(__lhs, "lhs")
705  ._M_iterator(__rhs, "rhs"));
706  return __lhs.base() - __rhs.base();
707  }
708 
709  template<typename _Iterator, typename _Sequence>
710  inline _Safe_iterator<_Iterator, _Sequence>
711  operator+(typename _Safe_iterator<_Iterator,_Sequence>::difference_type __n,
712  const _Safe_iterator<_Iterator, _Sequence>& __i)
713  { return __i + __n; }
714 
715  // Helper struct to detect random access safe iterators.
716  template<typename _Iterator>
717  struct __is_safe_random_iterator
718  {
719  enum { __value = 0 };
720  typedef std::__false_type __type;
721  };
722 
723  template<typename _Iterator, typename _Sequence>
724  struct __is_safe_random_iterator<_Safe_iterator<_Iterator, _Sequence> >
725  : std::__are_same<std::random_access_iterator_tag,
726  typename std::iterator_traits<_Iterator>::
727  iterator_category>
728  { };
729 
730  template<typename _Iterator>
731  struct _Siter_base
732  : std::_Iter_base<_Iterator, __is_safe_random_iterator<_Iterator>::__value>
733  { };
734 
735  /** Helper function to extract base iterator of random access safe iterator
736  in order to reduce performance impact of debug mode. Limited to random
737  access iterator because it is the only category for which it is possible
738  to check for correct iterators order in the __valid_range function
739  thanks to the < operator.
740  */
741  template<typename _Iterator>
742  inline typename _Siter_base<_Iterator>::iterator_type
743  __base(_Iterator __it)
744  { return _Siter_base<_Iterator>::_S_base(__it); }
745 } // namespace __gnu_debug
746 
747 #include <debug/safe_iterator.tcc>
748 
749 #endif