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