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