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