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
41namespace __gnu_debug
42{
43  /** Helper struct to deal with sequence offering a before_begin
44   *  iterator.
45   **/
46  template <typename _Sequence>
47    struct _BeforeBeginHelper
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   */
72  enum _Distance_precision
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>
83    inline std::pair<typename std::iterator_traits<_Iterator1>::difference_type,
84		     _Distance_precision>
85    __get_distance(const _Iterator1& __lhs, const _Iterator2& __rhs,
86		   std::random_access_iterator_tag)
87    { return std::make_pair(__rhs - __lhs, __dp_exact); }
88
89  template<typename _Iterator1, typename _Iterator2>
90    inline std::pair<typename std::iterator_traits<_Iterator1>::difference_type,
91		     _Distance_precision>
92    __get_distance(const _Iterator1& __lhs, const _Iterator2& __rhs,
93		   std::forward_iterator_tag)
94    { return std::make_pair(__lhs == __rhs? 0 : 1, __dp_equality); }
95
96  template<typename _Iterator1, typename _Iterator2>
97    inline std::pair<typename std::iterator_traits<_Iterator1>::difference_type,
98		     _Distance_precision>
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>
118    class _Safe_iterator : public _Safe_iterator_base
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       */
164      _Safe_iterator(const _Safe_iterator& __x)
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>
199        _Safe_iterator(
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       */
218      _Safe_iterator&
219      operator=(const _Safe_iterator& __x)
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       */
238      _Safe_iterator&
239      operator=(_Safe_iterator&& __x)
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       */
287      _Safe_iterator&
288      operator++()
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       */
301      _Safe_iterator
302      operator++(int)
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       */
317      _Safe_iterator&
318      operator--()
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       */
331      _Safe_iterator
332      operator--(int)
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
354      _Safe_iterator&
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
364      _Safe_iterator
365      operator+(const difference_type& __n) const
366      {
367	_Safe_iterator __tmp(*this);
368	__tmp += __n;
369	return __tmp;
370      }
371
372      _Safe_iterator&
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
382      _Safe_iterator
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
405      _M_attach(_Safe_sequence_base* __seq)
406      {
407	_Safe_iterator_base::_M_attach(__seq, _M_constant());
408      }
409
410      /** Likewise, but not thread-safe. */
411      void
412      _M_attach_single(_Safe_sequence_base* __seq)
413      {
414	_Safe_iterator_base::_M_attach_single(__seq, _M_constant());
415      }
416
417      /// Is the iterator dereferenceable?
418      bool
419      _M_dereferenceable() const
420      { return !this->_M_singular() && !_M_is_end() && !_M_is_before_begin(); }
421
422      /// Is the iterator before a dereferenceable one?
423      bool
424      _M_before_dereferenceable() const
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
436      _M_incrementable() const
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      {
476	return _BeforeBeginHelper<_Sequence>::_S_Is_Beginnest(base(),
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
750