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