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