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