Home | History | Annotate | Download | only in 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 
     41 namespace __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