# safe_iterator.h

    00001 // Safe iterator implementation  -*- C++ -*-
    00002
    00003 // Copyright (C) 2003, 2004
    00004 // Free Software Foundation, Inc.
    00005 //
    00006 // This file is part of the GNU ISO C++ Library.  This library is free
    00007 // software; you can redistribute it and/or modify it under the
    00008 // terms of the GNU General Public License as published by the
    00009 // Free Software Foundation; either version 2, or (at your option)
    00010 // any later version.
    00011
    00012 // This library is distributed in the hope that it will be useful,
    00013 // but WITHOUT ANY WARRANTY; without even the implied warranty of
    00014 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    00015 // GNU General Public License for more details.
    00016
    00017 // You should have received a copy of the GNU General Public License along
    00018 // with this library; see the file COPYING.  If not, write to the Free
    00019 // Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307,
    00020 // USA.
    00021
    00022 // As a special exception, you may use this file as part of a free software
    00023 // library without restriction.  Specifically, if other files instantiate
    00024 // templates or use macros or inline functions from this file, or you compile
    00025 // this file and link it with other files to produce an executable, this
    00026 // file does not by itself cause the resulting executable to be covered by
    00027 // the GNU General Public License.  This exception does not however
    00028 // invalidate any other reasons why the executable file might be covered by
    00029 // the GNU General Public License.
    00030
    00031 #ifndef _GLIBCXX_DEBUG_SAFE_ITERATOR_H
    00032 #define _GLIBCXX_DEBUG_SAFE_ITERATOR_H 1
    00033
    00034 #include <bits/stl_pair.h>
    00035 #include <debug/debug.h>
    00036 #include <debug/formatter.h>
    00037 #include <debug/safe_base.h>
    00038 #include <bits/cpp_type_traits.h>
    00039
    00040 namespace __gnu_debug
    00041 {
    00042   using std::iterator_traits;
    00043   using std::pair;
    00044
    00045   /** Iterators that derive from _Safe_iterator_base but that aren't
    00046    *  _Safe_iterators can be determined singular or non-singular via
    00047    *  _Safe_iterator_base.
    00048    */
    00049   inline bool __check_singular_aux(const _Safe_iterator_base* __x)
    00050   { return __x->_M_singular(); }
    00051
    00052   /** \brief Safe iterator wrapper.
    00053    *
    00054    *  The class template %_Safe_iterator is a wrapper around an
    00055    *  iterator that tracks the iterator's movement among sequences and
    00056    *  checks that operations performed on the "safe" iterator are
    00057    *  legal. In additional to the basic iterator operations (which are
    00058    *  validated, and then passed to the underlying iterator),
    00059    *  %_Safe_iterator has member functions for iterator invalidation,
    00060    *  attaching/detaching the iterator from sequences, and querying
    00061    *  the iterator's state.
    00062    */
    00063   template<typename _Iterator, typename _Sequence>
    00064     class _Safe_iterator : public _Safe_iterator_base
    00065     {
    00066       typedef _Safe_iterator _Self;
    00067
    00068       /** The precision to which we can calculate the distance between
    00069        *  two iterators.
    00070        */
    00071       enum _Distance_precision
    00072     {
    00073       __dp_equality, //< Can compare iterator equality, only
    00074       __dp_sign,     //< Can determine equality and ordering
    00075       __dp_exact     //< Can determine distance precisely
    00076     };
    00077
    00078       /// The underlying iterator
    00079       _Iterator _M_current;
    00080
    00081       /// Determine if this is a constant iterator.
    00082       bool
    00083       _M_constant() const
    00084       {
    00085     typedef typename _Sequence::const_iterator const_iterator;
    00086     return __is_same<const_iterator, _Safe_iterator>::value;
    00087       }
    00088
    00089       typedef iterator_traits<_Iterator> _Traits;
    00090
    00091     public:
    00092       typedef _Iterator                           _Base_iterator;
    00093       typedef typename _Traits::iterator_category iterator_category;
    00094       typedef typename _Traits::value_type        value_type;
    00095       typedef typename _Traits::difference_type   difference_type;
    00096       typedef typename _Traits::reference         reference;
    00097       typedef typename _Traits::pointer           pointer;
    00098
    00099       /// @post the iterator is singular and unattached
    00100       _Safe_iterator() : _M_current() { }
    00101
    00102       /**
    00103        * @brief Safe iterator construction from an unsafe iterator and
    00104        * its sequence.
    00105        *
    00106        * @pre @p seq is not NULL
    00107        * @post this is not singular
    00108        */
    00109       _Safe_iterator(const _Iterator& __i, const _Sequence* __seq)
    00110       : _Safe_iterator_base(__seq, _M_constant()), _M_current(__i)
    00111       {
    00112     _GLIBCXX_DEBUG_VERIFY(! this->_M_singular(),
    00113                   _M_message(__msg_init_singular)
    00114                   ._M_iterator(*this, "this"));
    00115       }
    00116
    00117       /**
    00118        * @brief Copy construction.
    00119        * @pre @p x is not singular
    00120        */
    00121       _Safe_iterator(const _Safe_iterator& __x)
    00122       : _Safe_iterator_base(__x, _M_constant()), _M_current(__x._M_current)
    00123       {
    00124     _GLIBCXX_DEBUG_VERIFY(!__x._M_singular(),
    00125                   _M_message(__msg_init_copy_singular)
    00126                   ._M_iterator(*this, "this")
    00127                   ._M_iterator(__x, "other"));
    00128       }
    00129
    00130       /**
    00131        *  @brief Converting constructor from a mutable iterator to a
    00132        *  constant iterator.
    00133        *
    00134        *  @pre @p x is not singular
    00135       */
    00136       template<typename _MutableIterator>
    00137         _Safe_iterator(
    00138           const _Safe_iterator<_MutableIterator,
    00139           typename std::__enable_if<
    00140                      _Sequence,
    00141                      (std::__are_same<_MutableIterator,
    00142                       typename _Sequence::iterator::_Base_iterator>::_M_type)
    00143                    >::_M_type>& __x)
    00144     : _Safe_iterator_base(__x, _M_constant()), _M_current(__x.base())
    00145         {
    00146       _GLIBCXX_DEBUG_VERIFY(!__x._M_singular(),
    00147                 _M_message(__msg_init_const_singular)
    00148                 ._M_iterator(*this, "this")
    00149                 ._M_iterator(__x, "other"));
    00150     }
    00151
    00152       /**
    00153        * @brief Copy assignment.
    00154        * @pre @p x is not singular
    00155        */
    00156       _Safe_iterator&
    00157       operator=(const _Safe_iterator& __x)
    00158       {
    00159     _GLIBCXX_DEBUG_VERIFY(!__x._M_singular(),
    00160                   _M_message(__msg_copy_singular)
    00161                   ._M_iterator(*this, "this")
    00162                   ._M_iterator(__x, "other"));
    00163     _M_current = __x._M_current;
    00164     this->_M_attach(static_cast<_Sequence*>(__x._M_sequence));
    00165     return *this;
    00166       }
    00167
    00168       /**
    00169        *  @brief Iterator dereference.
    00170        *  @pre iterator is dereferenceable
    00171        */
    00172       reference
    00173       operator*() const
    00174       {
    00175
    00176     _GLIBCXX_DEBUG_VERIFY(this->_M_dereferenceable(),
    00177                   _M_message(__msg_bad_deref)
    00178                   ._M_iterator(*this, "this"));
    00179     return *_M_current;
    00180       }
    00181
    00182       /**
    00183        *  @brief Iterator dereference.
    00184        *  @pre iterator is dereferenceable
    00185        *  @todo Make this correct w.r.t. iterators that return proxies
    00186        *  @todo Use addressof() instead of & operator
    00187        */
    00188       pointer
    00189       operator->() const
    00190       {
    00191     _GLIBCXX_DEBUG_VERIFY(this->_M_dereferenceable(),
    00192                   _M_message(__msg_bad_deref)
    00193                   ._M_iterator(*this, "this"));
    00194     return &*_M_current;
    00195       }
    00196
    00197       // ------ Input iterator requirements ------
    00198       /**
    00199        *  @brief Iterator preincrement
    00200        *  @pre iterator is incrementable
    00201        */
    00202       _Safe_iterator&
    00203       operator++()
    00204       {
    00205     _GLIBCXX_DEBUG_VERIFY(this->_M_incrementable(),
    00206                   _M_message(__msg_bad_inc)
    00207                   ._M_iterator(*this, "this"));
    00208     ++_M_current;
    00209     return *this;
    00210       }
    00211
    00212       /**
    00213        *  @brief Iterator postincrement
    00214        *  @pre iterator is incrementable
    00215        */
    00216       _Safe_iterator
    00217       operator++(int)
    00218       {
    00219     _GLIBCXX_DEBUG_VERIFY(this->_M_incrementable(),
    00220                   _M_message(__msg_bad_inc)
    00221                   ._M_iterator(*this, "this"));
    00222     _Safe_iterator __tmp(*this);
    00223     ++_M_current;
    00224     return __tmp;
    00225       }
    00226
    00227       // ------ Bidirectional iterator requirements ------
    00228       /**
    00229        *  @brief Iterator predecrement
    00230        *  @pre iterator is decrementable
    00231        */
    00232       _Safe_iterator&
    00233       operator--()
    00234       {
    00235     _GLIBCXX_DEBUG_VERIFY(this->_M_decrementable(),
    00236                   _M_message(__msg_bad_dec)
    00237                   ._M_iterator(*this, "this"));
    00238     --_M_current;
    00239     return *this;
    00240       }
    00241
    00242       /**
    00243        *  @brief Iterator postdecrement
    00244        *  @pre iterator is decrementable
    00245        */
    00246       _Safe_iterator
    00247       operator--(int)
    00248       {
    00249     _GLIBCXX_DEBUG_VERIFY(this->_M_decrementable(),
    00250                   _M_message(__msg_bad_dec)
    00251                   ._M_iterator(*this, "this"));
    00252     _Safe_iterator __tmp(*this);
    00253     --_M_current;
    00254     return __tmp;
    00255       }
    00256
    00257       // ------ Random access iterator requirements ------
    00258       reference
    00259       operator[](const difference_type& __n) const
    00260       {
    00261     _GLIBCXX_DEBUG_VERIFY(this->_M_can_advance(__n)
    00262                   && this->_M_can_advance(__n+1),
    00263                   _M_message(__msg_iter_subscript_oob)
    00264                   ._M_iterator(*this)._M_integer(__n));
    00265
    00266     return _M_current[__n];
    00267       }
    00268
    00269       _Safe_iterator&
    00270       operator+=(const difference_type& __n)
    00271       {
    00272     _GLIBCXX_DEBUG_VERIFY(this->_M_can_advance(__n),
    00273                   _M_message(__msg_advance_oob)
    00274                   ._M_iterator(*this)._M_integer(__n));
    00275     _M_current += __n;
    00276     return *this;
    00277       }
    00278
    00279       _Safe_iterator
    00280       operator+(const difference_type& __n) const
    00281       {
    00282     _Safe_iterator __tmp(*this);
    00283     __tmp += __n;
    00284     return __tmp;
    00285       }
    00286
    00287       _Safe_iterator&
    00288       operator-=(const difference_type& __n)
    00289       {
    00290     _GLIBCXX_DEBUG_VERIFY(this->_M_can_advance(-__n),
    00291                   _M_message(__msg_retreat_oob)
    00292                   ._M_iterator(*this)._M_integer(__n));
    00293     _M_current += -__n;
    00294     return *this;
    00295       }
    00296
    00297       _Safe_iterator
    00298       operator-(const difference_type& __n) const
    00299       {
    00300     _Safe_iterator __tmp(*this);
    00301     __tmp -= __n;
    00302     return __tmp;
    00303       }
    00304
    00305       // ------ Utilities ------
    00306       /**
    00307        * @brief Return the underlying iterator
    00308        */
    00309       _Iterator
    00310       base() const { return _M_current; }
    00311
    00312       /**
    00313        * @brief Conversion to underlying non-debug iterator to allow
    00314        * better interaction with non-debug containers.
    00315        */
    00316       operator _Iterator() const { return _M_current; }
    00317
    00318       /** Attach iterator to the given sequence. */
    00319       void
    00320       _M_attach(const _Sequence* __seq)
    00321       {
    00322     _Safe_iterator_base::_M_attach(const_cast<_Sequence*>(__seq),
    00323                        _M_constant());
    00324       }
    00325
    00326       /** Invalidate the iterator, making it singular. */
    00327       void
    00328       _M_invalidate();
    00329
    00330       /// Is the iterator dereferenceable?
    00331       bool
    00332       _M_dereferenceable() const
    00333       { return !this->_M_singular() && !_M_is_end(); }
    00334
    00335       /// Is the iterator incrementable?
    00336       bool
    00337       _M_incrementable() const { return this->_M_dereferenceable(); }
    00338
    00339       // Is the iterator decrementable?
    00340       bool
    00341       _M_decrementable() const { return !_M_singular() && !_M_is_begin(); }
    00342
    00343       // Can we advance the iterator @p __n steps (@p __n may be negative)
    00344       bool
    00345       _M_can_advance(const difference_type& __n) const;
    00346
    00347       // Is the iterator range [*this, __rhs) valid?
    00348       template<typename _Other>
    00349         bool
    00350         _M_valid_range(const _Safe_iterator<_Other, _Sequence>& __rhs) const;
    00351
    00352       // The sequence this iterator references.
    00353       const _Sequence*
    00354       _M_get_sequence() const
    00355       { return static_cast<const _Sequence*>(_M_sequence); }
    00356
    00357     /** Determine the distance between two iterators with some known
    00358      *  precision.
    00359     */
    00360     template<typename _Iterator1, typename _Iterator2>
    00361       static pair<difference_type, _Distance_precision>
    00362       _M_get_distance(const _Iterator1& __lhs, const _Iterator2& __rhs)
    00363       {
    00364         typedef typename iterator_traits<_Iterator1>::iterator_category
    00365       _Category;
    00366         return _M_get_distance(__lhs, __rhs, _Category());
    00367       }
    00368
    00369     template<typename _Iterator1, typename _Iterator2>
    00370       static pair<difference_type, _Distance_precision>
    00371       _M_get_distance(const _Iterator1& __lhs, const _Iterator2& __rhs,
    00372               std::random_access_iterator_tag)
    00373       {
    00374         return std::make_pair(__rhs.base() - __lhs.base(), __dp_exact);
    00375       }
    00376
    00377     template<typename _Iterator1, typename _Iterator2>
    00378       static pair<difference_type, _Distance_precision>
    00379       _M_get_distance(const _Iterator1& __lhs, const _Iterator2& __rhs,
    00380             std::forward_iterator_tag)
    00381       {
    00382         return std::make_pair(__lhs.base() == __rhs.base()? 0 : 1,
    00383                   __dp_equality);
    00384       }
    00385
    00386       /// Is this iterator equal to the sequence's begin() iterator?
    00387       bool _M_is_begin() const
    00388       { return *this == static_cast<const _Sequence*>(_M_sequence)->begin(); }
    00389
    00390       /// Is this iterator equal to the sequence's end() iterator?
    00391       bool _M_is_end() const
    00392       { return *this == static_cast<const _Sequence*>(_M_sequence)->end(); }
    00393     };
    00394
    00395   template<typename _IteratorL, typename _IteratorR, typename _Sequence>
    00396     inline bool
    00397     operator==(const _Safe_iterator<_IteratorL, _Sequence>& __lhs,
    00398            const _Safe_iterator<_IteratorR, _Sequence>& __rhs)
    00399     {
    00400       _GLIBCXX_DEBUG_VERIFY(! __lhs._M_singular() && ! __rhs._M_singular(),
    00401                 _M_message(__msg_iter_compare_bad)
    00402                 ._M_iterator(__lhs, "lhs")
    00403                 ._M_iterator(__rhs, "rhs"));
    00404       _GLIBCXX_DEBUG_VERIFY(__lhs._M_can_compare(__rhs),
    00405                 _M_message(__msg_compare_different)
    00406                 ._M_iterator(__lhs, "lhs")
    00407                 ._M_iterator(__rhs, "rhs"));
    00408       return __lhs.base() == __rhs.base();
    00409     }
    00410
    00411   template<typename _Iterator, typename _Sequence>
    00412     inline bool
    00413     operator==(const _Safe_iterator<_Iterator, _Sequence>& __lhs,
    00414                const _Safe_iterator<_Iterator, _Sequence>& __rhs)
    00415     {
    00416       _GLIBCXX_DEBUG_VERIFY(! __lhs._M_singular() && ! __rhs._M_singular(),
    00417                 _M_message(__msg_iter_compare_bad)
    00418                 ._M_iterator(__lhs, "lhs")
    00419                 ._M_iterator(__rhs, "rhs"));
    00420       _GLIBCXX_DEBUG_VERIFY(__lhs._M_can_compare(__rhs),
    00421                 _M_message(__msg_compare_different)
    00422                 ._M_iterator(__lhs, "lhs")
    00423                 ._M_iterator(__rhs, "rhs"));
    00424       return __lhs.base() == __rhs.base();
    00425     }
    00426
    00427   template<typename _IteratorL, typename _IteratorR, typename _Sequence>
    00428     inline bool
    00429     operator!=(const _Safe_iterator<_IteratorL, _Sequence>& __lhs,
    00430            const _Safe_iterator<_IteratorR, _Sequence>& __rhs)
    00431     {
    00432       _GLIBCXX_DEBUG_VERIFY(! __lhs._M_singular() && ! __rhs._M_singular(),
    00433                 _M_message(__msg_iter_compare_bad)
    00434                 ._M_iterator(__lhs, "lhs")
    00435                 ._M_iterator(__rhs, "rhs"));
    00436       _GLIBCXX_DEBUG_VERIFY(__lhs._M_can_compare(__rhs),
    00437                 _M_message(__msg_compare_different)
    00438                 ._M_iterator(__lhs, "lhs")
    00439                 ._M_iterator(__rhs, "rhs"));
    00440       return __lhs.base() != __rhs.base();
    00441     }
    00442
    00443   template<typename _Iterator, typename _Sequence>
    00444     inline bool
    00445     operator!=(const _Safe_iterator<_Iterator, _Sequence>& __lhs,
    00446                const _Safe_iterator<_Iterator, _Sequence>& __rhs)
    00447     {
    00448       _GLIBCXX_DEBUG_VERIFY(! __lhs._M_singular() && ! __rhs._M_singular(),
    00449                 _M_message(__msg_iter_compare_bad)
    00450                 ._M_iterator(__lhs, "lhs")
    00451                 ._M_iterator(__rhs, "rhs"));
    00452       _GLIBCXX_DEBUG_VERIFY(__lhs._M_can_compare(__rhs),
    00453                 _M_message(__msg_compare_different)
    00454                 ._M_iterator(__lhs, "lhs")
    00455                 ._M_iterator(__rhs, "rhs"));
    00456       return __lhs.base() != __rhs.base();
    00457     }
    00458
    00459   template<typename _IteratorL, typename _IteratorR, typename _Sequence>
    00460     inline bool
    00461     operator<(const _Safe_iterator<_IteratorL, _Sequence>& __lhs,
    00462           const _Safe_iterator<_IteratorR, _Sequence>& __rhs)
    00463     {
    00464       _GLIBCXX_DEBUG_VERIFY(! __lhs._M_singular() && ! __rhs._M_singular(),
    00465                 _M_message(__msg_iter_order_bad)
    00466                 ._M_iterator(__lhs, "lhs")
    00467                 ._M_iterator(__rhs, "rhs"));
    00468       _GLIBCXX_DEBUG_VERIFY(__lhs._M_can_compare(__rhs),
    00469                 _M_message(__msg_order_different)
    00470                 ._M_iterator(__lhs, "lhs")
    00471                 ._M_iterator(__rhs, "rhs"));
    00472       return __lhs.base() < __rhs.base();
    00473     }
    00474
    00475   template<typename _Iterator, typename _Sequence>
    00476     inline bool
    00477     operator<(const _Safe_iterator<_Iterator, _Sequence>& __lhs,
    00478           const _Safe_iterator<_Iterator, _Sequence>& __rhs)
    00479     {
    00480       _GLIBCXX_DEBUG_VERIFY(! __lhs._M_singular() && ! __rhs._M_singular(),
    00481                 _M_message(__msg_iter_order_bad)
    00482                 ._M_iterator(__lhs, "lhs")
    00483                 ._M_iterator(__rhs, "rhs"));
    00484       _GLIBCXX_DEBUG_VERIFY(__lhs._M_can_compare(__rhs),
    00485                 _M_message(__msg_order_different)
    00486                 ._M_iterator(__lhs, "lhs")
    00487                 ._M_iterator(__rhs, "rhs"));
    00488       return __lhs.base() < __rhs.base();
    00489     }
    00490
    00491   template<typename _IteratorL, typename _IteratorR, typename _Sequence>
    00492     inline bool
    00493     operator<=(const _Safe_iterator<_IteratorL, _Sequence>& __lhs,
    00494            const _Safe_iterator<_IteratorR, _Sequence>& __rhs)
    00495     {
    00496       _GLIBCXX_DEBUG_VERIFY(! __lhs._M_singular() && ! __rhs._M_singular(),
    00497                 _M_message(__msg_iter_order_bad)
    00498                 ._M_iterator(__lhs, "lhs")
    00499                 ._M_iterator(__rhs, "rhs"));
    00500       _GLIBCXX_DEBUG_VERIFY(__lhs._M_can_compare(__rhs),
    00501                 _M_message(__msg_order_different)
    00502                 ._M_iterator(__lhs, "lhs")
    00503                 ._M_iterator(__rhs, "rhs"));
    00504       return __lhs.base() <= __rhs.base();
    00505     }
    00506
    00507   template<typename _Iterator, typename _Sequence>
    00508     inline bool
    00509     operator<=(const _Safe_iterator<_Iterator, _Sequence>& __lhs,
    00510                const _Safe_iterator<_Iterator, _Sequence>& __rhs)
    00511     {
    00512       _GLIBCXX_DEBUG_VERIFY(! __lhs._M_singular() && ! __rhs._M_singular(),
    00513                 _M_message(__msg_iter_order_bad)
    00514                 ._M_iterator(__lhs, "lhs")
    00515                 ._M_iterator(__rhs, "rhs"));
    00516       _GLIBCXX_DEBUG_VERIFY(__lhs._M_can_compare(__rhs),
    00517                 _M_message(__msg_order_different)
    00518                 ._M_iterator(__lhs, "lhs")
    00519                 ._M_iterator(__rhs, "rhs"));
    00520       return __lhs.base() <= __rhs.base();
    00521     }
    00522
    00523   template<typename _IteratorL, typename _IteratorR, typename _Sequence>
    00524     inline bool
    00525     operator>(const _Safe_iterator<_IteratorL, _Sequence>& __lhs,
    00526           const _Safe_iterator<_IteratorR, _Sequence>& __rhs)
    00527     {
    00528       _GLIBCXX_DEBUG_VERIFY(! __lhs._M_singular() && ! __rhs._M_singular(),
    00529                 _M_message(__msg_iter_order_bad)
    00530                 ._M_iterator(__lhs, "lhs")
    00531                 ._M_iterator(__rhs, "rhs"));
    00532       _GLIBCXX_DEBUG_VERIFY(__lhs._M_can_compare(__rhs),
    00533                 _M_message(__msg_order_different)
    00534                 ._M_iterator(__lhs, "lhs")
    00535                 ._M_iterator(__rhs, "rhs"));
    00536       return __lhs.base() > __rhs.base();
    00537     }
    00538
    00539   template<typename _Iterator, typename _Sequence>
    00540     inline bool
    00541     operator>(const _Safe_iterator<_Iterator, _Sequence>& __lhs,
    00542           const _Safe_iterator<_Iterator, _Sequence>& __rhs)
    00543     {
    00544       _GLIBCXX_DEBUG_VERIFY(! __lhs._M_singular() && ! __rhs._M_singular(),
    00545                 _M_message(__msg_iter_order_bad)
    00546                 ._M_iterator(__lhs, "lhs")
    00547                 ._M_iterator(__rhs, "rhs"));
    00548       _GLIBCXX_DEBUG_VERIFY(__lhs._M_can_compare(__rhs),
    00549                 _M_message(__msg_order_different)
    00550                 ._M_iterator(__lhs, "lhs")
    00551                 ._M_iterator(__rhs, "rhs"));
    00552       return __lhs.base() > __rhs.base();
    00553     }
    00554
    00555   template<typename _IteratorL, typename _IteratorR, typename _Sequence>
    00556     inline bool
    00557     operator>=(const _Safe_iterator<_IteratorL, _Sequence>& __lhs,
    00558            const _Safe_iterator<_IteratorR, _Sequence>& __rhs)
    00559     {
    00560       _GLIBCXX_DEBUG_VERIFY(! __lhs._M_singular() && ! __rhs._M_singular(),
    00561                 _M_message(__msg_iter_order_bad)
    00562                 ._M_iterator(__lhs, "lhs")
    00563                 ._M_iterator(__rhs, "rhs"));
    00564       _GLIBCXX_DEBUG_VERIFY(__lhs._M_can_compare(__rhs),
    00565                 _M_message(__msg_order_different)
    00566                 ._M_iterator(__lhs, "lhs")
    00567                 ._M_iterator(__rhs, "rhs"));
    00568       return __lhs.base() >= __rhs.base();
    00569     }
    00570
    00571   template<typename _Iterator, typename _Sequence>
    00572     inline bool
    00573     operator>=(const _Safe_iterator<_Iterator, _Sequence>& __lhs,
    00574                const _Safe_iterator<_Iterator, _Sequence>& __rhs)
    00575     {
    00576       _GLIBCXX_DEBUG_VERIFY(! __lhs._M_singular() && ! __rhs._M_singular(),
    00577                 _M_message(__msg_iter_order_bad)
    00578                 ._M_iterator(__lhs, "lhs")
    00579                 ._M_iterator(__rhs, "rhs"));
    00580       _GLIBCXX_DEBUG_VERIFY(__lhs._M_can_compare(__rhs),
    00581                 _M_message(__msg_order_different)
    00582                 ._M_iterator(__lhs, "lhs")
    00583                 ._M_iterator(__rhs, "rhs"));
    00584       return __lhs.base() >= __rhs.base();
    00585     }
    00586
    00587   // _GLIBCXX_RESOLVE_LIB_DEFECTS
    00588   // According to the resolution of DR179 not only the various comparison
    00589   // operators but also operator- must accept mixed iterator/const_iterator
    00590   // parameters.
    00591   template<typename _IteratorL, typename _IteratorR, typename _Sequence>
    00592     inline typename _Safe_iterator<_IteratorL, _Sequence>::difference_type
    00593     operator-(const _Safe_iterator<_IteratorL, _Sequence>& __lhs,
    00594           const _Safe_iterator<_IteratorR, _Sequence>& __rhs)
    00595     {
    00596       _GLIBCXX_DEBUG_VERIFY(! __lhs._M_singular() && ! __rhs._M_singular(),
    00597                 _M_message(__msg_distance_bad)
    00598                 ._M_iterator(__lhs, "lhs")
    00599                 ._M_iterator(__rhs, "rhs"));
    00600       _GLIBCXX_DEBUG_VERIFY(__lhs._M_can_compare(__rhs),
    00601                 _M_message(__msg_distance_different)
    00602                 ._M_iterator(__lhs, "lhs")
    00603                 ._M_iterator(__rhs, "rhs"));
    00604       return __lhs.base() - __rhs.base();
    00605     }
    00606
    00607   template<typename _Iterator, typename _Sequence>
    00608     inline _Safe_iterator<_Iterator, _Sequence>
    00609     operator+(typename _Safe_iterator<_Iterator,_Sequence>::difference_type __n,
    00610           const _Safe_iterator<_Iterator, _Sequence>& __i)
    00611     { return __i + __n; }
    00612 } // namespace __gnu_debug
    00613
    00614 #ifndef _GLIBCXX_EXPORT_TEMPLATE
    00615 #  include <debug/safe_iterator.tcc>
    00616 #endif
    00617
    00618 #endif