# safe_iterator.h

Go to the documentation of this file.

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