• Home
  • History
  • Annotate
  • Line#
  • Navigate
  • Raw
  • Download
  • only in /asuswrt-rt-n18u-9.0.0.4.380.2695/release/src-rt-6.x.4708/toolchains/hndtools-armeabi-2011.09/arm-none-eabi/include/c++/4.6.1/debug/
1// Safe iterator implementation  -*- C++ -*-
2
3// Copyright (C) 2003, 2004, 2005, 2006, 2009, 2010, 2011
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      _M_Is(_BaseIt __it, const _Sequence* __seq)
54      { return false; }
55    };
56
57  /** Iterators that derive from _Safe_iterator_base but that aren't
58   *  _Safe_iterators can be determined singular or non-singular via
59   *  _Safe_iterator_base.
60   */
61  inline bool
62  __check_singular_aux(const _Safe_iterator_base* __x)
63  { return __x->_M_singular(); }
64
65  /** \brief Safe iterator wrapper.
66   *
67   *  The class template %_Safe_iterator is a wrapper around an
68   *  iterator that tracks the iterator's movement among sequences and
69   *  checks that operations performed on the "safe" iterator are
70   *  legal. In additional to the basic iterator operations (which are
71   *  validated, and then passed to the underlying iterator),
72   *  %_Safe_iterator has member functions for iterator invalidation,
73   *  attaching/detaching the iterator from sequences, and querying
74   *  the iterator's state.
75   */
76  template<typename _Iterator, typename _Sequence>
77    class _Safe_iterator : public _Safe_iterator_base
78    {
79      typedef _Safe_iterator _Self;
80
81      /** The precision to which we can calculate the distance between
82       *  two iterators.
83       */
84      enum _Distance_precision
85	{
86	  __dp_equality, //< Can compare iterator equality, only
87	  __dp_sign,     //< Can determine equality and ordering
88	  __dp_exact     //< Can determine distance precisely
89	};
90
91      /// The underlying iterator
92      _Iterator _M_current;
93
94      /// Determine if this is a constant iterator.
95      bool
96      _M_constant() const
97      {
98	typedef typename _Sequence::const_iterator const_iterator;
99	return std::__are_same<const_iterator, _Safe_iterator>::__value;
100      }
101
102      typedef std::iterator_traits<_Iterator> _Traits;
103
104    public:
105      typedef _Iterator                           iterator_type;
106      typedef typename _Traits::iterator_category iterator_category;
107      typedef typename _Traits::value_type        value_type;
108      typedef typename _Traits::difference_type   difference_type;
109      typedef typename _Traits::reference         reference;
110      typedef typename _Traits::pointer           pointer;
111
112      /// @post the iterator is singular and unattached
113      _Safe_iterator() : _M_current() { }
114
115      /**
116       * @brief Safe iterator construction from an unsafe iterator and
117       * its sequence.
118       *
119       * @pre @p seq is not NULL
120       * @post this is not singular
121       */
122      _Safe_iterator(const _Iterator& __i, const _Sequence* __seq)
123      : _Safe_iterator_base(__seq, _M_constant()), _M_current(__i)
124      {
125	_GLIBCXX_DEBUG_VERIFY(! this->_M_singular(),
126			      _M_message(__msg_init_singular)
127			      ._M_iterator(*this, "this"));
128      }
129
130      /**
131       * @brief Copy construction.
132       */
133      _Safe_iterator(const _Safe_iterator& __x)
134      : _Safe_iterator_base(__x, _M_constant()), _M_current(__x._M_current)
135      {
136	// _GLIBCXX_RESOLVE_LIB_DEFECTS
137	// DR 408. Is vector<reverse_iterator<char*> > forbidden?
138	_GLIBCXX_DEBUG_VERIFY(!__x._M_singular()
139			      || __x._M_current == _Iterator(),
140			      _M_message(__msg_init_copy_singular)
141			      ._M_iterator(*this, "this")
142			      ._M_iterator(__x, "other"));
143      }
144
145      /**
146       *  @brief Converting constructor from a mutable iterator to a
147       *  constant iterator.
148      */
149      template<typename _MutableIterator>
150        _Safe_iterator(
151          const _Safe_iterator<_MutableIterator,
152          typename __gnu_cxx::__enable_if<(std::__are_same<_MutableIterator,
153                      typename _Sequence::iterator::iterator_type>::__value),
154                   _Sequence>::__type>& __x)
155	: _Safe_iterator_base(__x, _M_constant()), _M_current(__x.base())
156        {
157	  // _GLIBCXX_RESOLVE_LIB_DEFECTS
158	  // DR 408. Is vector<reverse_iterator<char*> > forbidden?
159	  _GLIBCXX_DEBUG_VERIFY(!__x._M_singular()
160				|| __x.base() == _Iterator(),
161				_M_message(__msg_init_const_singular)
162				._M_iterator(*this, "this")
163				._M_iterator(__x, "other"));
164	}
165
166      /**
167       * @brief Copy assignment.
168       */
169      _Safe_iterator&
170      operator=(const _Safe_iterator& __x)
171      {
172	// _GLIBCXX_RESOLVE_LIB_DEFECTS
173	// DR 408. Is vector<reverse_iterator<char*> > forbidden?
174	_GLIBCXX_DEBUG_VERIFY(!__x._M_singular()
175			      || __x._M_current == _Iterator(),
176			      _M_message(__msg_copy_singular)
177			      ._M_iterator(*this, "this")
178			      ._M_iterator(__x, "other"));
179	_M_current = __x._M_current;
180	this->_M_attach(__x._M_sequence);
181	return *this;
182      }
183
184      /**
185       *  @brief Iterator dereference.
186       *  @pre iterator is dereferenceable
187       */
188      reference
189      operator*() const
190      {
191	_GLIBCXX_DEBUG_VERIFY(this->_M_dereferenceable(),
192			      _M_message(__msg_bad_deref)
193			      ._M_iterator(*this, "this"));
194	return *_M_current;
195      }
196
197      /**
198       *  @brief Iterator dereference.
199       *  @pre iterator is dereferenceable
200       *  @todo Make this correct w.r.t. iterators that return proxies
201       *  @todo Use addressof() instead of & operator
202       */
203      pointer
204      operator->() const
205      {
206	_GLIBCXX_DEBUG_VERIFY(this->_M_dereferenceable(),
207			      _M_message(__msg_bad_deref)
208			      ._M_iterator(*this, "this"));
209	return &*_M_current;
210      }
211
212      // ------ Input iterator requirements ------
213      /**
214       *  @brief Iterator preincrement
215       *  @pre iterator is incrementable
216       */
217      _Safe_iterator&
218      operator++()
219      {
220	_GLIBCXX_DEBUG_VERIFY(this->_M_incrementable(),
221			      _M_message(__msg_bad_inc)
222			      ._M_iterator(*this, "this"));
223	++_M_current;
224	return *this;
225      }
226
227      /**
228       *  @brief Iterator postincrement
229       *  @pre iterator is incrementable
230       */
231      _Safe_iterator
232      operator++(int)
233      {
234	_GLIBCXX_DEBUG_VERIFY(this->_M_incrementable(),
235			      _M_message(__msg_bad_inc)
236			      ._M_iterator(*this, "this"));
237	_Safe_iterator __tmp(*this);
238	++_M_current;
239	return __tmp;
240      }
241
242      // ------ Bidirectional iterator requirements ------
243      /**
244       *  @brief Iterator predecrement
245       *  @pre iterator is decrementable
246       */
247      _Safe_iterator&
248      operator--()
249      {
250	_GLIBCXX_DEBUG_VERIFY(this->_M_decrementable(),
251			      _M_message(__msg_bad_dec)
252			      ._M_iterator(*this, "this"));
253	--_M_current;
254	return *this;
255      }
256
257      /**
258       *  @brief Iterator postdecrement
259       *  @pre iterator is decrementable
260       */
261      _Safe_iterator
262      operator--(int)
263      {
264	_GLIBCXX_DEBUG_VERIFY(this->_M_decrementable(),
265			      _M_message(__msg_bad_dec)
266			      ._M_iterator(*this, "this"));
267	_Safe_iterator __tmp(*this);
268	--_M_current;
269	return __tmp;
270      }
271
272      // ------ Random access iterator requirements ------
273      reference
274      operator[](const difference_type& __n) const
275      {
276	_GLIBCXX_DEBUG_VERIFY(this->_M_can_advance(__n)
277			      && this->_M_can_advance(__n+1),
278			      _M_message(__msg_iter_subscript_oob)
279			      ._M_iterator(*this)._M_integer(__n));
280
281	return _M_current[__n];
282      }
283
284      _Safe_iterator&
285      operator+=(const difference_type& __n)
286      {
287	_GLIBCXX_DEBUG_VERIFY(this->_M_can_advance(__n),
288			      _M_message(__msg_advance_oob)
289			      ._M_iterator(*this)._M_integer(__n));
290	_M_current += __n;
291	return *this;
292      }
293
294      _Safe_iterator
295      operator+(const difference_type& __n) const
296      {
297	_Safe_iterator __tmp(*this);
298	__tmp += __n;
299	return __tmp;
300      }
301
302      _Safe_iterator&
303      operator-=(const difference_type& __n)
304      {
305	_GLIBCXX_DEBUG_VERIFY(this->_M_can_advance(-__n),
306			      _M_message(__msg_retreat_oob)
307			      ._M_iterator(*this)._M_integer(__n));
308	_M_current += -__n;
309	return *this;
310      }
311
312      _Safe_iterator
313      operator-(const difference_type& __n) const
314      {
315	_Safe_iterator __tmp(*this);
316	__tmp -= __n;
317	return __tmp;
318      }
319
320      // ------ Utilities ------
321      /**
322       * @brief Return the underlying iterator
323       */
324      _Iterator
325      base() const { return _M_current; }
326
327      /**
328       * @brief Conversion to underlying non-debug iterator to allow
329       * better interaction with non-debug containers.
330       */
331      operator _Iterator() const { return _M_current; }
332
333      /** Attach iterator to the given sequence. */
334      void
335      _M_attach(_Safe_sequence_base* __seq)
336      {
337	_Safe_iterator_base::_M_attach(__seq, _M_constant());
338      }
339
340      /** Likewise, but not thread-safe. */
341      void
342      _M_attach_single(_Safe_sequence_base* __seq)
343      {
344	_Safe_iterator_base::_M_attach_single(__seq, _M_constant());
345      }
346
347      /// Is the iterator dereferenceable?
348      bool
349      _M_dereferenceable() const
350      { return !this->_M_singular() && !_M_is_end() && !_M_is_before_begin(); }
351
352      /// Is the iterator before a dereferenceable one?
353      bool
354      _M_before_dereferenceable() const
355      {
356	_Self __it = *this;
357	return __it._M_incrementable() && (++__it)._M_dereferenceable();
358      }
359
360      /// Is the iterator incrementable?
361      bool
362      _M_incrementable() const
363      { return !this->_M_singular() && !_M_is_end(); }
364
365      // Is the iterator decrementable?
366      bool
367      _M_decrementable() const { return !_M_singular() && !_M_is_begin(); }
368
369      // Can we advance the iterator @p __n steps (@p __n may be negative)
370      bool
371      _M_can_advance(const difference_type& __n) const;
372
373      // Is the iterator range [*this, __rhs) valid?
374      template<typename _Other>
375        bool
376        _M_valid_range(const _Safe_iterator<_Other, _Sequence>& __rhs) const;
377
378      // The sequence this iterator references.
379      const _Sequence*
380      _M_get_sequence() const
381      { return static_cast<const _Sequence*>(_M_sequence); }
382
383    /** Determine the distance between two iterators with some known
384     *	precision.
385    */
386    template<typename _Iterator1, typename _Iterator2>
387      static std::pair<difference_type, _Distance_precision>
388      _M_get_distance(const _Iterator1& __lhs, const _Iterator2& __rhs)
389      {
390        typedef typename std::iterator_traits<_Iterator1>::iterator_category
391	  _Category;
392        return _M_get_distance(__lhs, __rhs, _Category());
393      }
394
395    template<typename _Iterator1, typename _Iterator2>
396      static std::pair<difference_type, _Distance_precision>
397      _M_get_distance(const _Iterator1& __lhs, const _Iterator2& __rhs,
398		      std::random_access_iterator_tag)
399      { return std::make_pair(__rhs - __lhs, __dp_exact); }
400
401    template<typename _Iterator1, typename _Iterator2>
402      static std::pair<difference_type, _Distance_precision>
403      _M_get_distance(const _Iterator1& __lhs, const _Iterator2& __rhs,
404		    std::forward_iterator_tag)
405      { return std::make_pair(__lhs == __rhs? 0 : 1, __dp_equality); }
406
407      /// Is this iterator equal to the sequence's begin() iterator?
408      bool _M_is_begin() const
409      { return base() == _M_get_sequence()->_M_base().begin(); }
410
411      /// Is this iterator equal to the sequence's end() iterator?
412      bool _M_is_end() const
413      { return base() == _M_get_sequence()->_M_base().end(); }
414
415      /// Is this iterator equal to the sequence's before_begin() iterator if
416      /// any?
417      bool _M_is_before_begin() const
418      { return _BeforeBeginHelper<_Sequence>::_M_Is(base(), _M_get_sequence()); }
419    };
420
421  template<typename _IteratorL, typename _IteratorR, typename _Sequence>
422    inline bool
423    operator==(const _Safe_iterator<_IteratorL, _Sequence>& __lhs,
424	       const _Safe_iterator<_IteratorR, _Sequence>& __rhs)
425    {
426      _GLIBCXX_DEBUG_VERIFY(! __lhs._M_singular() && ! __rhs._M_singular(),
427			    _M_message(__msg_iter_compare_bad)
428			    ._M_iterator(__lhs, "lhs")
429			    ._M_iterator(__rhs, "rhs"));
430      _GLIBCXX_DEBUG_VERIFY(__lhs._M_can_compare(__rhs),
431			    _M_message(__msg_compare_different)
432			    ._M_iterator(__lhs, "lhs")
433			    ._M_iterator(__rhs, "rhs"));
434      return __lhs.base() == __rhs.base();
435    }
436
437  template<typename _Iterator, typename _Sequence>
438    inline bool
439    operator==(const _Safe_iterator<_Iterator, _Sequence>& __lhs,
440               const _Safe_iterator<_Iterator, _Sequence>& __rhs)
441    {
442      _GLIBCXX_DEBUG_VERIFY(! __lhs._M_singular() && ! __rhs._M_singular(),
443			    _M_message(__msg_iter_compare_bad)
444			    ._M_iterator(__lhs, "lhs")
445			    ._M_iterator(__rhs, "rhs"));
446      _GLIBCXX_DEBUG_VERIFY(__lhs._M_can_compare(__rhs),
447			    _M_message(__msg_compare_different)
448			    ._M_iterator(__lhs, "lhs")
449			    ._M_iterator(__rhs, "rhs"));
450      return __lhs.base() == __rhs.base();
451    }
452
453  template<typename _IteratorL, typename _IteratorR, typename _Sequence>
454    inline bool
455    operator!=(const _Safe_iterator<_IteratorL, _Sequence>& __lhs,
456	       const _Safe_iterator<_IteratorR, _Sequence>& __rhs)
457    {
458      _GLIBCXX_DEBUG_VERIFY(! __lhs._M_singular() && ! __rhs._M_singular(),
459			    _M_message(__msg_iter_compare_bad)
460			    ._M_iterator(__lhs, "lhs")
461			    ._M_iterator(__rhs, "rhs"));
462      _GLIBCXX_DEBUG_VERIFY(__lhs._M_can_compare(__rhs),
463			    _M_message(__msg_compare_different)
464			    ._M_iterator(__lhs, "lhs")
465			    ._M_iterator(__rhs, "rhs"));
466      return __lhs.base() != __rhs.base();
467    }
468
469  template<typename _Iterator, typename _Sequence>
470    inline bool
471    operator!=(const _Safe_iterator<_Iterator, _Sequence>& __lhs,
472               const _Safe_iterator<_Iterator, _Sequence>& __rhs)
473    {
474      _GLIBCXX_DEBUG_VERIFY(! __lhs._M_singular() && ! __rhs._M_singular(),
475			    _M_message(__msg_iter_compare_bad)
476			    ._M_iterator(__lhs, "lhs")
477			    ._M_iterator(__rhs, "rhs"));
478      _GLIBCXX_DEBUG_VERIFY(__lhs._M_can_compare(__rhs),
479			    _M_message(__msg_compare_different)
480			    ._M_iterator(__lhs, "lhs")
481			    ._M_iterator(__rhs, "rhs"));
482      return __lhs.base() != __rhs.base();
483    }
484
485  template<typename _IteratorL, typename _IteratorR, typename _Sequence>
486    inline bool
487    operator<(const _Safe_iterator<_IteratorL, _Sequence>& __lhs,
488	      const _Safe_iterator<_IteratorR, _Sequence>& __rhs)
489    {
490      _GLIBCXX_DEBUG_VERIFY(! __lhs._M_singular() && ! __rhs._M_singular(),
491			    _M_message(__msg_iter_order_bad)
492			    ._M_iterator(__lhs, "lhs")
493			    ._M_iterator(__rhs, "rhs"));
494      _GLIBCXX_DEBUG_VERIFY(__lhs._M_can_compare(__rhs),
495			    _M_message(__msg_order_different)
496			    ._M_iterator(__lhs, "lhs")
497			    ._M_iterator(__rhs, "rhs"));
498      return __lhs.base() < __rhs.base();
499    }
500
501  template<typename _Iterator, typename _Sequence>
502    inline bool
503    operator<(const _Safe_iterator<_Iterator, _Sequence>& __lhs,
504	      const _Safe_iterator<_Iterator, _Sequence>& __rhs)
505    {
506      _GLIBCXX_DEBUG_VERIFY(! __lhs._M_singular() && ! __rhs._M_singular(),
507			    _M_message(__msg_iter_order_bad)
508			    ._M_iterator(__lhs, "lhs")
509			    ._M_iterator(__rhs, "rhs"));
510      _GLIBCXX_DEBUG_VERIFY(__lhs._M_can_compare(__rhs),
511			    _M_message(__msg_order_different)
512			    ._M_iterator(__lhs, "lhs")
513			    ._M_iterator(__rhs, "rhs"));
514      return __lhs.base() < __rhs.base();
515    }
516
517  template<typename _IteratorL, typename _IteratorR, typename _Sequence>
518    inline bool
519    operator<=(const _Safe_iterator<_IteratorL, _Sequence>& __lhs,
520	       const _Safe_iterator<_IteratorR, _Sequence>& __rhs)
521    {
522      _GLIBCXX_DEBUG_VERIFY(! __lhs._M_singular() && ! __rhs._M_singular(),
523			    _M_message(__msg_iter_order_bad)
524			    ._M_iterator(__lhs, "lhs")
525			    ._M_iterator(__rhs, "rhs"));
526      _GLIBCXX_DEBUG_VERIFY(__lhs._M_can_compare(__rhs),
527			    _M_message(__msg_order_different)
528			    ._M_iterator(__lhs, "lhs")
529			    ._M_iterator(__rhs, "rhs"));
530      return __lhs.base() <= __rhs.base();
531    }
532
533  template<typename _Iterator, typename _Sequence>
534    inline bool
535    operator<=(const _Safe_iterator<_Iterator, _Sequence>& __lhs,
536               const _Safe_iterator<_Iterator, _Sequence>& __rhs)
537    {
538      _GLIBCXX_DEBUG_VERIFY(! __lhs._M_singular() && ! __rhs._M_singular(),
539			    _M_message(__msg_iter_order_bad)
540			    ._M_iterator(__lhs, "lhs")
541			    ._M_iterator(__rhs, "rhs"));
542      _GLIBCXX_DEBUG_VERIFY(__lhs._M_can_compare(__rhs),
543			    _M_message(__msg_order_different)
544			    ._M_iterator(__lhs, "lhs")
545			    ._M_iterator(__rhs, "rhs"));
546      return __lhs.base() <= __rhs.base();
547    }
548
549  template<typename _IteratorL, typename _IteratorR, typename _Sequence>
550    inline bool
551    operator>(const _Safe_iterator<_IteratorL, _Sequence>& __lhs,
552	      const _Safe_iterator<_IteratorR, _Sequence>& __rhs)
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    {
570      _GLIBCXX_DEBUG_VERIFY(! __lhs._M_singular() && ! __rhs._M_singular(),
571			    _M_message(__msg_iter_order_bad)
572			    ._M_iterator(__lhs, "lhs")
573			    ._M_iterator(__rhs, "rhs"));
574      _GLIBCXX_DEBUG_VERIFY(__lhs._M_can_compare(__rhs),
575			    _M_message(__msg_order_different)
576			    ._M_iterator(__lhs, "lhs")
577			    ._M_iterator(__rhs, "rhs"));
578      return __lhs.base() > __rhs.base();
579    }
580
581  template<typename _IteratorL, typename _IteratorR, typename _Sequence>
582    inline bool
583    operator>=(const _Safe_iterator<_IteratorL, _Sequence>& __lhs,
584	       const _Safe_iterator<_IteratorR, _Sequence>& __rhs)
585    {
586      _GLIBCXX_DEBUG_VERIFY(! __lhs._M_singular() && ! __rhs._M_singular(),
587			    _M_message(__msg_iter_order_bad)
588			    ._M_iterator(__lhs, "lhs")
589			    ._M_iterator(__rhs, "rhs"));
590      _GLIBCXX_DEBUG_VERIFY(__lhs._M_can_compare(__rhs),
591			    _M_message(__msg_order_different)
592			    ._M_iterator(__lhs, "lhs")
593			    ._M_iterator(__rhs, "rhs"));
594      return __lhs.base() >= __rhs.base();
595    }
596
597  template<typename _Iterator, typename _Sequence>
598    inline bool
599    operator>=(const _Safe_iterator<_Iterator, _Sequence>& __lhs,
600               const _Safe_iterator<_Iterator, _Sequence>& __rhs)
601    {
602      _GLIBCXX_DEBUG_VERIFY(! __lhs._M_singular() && ! __rhs._M_singular(),
603			    _M_message(__msg_iter_order_bad)
604			    ._M_iterator(__lhs, "lhs")
605			    ._M_iterator(__rhs, "rhs"));
606      _GLIBCXX_DEBUG_VERIFY(__lhs._M_can_compare(__rhs),
607			    _M_message(__msg_order_different)
608			    ._M_iterator(__lhs, "lhs")
609			    ._M_iterator(__rhs, "rhs"));
610      return __lhs.base() >= __rhs.base();
611    }
612
613  // _GLIBCXX_RESOLVE_LIB_DEFECTS
614  // According to the resolution of DR179 not only the various comparison
615  // operators but also operator- must accept mixed iterator/const_iterator
616  // parameters.
617  template<typename _IteratorL, typename _IteratorR, typename _Sequence>
618    inline typename _Safe_iterator<_IteratorL, _Sequence>::difference_type
619    operator-(const _Safe_iterator<_IteratorL, _Sequence>& __lhs,
620	      const _Safe_iterator<_IteratorR, _Sequence>& __rhs)
621    {
622      _GLIBCXX_DEBUG_VERIFY(! __lhs._M_singular() && ! __rhs._M_singular(),
623			    _M_message(__msg_distance_bad)
624			    ._M_iterator(__lhs, "lhs")
625			    ._M_iterator(__rhs, "rhs"));
626      _GLIBCXX_DEBUG_VERIFY(__lhs._M_can_compare(__rhs),
627			    _M_message(__msg_distance_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 typename _Safe_iterator<_Iterator, _Sequence>::difference_type
635     operator-(const _Safe_iterator<_Iterator, _Sequence>& __lhs,
636	       const _Safe_iterator<_Iterator, _Sequence>& __rhs)
637     {
638       _GLIBCXX_DEBUG_VERIFY(! __lhs._M_singular() && ! __rhs._M_singular(),
639			     _M_message(__msg_distance_bad)
640			     ._M_iterator(__lhs, "lhs")
641			     ._M_iterator(__rhs, "rhs"));
642       _GLIBCXX_DEBUG_VERIFY(__lhs._M_can_compare(__rhs),
643			     _M_message(__msg_distance_different)
644			     ._M_iterator(__lhs, "lhs")
645			     ._M_iterator(__rhs, "rhs"));
646       return __lhs.base() - __rhs.base();
647     }
648
649  template<typename _Iterator, typename _Sequence>
650    inline _Safe_iterator<_Iterator, _Sequence>
651    operator+(typename _Safe_iterator<_Iterator,_Sequence>::difference_type __n,
652	      const _Safe_iterator<_Iterator, _Sequence>& __i)
653    { return __i + __n; }
654
655  // Helper struct to detect random access safe iterators.
656  template<typename _Iterator>
657    struct __is_safe_random_iterator
658    {
659      enum { __value = 0 };
660      typedef std::__false_type __type;
661    };
662
663  template<typename _Iterator, typename _Sequence>
664    struct __is_safe_random_iterator<_Safe_iterator<_Iterator, _Sequence> >
665    : std::__are_same<std::random_access_iterator_tag,
666                      typename std::iterator_traits<_Iterator>::
667		      iterator_category>
668    { };
669
670  template<typename _Iterator>
671    struct _Siter_base
672    : std::_Iter_base<_Iterator, __is_safe_random_iterator<_Iterator>::__value>
673    { };
674
675  /** Helper function to extract base iterator of random access safe iterator
676      in order to reduce performance impact of debug mode.  Limited to random
677      access iterator because it is the only category for which it is possible
678      to check for correct iterators order in the __valid_range function
679      thanks to the < operator.
680  */
681  template<typename _Iterator>
682    inline typename _Siter_base<_Iterator>::iterator_type
683    __base(_Iterator __it)
684    { return _Siter_base<_Iterator>::_S_base(__it); }
685} // namespace __gnu_debug
686
687#include <debug/safe_iterator.tcc>
688
689#endif
690