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