Home | History | Annotate | Download | only in debug
      1 // Safe iterator implementation  -*- C++ -*-
      2 
      3 // Copyright (C) 2003, 2004, 2005, 2006, 2009
      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/formatter.h>
     37 #include <debug/safe_base.h>
     38 #include <bits/stl_pair.h>
     39 #include <ext/type_traits.h>
     40 
     41 namespace __gnu_debug
     42 {
     43   /** Iterators that derive from _Safe_iterator_base but that aren't
     44    *  _Safe_iterators can be determined singular or non-singular via
     45    *  _Safe_iterator_base.
     46    */
     47   inline bool
     48   __check_singular_aux(const _Safe_iterator_base* __x)
     49   { return __x->_M_singular(); }
     50 
     51   /** \brief Safe iterator wrapper.
     52    *
     53    *  The class template %_Safe_iterator is a wrapper around an
     54    *  iterator that tracks the iterator's movement among sequences and
     55    *  checks that operations performed on the "safe" iterator are
     56    *  legal. In additional to the basic iterator operations (which are
     57    *  validated, and then passed to the underlying iterator),
     58    *  %_Safe_iterator has member functions for iterator invalidation,
     59    *  attaching/detaching the iterator from sequences, and querying
     60    *  the iterator's state.
     61    */
     62   template<typename _Iterator, typename _Sequence>
     63     class _Safe_iterator : public _Safe_iterator_base
     64     {
     65       typedef _Safe_iterator _Self;
     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       /// The underlying iterator
     78       _Iterator _M_current;
     79 
     80       /// Determine if this is a constant iterator.
     81       bool
     82       _M_constant() const
     83       {
     84 	typedef typename _Sequence::const_iterator const_iterator;
     85 	return __is_same<const_iterator, _Safe_iterator>::value;
     86       }
     87 
     88       typedef std::iterator_traits<_Iterator> _Traits;
     89 
     90     public:
     91       typedef _Iterator                           _Base_iterator;
     92       typedef typename _Traits::iterator_category iterator_category;
     93       typedef typename _Traits::value_type        value_type;
     94       typedef typename _Traits::difference_type   difference_type;
     95       typedef typename _Traits::reference         reference;
     96       typedef typename _Traits::pointer           pointer;
     97 
     98       /// @post the iterator is singular and unattached
     99       _Safe_iterator() : _M_current() { }
    100 
    101       /**
    102        * @brief Safe iterator construction from an unsafe iterator and
    103        * its sequence.
    104        *
    105        * @pre @p seq is not NULL
    106        * @post this is not singular
    107        */
    108       _Safe_iterator(const _Iterator& __i, const _Sequence* __seq)
    109       : _Safe_iterator_base(__seq, _M_constant()), _M_current(__i)
    110       {
    111 	_GLIBCXX_DEBUG_VERIFY(! this->_M_singular(),
    112 			      _M_message(__msg_init_singular)
    113 			      ._M_iterator(*this, "this"));
    114       }
    115 
    116       /**
    117        * @brief Copy construction.
    118        * @pre @p x is not singular
    119        */
    120       _Safe_iterator(const _Safe_iterator& __x)
    121       : _Safe_iterator_base(__x, _M_constant()), _M_current(__x._M_current)
    122       {
    123 	_GLIBCXX_DEBUG_VERIFY(!__x._M_singular(),
    124 			      _M_message(__msg_init_copy_singular)
    125 			      ._M_iterator(*this, "this")
    126 			      ._M_iterator(__x, "other"));
    127       }
    128 
    129       /**
    130        *  @brief Converting constructor from a mutable iterator to a
    131        *  constant iterator.
    132        *
    133        *  @pre @p x is not singular
    134       */
    135       template<typename _MutableIterator>
    136         _Safe_iterator(
    137           const _Safe_iterator<_MutableIterator,
    138           typename __gnu_cxx::__enable_if<(std::__are_same<_MutableIterator,
    139                       typename _Sequence::iterator::_Base_iterator>::__value),
    140                    _Sequence>::__type>& __x)
    141 	: _Safe_iterator_base(__x, _M_constant()), _M_current(__x.base())
    142         {
    143 	  _GLIBCXX_DEBUG_VERIFY(!__x._M_singular(),
    144 				_M_message(__msg_init_const_singular)
    145 				._M_iterator(*this, "this")
    146 				._M_iterator(__x, "other"));
    147 	}
    148 
    149       /**
    150        * @brief Copy assignment.
    151        * @pre @p x is not singular
    152        */
    153       _Safe_iterator&
    154       operator=(const _Safe_iterator& __x)
    155       {
    156 	_GLIBCXX_DEBUG_VERIFY(!__x._M_singular(),
    157 			      _M_message(__msg_copy_singular)
    158 			      ._M_iterator(*this, "this")
    159 			      ._M_iterator(__x, "other"));
    160 	_M_current = __x._M_current;
    161 	this->_M_attach(static_cast<_Sequence*>(__x._M_sequence));
    162 	return *this;
    163       }
    164 
    165       /**
    166        *  @brief Iterator dereference.
    167        *  @pre iterator is dereferenceable
    168        */
    169       reference
    170       operator*() const
    171       {
    172 
    173 	_GLIBCXX_DEBUG_VERIFY(this->_M_dereferenceable(),
    174 			      _M_message(__msg_bad_deref)
    175 			      ._M_iterator(*this, "this"));
    176 	return *_M_current;
    177       }
    178 
    179       /**
    180        *  @brief Iterator dereference.
    181        *  @pre iterator is dereferenceable
    182        *  @todo Make this correct w.r.t. iterators that return proxies
    183        *  @todo Use addressof() instead of & operator
    184        */
    185       pointer
    186       operator->() const
    187       {
    188 	_GLIBCXX_DEBUG_VERIFY(this->_M_dereferenceable(),
    189 			      _M_message(__msg_bad_deref)
    190 			      ._M_iterator(*this, "this"));
    191 	return &*_M_current;
    192       }
    193 
    194       // ------ Input iterator requirements ------
    195       /**
    196        *  @brief Iterator preincrement
    197        *  @pre iterator is incrementable
    198        */
    199       _Safe_iterator&
    200       operator++()
    201       {
    202 	_GLIBCXX_DEBUG_VERIFY(this->_M_incrementable(),
    203 			      _M_message(__msg_bad_inc)
    204 			      ._M_iterator(*this, "this"));
    205 	++_M_current;
    206 	return *this;
    207       }
    208 
    209       /**
    210        *  @brief Iterator postincrement
    211        *  @pre iterator is incrementable
    212        */
    213       _Safe_iterator
    214       operator++(int)
    215       {
    216 	_GLIBCXX_DEBUG_VERIFY(this->_M_incrementable(),
    217 			      _M_message(__msg_bad_inc)
    218 			      ._M_iterator(*this, "this"));
    219 	_Safe_iterator __tmp(*this);
    220 	++_M_current;
    221 	return __tmp;
    222       }
    223 
    224       // ------ Bidirectional iterator requirements ------
    225       /**
    226        *  @brief Iterator predecrement
    227        *  @pre iterator is decrementable
    228        */
    229       _Safe_iterator&
    230       operator--()
    231       {
    232 	_GLIBCXX_DEBUG_VERIFY(this->_M_decrementable(),
    233 			      _M_message(__msg_bad_dec)
    234 			      ._M_iterator(*this, "this"));
    235 	--_M_current;
    236 	return *this;
    237       }
    238 
    239       /**
    240        *  @brief Iterator postdecrement
    241        *  @pre iterator is decrementable
    242        */
    243       _Safe_iterator
    244       operator--(int)
    245       {
    246 	_GLIBCXX_DEBUG_VERIFY(this->_M_decrementable(),
    247 			      _M_message(__msg_bad_dec)
    248 			      ._M_iterator(*this, "this"));
    249 	_Safe_iterator __tmp(*this);
    250 	--_M_current;
    251 	return __tmp;
    252       }
    253 
    254       // ------ Random access iterator requirements ------
    255       reference
    256       operator[](const difference_type& __n) const
    257       {
    258 	_GLIBCXX_DEBUG_VERIFY(this->_M_can_advance(__n)
    259 			      && this->_M_can_advance(__n+1),
    260 			      _M_message(__msg_iter_subscript_oob)
    261 			      ._M_iterator(*this)._M_integer(__n));
    262 
    263 	return _M_current[__n];
    264       }
    265 
    266       _Safe_iterator&
    267       operator+=(const difference_type& __n)
    268       {
    269 	_GLIBCXX_DEBUG_VERIFY(this->_M_can_advance(__n),
    270 			      _M_message(__msg_advance_oob)
    271 			      ._M_iterator(*this)._M_integer(__n));
    272 	_M_current += __n;
    273 	return *this;
    274       }
    275 
    276       _Safe_iterator
    277       operator+(const difference_type& __n) const
    278       {
    279 	_Safe_iterator __tmp(*this);
    280 	__tmp += __n;
    281 	return __tmp;
    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_retreat_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       // ------ Utilities ------
    303       /**
    304        * @brief Return the underlying iterator
    305        */
    306       _Iterator
    307       base() const { return _M_current; }
    308 
    309       /**
    310        * @brief Conversion to underlying non-debug iterator to allow
    311        * better interaction with non-debug containers.
    312        */
    313       operator _Iterator() const { return _M_current; }
    314 
    315       /** Attach iterator to the given sequence. */
    316       void
    317       _M_attach(const _Sequence* __seq)
    318       {
    319 	_Safe_iterator_base::_M_attach(const_cast<_Sequence*>(__seq),
    320 				       _M_constant());
    321       }
    322 
    323       /** Likewise, but not thread-safe. */
    324       void
    325       _M_attach_single(const _Sequence* __seq)
    326       {
    327 	_Safe_iterator_base::_M_attach_single(const_cast<_Sequence*>(__seq),
    328 					      _M_constant());
    329       }
    330 
    331       /** Invalidate the iterator, making it singular. */
    332       void
    333       _M_invalidate();
    334 
    335       /** Likewise, but not thread-safe. */
    336       void
    337       _M_invalidate_single();
    338 
    339       /// Is the iterator dereferenceable?
    340       bool
    341       _M_dereferenceable() const
    342       { return !this->_M_singular() && !_M_is_end(); }
    343 
    344       /// Is the iterator incrementable?
    345       bool
    346       _M_incrementable() const { return this->_M_dereferenceable(); }
    347 
    348       // Is the iterator decrementable?
    349       bool
    350       _M_decrementable() const { return !_M_singular() && !_M_is_begin(); }
    351 
    352       // Can we advance the iterator @p __n steps (@p __n may be negative)
    353       bool
    354       _M_can_advance(const difference_type& __n) const;
    355 
    356       // Is the iterator range [*this, __rhs) valid?
    357       template<typename _Other>
    358         bool
    359         _M_valid_range(const _Safe_iterator<_Other, _Sequence>& __rhs) const;
    360 
    361       // The sequence this iterator references.
    362       const _Sequence*
    363       _M_get_sequence() const
    364       { return static_cast<const _Sequence*>(_M_sequence); }
    365 
    366     /** Determine the distance between two iterators with some known
    367      *	precision.
    368     */
    369     template<typename _Iterator1, typename _Iterator2>
    370       static std::pair<difference_type, _Distance_precision>
    371       _M_get_distance(const _Iterator1& __lhs, const _Iterator2& __rhs)
    372       {
    373         typedef typename std::iterator_traits<_Iterator1>::iterator_category
    374 	  _Category;
    375         return _M_get_distance(__lhs, __rhs, _Category());
    376       }
    377 
    378     template<typename _Iterator1, typename _Iterator2>
    379       static std::pair<difference_type, _Distance_precision>
    380       _M_get_distance(const _Iterator1& __lhs, const _Iterator2& __rhs,
    381 		      std::random_access_iterator_tag)
    382       {
    383         return std::make_pair(__rhs.base() - __lhs.base(), __dp_exact);
    384       }
    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 		    std::forward_iterator_tag)
    390       {
    391         return std::make_pair(__lhs.base() == __rhs.base()? 0 : 1,
    392 			      __dp_equality);
    393       }
    394 
    395       /// Is this iterator equal to the sequence's begin() iterator?
    396       bool _M_is_begin() const
    397       {	return *this == static_cast<const _Sequence*>(_M_sequence)->begin(); }
    398 
    399       /// Is this iterator equal to the sequence's end() iterator?
    400       bool _M_is_end() const
    401       {	return *this == static_cast<const _Sequence*>(_M_sequence)->end(); }
    402     };
    403 
    404   template<typename _IteratorL, typename _IteratorR, typename _Sequence>
    405     inline bool
    406     operator==(const _Safe_iterator<_IteratorL, _Sequence>& __lhs,
    407 	       const _Safe_iterator<_IteratorR, _Sequence>& __rhs)
    408     {
    409       _GLIBCXX_DEBUG_VERIFY(! __lhs._M_singular() && ! __rhs._M_singular(),
    410 			    _M_message(__msg_iter_compare_bad)
    411 			    ._M_iterator(__lhs, "lhs")
    412 			    ._M_iterator(__rhs, "rhs"));
    413       _GLIBCXX_DEBUG_VERIFY(__lhs._M_can_compare(__rhs),
    414 			    _M_message(__msg_compare_different)
    415 			    ._M_iterator(__lhs, "lhs")
    416 			    ._M_iterator(__rhs, "rhs"));
    417       return __lhs.base() == __rhs.base();
    418     }
    419 
    420   template<typename _Iterator, typename _Sequence>
    421     inline bool
    422     operator==(const _Safe_iterator<_Iterator, _Sequence>& __lhs,
    423                const _Safe_iterator<_Iterator, _Sequence>& __rhs)
    424     {
    425       _GLIBCXX_DEBUG_VERIFY(! __lhs._M_singular() && ! __rhs._M_singular(),
    426 			    _M_message(__msg_iter_compare_bad)
    427 			    ._M_iterator(__lhs, "lhs")
    428 			    ._M_iterator(__rhs, "rhs"));
    429       _GLIBCXX_DEBUG_VERIFY(__lhs._M_can_compare(__rhs),
    430 			    _M_message(__msg_compare_different)
    431 			    ._M_iterator(__lhs, "lhs")
    432 			    ._M_iterator(__rhs, "rhs"));
    433       return __lhs.base() == __rhs.base();
    434     }
    435 
    436   template<typename _IteratorL, typename _IteratorR, typename _Sequence>
    437     inline bool
    438     operator!=(const _Safe_iterator<_IteratorL, _Sequence>& __lhs,
    439 	       const _Safe_iterator<_IteratorR, _Sequence>& __rhs)
    440     {
    441       _GLIBCXX_DEBUG_VERIFY(! __lhs._M_singular() && ! __rhs._M_singular(),
    442 			    _M_message(__msg_iter_compare_bad)
    443 			    ._M_iterator(__lhs, "lhs")
    444 			    ._M_iterator(__rhs, "rhs"));
    445       _GLIBCXX_DEBUG_VERIFY(__lhs._M_can_compare(__rhs),
    446 			    _M_message(__msg_compare_different)
    447 			    ._M_iterator(__lhs, "lhs")
    448 			    ._M_iterator(__rhs, "rhs"));
    449       return __lhs.base() != __rhs.base();
    450     }
    451 
    452   template<typename _Iterator, typename _Sequence>
    453     inline bool
    454     operator!=(const _Safe_iterator<_Iterator, _Sequence>& __lhs,
    455                const _Safe_iterator<_Iterator, _Sequence>& __rhs)
    456     {
    457       _GLIBCXX_DEBUG_VERIFY(! __lhs._M_singular() && ! __rhs._M_singular(),
    458 			    _M_message(__msg_iter_compare_bad)
    459 			    ._M_iterator(__lhs, "lhs")
    460 			    ._M_iterator(__rhs, "rhs"));
    461       _GLIBCXX_DEBUG_VERIFY(__lhs._M_can_compare(__rhs),
    462 			    _M_message(__msg_compare_different)
    463 			    ._M_iterator(__lhs, "lhs")
    464 			    ._M_iterator(__rhs, "rhs"));
    465       return __lhs.base() != __rhs.base();
    466     }
    467 
    468   template<typename _IteratorL, typename _IteratorR, typename _Sequence>
    469     inline bool
    470     operator<(const _Safe_iterator<_IteratorL, _Sequence>& __lhs,
    471 	      const _Safe_iterator<_IteratorR, _Sequence>& __rhs)
    472     {
    473       _GLIBCXX_DEBUG_VERIFY(! __lhs._M_singular() && ! __rhs._M_singular(),
    474 			    _M_message(__msg_iter_order_bad)
    475 			    ._M_iterator(__lhs, "lhs")
    476 			    ._M_iterator(__rhs, "rhs"));
    477       _GLIBCXX_DEBUG_VERIFY(__lhs._M_can_compare(__rhs),
    478 			    _M_message(__msg_order_different)
    479 			    ._M_iterator(__lhs, "lhs")
    480 			    ._M_iterator(__rhs, "rhs"));
    481       return __lhs.base() < __rhs.base();
    482     }
    483 
    484   template<typename _Iterator, typename _Sequence>
    485     inline bool
    486     operator<(const _Safe_iterator<_Iterator, _Sequence>& __lhs,
    487 	      const _Safe_iterator<_Iterator, _Sequence>& __rhs)
    488     {
    489       _GLIBCXX_DEBUG_VERIFY(! __lhs._M_singular() && ! __rhs._M_singular(),
    490 			    _M_message(__msg_iter_order_bad)
    491 			    ._M_iterator(__lhs, "lhs")
    492 			    ._M_iterator(__rhs, "rhs"));
    493       _GLIBCXX_DEBUG_VERIFY(__lhs._M_can_compare(__rhs),
    494 			    _M_message(__msg_order_different)
    495 			    ._M_iterator(__lhs, "lhs")
    496 			    ._M_iterator(__rhs, "rhs"));
    497       return __lhs.base() < __rhs.base();
    498     }
    499 
    500   template<typename _IteratorL, typename _IteratorR, typename _Sequence>
    501     inline bool
    502     operator<=(const _Safe_iterator<_IteratorL, _Sequence>& __lhs,
    503 	       const _Safe_iterator<_IteratorR, _Sequence>& __rhs)
    504     {
    505       _GLIBCXX_DEBUG_VERIFY(! __lhs._M_singular() && ! __rhs._M_singular(),
    506 			    _M_message(__msg_iter_order_bad)
    507 			    ._M_iterator(__lhs, "lhs")
    508 			    ._M_iterator(__rhs, "rhs"));
    509       _GLIBCXX_DEBUG_VERIFY(__lhs._M_can_compare(__rhs),
    510 			    _M_message(__msg_order_different)
    511 			    ._M_iterator(__lhs, "lhs")
    512 			    ._M_iterator(__rhs, "rhs"));
    513       return __lhs.base() <= __rhs.base();
    514     }
    515 
    516   template<typename _Iterator, typename _Sequence>
    517     inline bool
    518     operator<=(const _Safe_iterator<_Iterator, _Sequence>& __lhs,
    519                const _Safe_iterator<_Iterator, _Sequence>& __rhs)
    520     {
    521       _GLIBCXX_DEBUG_VERIFY(! __lhs._M_singular() && ! __rhs._M_singular(),
    522 			    _M_message(__msg_iter_order_bad)
    523 			    ._M_iterator(__lhs, "lhs")
    524 			    ._M_iterator(__rhs, "rhs"));
    525       _GLIBCXX_DEBUG_VERIFY(__lhs._M_can_compare(__rhs),
    526 			    _M_message(__msg_order_different)
    527 			    ._M_iterator(__lhs, "lhs")
    528 			    ._M_iterator(__rhs, "rhs"));
    529       return __lhs.base() <= __rhs.base();
    530     }
    531 
    532   template<typename _IteratorL, typename _IteratorR, typename _Sequence>
    533     inline bool
    534     operator>(const _Safe_iterator<_IteratorL, _Sequence>& __lhs,
    535 	      const _Safe_iterator<_IteratorR, _Sequence>& __rhs)
    536     {
    537       _GLIBCXX_DEBUG_VERIFY(! __lhs._M_singular() && ! __rhs._M_singular(),
    538 			    _M_message(__msg_iter_order_bad)
    539 			    ._M_iterator(__lhs, "lhs")
    540 			    ._M_iterator(__rhs, "rhs"));
    541       _GLIBCXX_DEBUG_VERIFY(__lhs._M_can_compare(__rhs),
    542 			    _M_message(__msg_order_different)
    543 			    ._M_iterator(__lhs, "lhs")
    544 			    ._M_iterator(__rhs, "rhs"));
    545       return __lhs.base() > __rhs.base();
    546     }
    547 
    548   template<typename _Iterator, typename _Sequence>
    549     inline bool
    550     operator>(const _Safe_iterator<_Iterator, _Sequence>& __lhs,
    551 	      const _Safe_iterator<_Iterator, _Sequence>& __rhs)
    552     {
    553       _GLIBCXX_DEBUG_VERIFY(! __lhs._M_singular() && ! __rhs._M_singular(),
    554 			    _M_message(__msg_iter_order_bad)
    555 			    ._M_iterator(__lhs, "lhs")
    556 			    ._M_iterator(__rhs, "rhs"));
    557       _GLIBCXX_DEBUG_VERIFY(__lhs._M_can_compare(__rhs),
    558 			    _M_message(__msg_order_different)
    559 			    ._M_iterator(__lhs, "lhs")
    560 			    ._M_iterator(__rhs, "rhs"));
    561       return __lhs.base() > __rhs.base();
    562     }
    563 
    564   template<typename _IteratorL, typename _IteratorR, typename _Sequence>
    565     inline bool
    566     operator>=(const _Safe_iterator<_IteratorL, _Sequence>& __lhs,
    567 	       const _Safe_iterator<_IteratorR, _Sequence>& __rhs)
    568     {
    569       _GLIBCXX_DEBUG_VERIFY(! __lhs._M_singular() && ! __rhs._M_singular(),
    570 			    _M_message(__msg_iter_order_bad)
    571 			    ._M_iterator(__lhs, "lhs")
    572 			    ._M_iterator(__rhs, "rhs"));
    573       _GLIBCXX_DEBUG_VERIFY(__lhs._M_can_compare(__rhs),
    574 			    _M_message(__msg_order_different)
    575 			    ._M_iterator(__lhs, "lhs")
    576 			    ._M_iterator(__rhs, "rhs"));
    577       return __lhs.base() >= __rhs.base();
    578     }
    579 
    580   template<typename _Iterator, typename _Sequence>
    581     inline bool
    582     operator>=(const _Safe_iterator<_Iterator, _Sequence>& __lhs,
    583                const _Safe_iterator<_Iterator, _Sequence>& __rhs)
    584     {
    585       _GLIBCXX_DEBUG_VERIFY(! __lhs._M_singular() && ! __rhs._M_singular(),
    586 			    _M_message(__msg_iter_order_bad)
    587 			    ._M_iterator(__lhs, "lhs")
    588 			    ._M_iterator(__rhs, "rhs"));
    589       _GLIBCXX_DEBUG_VERIFY(__lhs._M_can_compare(__rhs),
    590 			    _M_message(__msg_order_different)
    591 			    ._M_iterator(__lhs, "lhs")
    592 			    ._M_iterator(__rhs, "rhs"));
    593       return __lhs.base() >= __rhs.base();
    594     }
    595 
    596   // _GLIBCXX_RESOLVE_LIB_DEFECTS
    597   // According to the resolution of DR179 not only the various comparison
    598   // operators but also operator- must accept mixed iterator/const_iterator
    599   // parameters.
    600   template<typename _IteratorL, typename _IteratorR, typename _Sequence>
    601     inline typename _Safe_iterator<_IteratorL, _Sequence>::difference_type
    602     operator-(const _Safe_iterator<_IteratorL, _Sequence>& __lhs,
    603 	      const _Safe_iterator<_IteratorR, _Sequence>& __rhs)
    604     {
    605       _GLIBCXX_DEBUG_VERIFY(! __lhs._M_singular() && ! __rhs._M_singular(),
    606 			    _M_message(__msg_distance_bad)
    607 			    ._M_iterator(__lhs, "lhs")
    608 			    ._M_iterator(__rhs, "rhs"));
    609       _GLIBCXX_DEBUG_VERIFY(__lhs._M_can_compare(__rhs),
    610 			    _M_message(__msg_distance_different)
    611 			    ._M_iterator(__lhs, "lhs")
    612 			    ._M_iterator(__rhs, "rhs"));
    613       return __lhs.base() - __rhs.base();
    614     }
    615 
    616    template<typename _Iterator, typename _Sequence>
    617      inline typename _Safe_iterator<_Iterator, _Sequence>::difference_type
    618      operator-(const _Safe_iterator<_Iterator, _Sequence>& __lhs,
    619 	       const _Safe_iterator<_Iterator, _Sequence>& __rhs)
    620      {
    621        _GLIBCXX_DEBUG_VERIFY(! __lhs._M_singular() && ! __rhs._M_singular(),
    622 			     _M_message(__msg_distance_bad)
    623 			     ._M_iterator(__lhs, "lhs")
    624 			     ._M_iterator(__rhs, "rhs"));
    625        _GLIBCXX_DEBUG_VERIFY(__lhs._M_can_compare(__rhs),
    626 			     _M_message(__msg_distance_different)
    627 			     ._M_iterator(__lhs, "lhs")
    628 			     ._M_iterator(__rhs, "rhs"));
    629        return __lhs.base() - __rhs.base();
    630      }
    631 
    632   template<typename _Iterator, typename _Sequence>
    633     inline _Safe_iterator<_Iterator, _Sequence>
    634     operator+(typename _Safe_iterator<_Iterator,_Sequence>::difference_type __n,
    635 	      const _Safe_iterator<_Iterator, _Sequence>& __i)
    636     { return __i + __n; }
    637 } // namespace __gnu_debug
    638 
    639 #ifndef _GLIBCXX_EXPORT_TEMPLATE
    640 #  include <debug/safe_iterator.tcc>
    641 #endif
    642 
    643 #endif
    644