libstdc++
safe_iterator.h
Go to the documentation of this file.
00001 // Safe iterator implementation  -*- C++ -*-
00002 
00003 // Copyright (C) 2003-2014 Free Software Foundation, Inc.
00004 //
00005 // This file is part of the GNU ISO C++ Library.  This library is free
00006 // software; you can redistribute it and/or modify it under the
00007 // terms of the GNU General Public License as published by the
00008 // Free Software Foundation; either version 3, or (at your option)
00009 // any later version.
00010 
00011 // This library is distributed in the hope that it will be useful,
00012 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00013 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00014 // GNU General Public License for more details.
00015 
00016 // Under Section 7 of GPL version 3, you are granted additional
00017 // permissions described in the GCC Runtime Library Exception, version
00018 // 3.1, as published by the Free Software Foundation.
00019 
00020 // You should have received a copy of the GNU General Public License and
00021 // a copy of the GCC Runtime Library Exception along with this program;
00022 // see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
00023 // <http://www.gnu.org/licenses/>.
00024 
00025 /** @file debug/safe_iterator.h
00026  *  This file is a GNU debug extension to the Standard C++ Library.
00027  */
00028 
00029 #ifndef _GLIBCXX_DEBUG_SAFE_ITERATOR_H
00030 #define _GLIBCXX_DEBUG_SAFE_ITERATOR_H 1
00031 
00032 #include <debug/debug.h>
00033 #include <debug/macros.h>
00034 #include <debug/functions.h>
00035 #include <debug/safe_base.h>
00036 #include <bits/stl_pair.h>
00037 #include <ext/type_traits.h>
00038 
00039 namespace __gnu_debug
00040 {
00041   /** Helper struct to deal with sequence offering a before_begin
00042    *  iterator.
00043    **/
00044   template <typename _Sequence>
00045     struct _BeforeBeginHelper
00046     {
00047       template<typename _Iterator>
00048     static bool
00049     _S_Is(const _Safe_iterator<_Iterator, _Sequence>&)
00050     { return false; }
00051 
00052       template<typename _Iterator>
00053     static bool
00054     _S_Is_Beginnest(const _Safe_iterator<_Iterator, _Sequence>& __it)
00055     { return __it.base() == __it._M_get_sequence()->_M_base().begin(); }
00056     };
00057 
00058   /** Iterators that derive from _Safe_iterator_base can be determined singular
00059    *  or non-singular.
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 _Iterator>
00079     inline std::pair<typename std::iterator_traits<_Iterator>::difference_type,
00080              _Distance_precision>
00081     __get_distance(const _Iterator& __lhs, const _Iterator& __rhs,
00082            std::random_access_iterator_tag)
00083     { return std::make_pair(__rhs - __lhs, __dp_exact); }
00084 
00085   template<typename _Iterator>
00086     inline std::pair<typename std::iterator_traits<_Iterator>::difference_type,
00087              _Distance_precision>
00088     __get_distance(const _Iterator& __lhs, const _Iterator& __rhs,
00089            std::forward_iterator_tag)
00090     { return std::make_pair(__lhs == __rhs? 0 : 1, __dp_equality); }
00091 
00092   template<typename _Iterator>
00093     inline std::pair<typename std::iterator_traits<_Iterator>::difference_type,
00094              _Distance_precision>
00095     __get_distance(const _Iterator& __lhs, const _Iterator& __rhs)
00096     {
00097       typedef typename std::iterator_traits<_Iterator>::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       typedef typename _Sequence::const_iterator _Const_iterator;
00118 
00119       /// The underlying iterator
00120       _Iterator _M_current;
00121 
00122       /// Determine if this is a constant iterator.
00123       bool
00124       _M_constant() const
00125       { return std::__are_same<_Const_iterator, _Safe_iterator>::__value; }
00126 
00127       typedef std::iterator_traits<_Iterator> _Traits;
00128 
00129     public:
00130       typedef _Iterator                           iterator_type;
00131       typedef typename _Traits::iterator_category iterator_category;
00132       typedef typename _Traits::value_type        value_type;
00133       typedef typename _Traits::difference_type   difference_type;
00134       typedef typename _Traits::reference         reference;
00135       typedef typename _Traits::pointer           pointer;
00136 
00137       /// @post the iterator is singular and unattached
00138       _Safe_iterator() _GLIBCXX_NOEXCEPT : _M_current() { }
00139 
00140       /**
00141        * @brief Safe iterator construction from an unsafe iterator and
00142        * its sequence.
00143        *
00144        * @pre @p seq is not NULL
00145        * @post this is not singular
00146        */
00147       _Safe_iterator(const _Iterator& __i, const _Sequence* __seq)
00148       _GLIBCXX_NOEXCEPT
00149       : _Safe_iterator_base(__seq, _M_constant()), _M_current(__i)
00150       {
00151     _GLIBCXX_DEBUG_VERIFY(! this->_M_singular(),
00152                   _M_message(__msg_init_singular)
00153                   ._M_iterator(*this, "this"));
00154       }
00155 
00156       /**
00157        * @brief Copy construction.
00158        */
00159       _Safe_iterator(const _Safe_iterator& __x) _GLIBCXX_NOEXCEPT
00160       : _Safe_iterator_base(__x, _M_constant()), _M_current(__x._M_current)
00161       {
00162     // _GLIBCXX_RESOLVE_LIB_DEFECTS
00163     // DR 408. Is vector<reverse_iterator<char*> > forbidden?
00164     _GLIBCXX_DEBUG_VERIFY(!__x._M_singular()
00165                   || __x._M_current == _Iterator(),
00166                   _M_message(__msg_init_copy_singular)
00167                   ._M_iterator(*this, "this")
00168                   ._M_iterator(__x, "other"));
00169       }
00170 
00171 #if __cplusplus >= 201103L
00172       /**
00173        * @brief Move construction.
00174        * @post __x is singular and unattached
00175        */
00176       _Safe_iterator(_Safe_iterator&& __x) noexcept : _M_current()
00177       {
00178     _GLIBCXX_DEBUG_VERIFY(!__x._M_singular()
00179                   || __x._M_current == _Iterator(),
00180                   _M_message(__msg_init_copy_singular)
00181                   ._M_iterator(*this, "this")
00182                   ._M_iterator(__x, "other"));
00183     std::swap(_M_current, __x._M_current);
00184     this->_M_attach(__x._M_sequence);
00185     __x._M_detach();
00186       }
00187 #endif
00188 
00189       /**
00190        *  @brief Converting constructor from a mutable iterator to a
00191        *  constant iterator.
00192       */
00193       template<typename _MutableIterator>
00194         _Safe_iterator(
00195           const _Safe_iterator<_MutableIterator,
00196           typename __gnu_cxx::__enable_if<(std::__are_same<_MutableIterator,
00197                       typename _Sequence::iterator::iterator_type>::__value),
00198                    _Sequence>::__type>& __x) _GLIBCXX_NOEXCEPT
00199     : _Safe_iterator_base(__x, _M_constant()), _M_current(__x.base())
00200         {
00201       // _GLIBCXX_RESOLVE_LIB_DEFECTS
00202       // DR 408. Is vector<reverse_iterator<char*> > forbidden?
00203       _GLIBCXX_DEBUG_VERIFY(!__x._M_singular()
00204                 || __x.base() == _Iterator(),
00205                 _M_message(__msg_init_const_singular)
00206                 ._M_iterator(*this, "this")
00207                 ._M_iterator(__x, "other"));
00208     }
00209 
00210       /**
00211        * @brief Copy assignment.
00212        */
00213       _Safe_iterator&
00214       operator=(const _Safe_iterator& __x) _GLIBCXX_NOEXCEPT
00215       {
00216     // _GLIBCXX_RESOLVE_LIB_DEFECTS
00217     // DR 408. Is vector<reverse_iterator<char*> > forbidden?
00218     _GLIBCXX_DEBUG_VERIFY(!__x._M_singular()
00219                   || __x._M_current == _Iterator(),
00220                   _M_message(__msg_copy_singular)
00221                   ._M_iterator(*this, "this")
00222                   ._M_iterator(__x, "other"));
00223     _M_current = __x._M_current;
00224     this->_M_attach(__x._M_sequence);
00225     return *this;
00226       }
00227 
00228 #if __cplusplus >= 201103L
00229       /**
00230        * @brief Move assignment.
00231        * @post __x is singular and unattached
00232        */
00233       _Safe_iterator&
00234       operator=(_Safe_iterator&& __x) noexcept
00235       {
00236     _GLIBCXX_DEBUG_VERIFY(this != &__x,
00237                   _M_message(__msg_self_move_assign)
00238                   ._M_iterator(*this, "this"));
00239     _GLIBCXX_DEBUG_VERIFY(!__x._M_singular()
00240                   || __x._M_current == _Iterator(),
00241                   _M_message(__msg_copy_singular)
00242                   ._M_iterator(*this, "this")
00243                   ._M_iterator(__x, "other"));
00244     _M_current = __x._M_current;
00245     _M_attach(__x._M_sequence);
00246     __x._M_detach();
00247     __x._M_current = _Iterator();
00248     return *this;
00249       }
00250 #endif
00251 
00252       /**
00253        *  @brief Iterator dereference.
00254        *  @pre iterator is dereferenceable
00255        */
00256       reference
00257       operator*() const _GLIBCXX_NOEXCEPT
00258       {
00259     _GLIBCXX_DEBUG_VERIFY(this->_M_dereferenceable(),
00260                   _M_message(__msg_bad_deref)
00261                   ._M_iterator(*this, "this"));
00262     return *_M_current;
00263       }
00264 
00265       /**
00266        *  @brief Iterator dereference.
00267        *  @pre iterator is dereferenceable
00268        *  @todo Make this correct w.r.t. iterators that return proxies
00269        */
00270       pointer
00271       operator->() const _GLIBCXX_NOEXCEPT
00272       {
00273     _GLIBCXX_DEBUG_VERIFY(this->_M_dereferenceable(),
00274                   _M_message(__msg_bad_deref)
00275                   ._M_iterator(*this, "this"));
00276     return std::__addressof(*_M_current);
00277       }
00278 
00279       // ------ Input iterator requirements ------
00280       /**
00281        *  @brief Iterator preincrement
00282        *  @pre iterator is incrementable
00283        */
00284       _Safe_iterator&
00285       operator++() _GLIBCXX_NOEXCEPT
00286       {
00287     _GLIBCXX_DEBUG_VERIFY(this->_M_incrementable(),
00288                   _M_message(__msg_bad_inc)
00289                   ._M_iterator(*this, "this"));
00290     ++_M_current;
00291     return *this;
00292       }
00293 
00294       /**
00295        *  @brief Iterator postincrement
00296        *  @pre iterator is incrementable
00297        */
00298       _Safe_iterator
00299       operator++(int) _GLIBCXX_NOEXCEPT
00300       {
00301     _GLIBCXX_DEBUG_VERIFY(this->_M_incrementable(),
00302                   _M_message(__msg_bad_inc)
00303                   ._M_iterator(*this, "this"));
00304     _Safe_iterator __tmp(*this);
00305     ++_M_current;
00306     return __tmp;
00307       }
00308 
00309       // ------ Bidirectional iterator requirements ------
00310       /**
00311        *  @brief Iterator predecrement
00312        *  @pre iterator is decrementable
00313        */
00314       _Safe_iterator&
00315       operator--() _GLIBCXX_NOEXCEPT
00316       {
00317     _GLIBCXX_DEBUG_VERIFY(this->_M_decrementable(),
00318                   _M_message(__msg_bad_dec)
00319                   ._M_iterator(*this, "this"));
00320     --_M_current;
00321     return *this;
00322       }
00323 
00324       /**
00325        *  @brief Iterator postdecrement
00326        *  @pre iterator is decrementable
00327        */
00328       _Safe_iterator
00329       operator--(int) _GLIBCXX_NOEXCEPT
00330       {
00331     _GLIBCXX_DEBUG_VERIFY(this->_M_decrementable(),
00332                   _M_message(__msg_bad_dec)
00333                   ._M_iterator(*this, "this"));
00334     _Safe_iterator __tmp(*this);
00335     --_M_current;
00336     return __tmp;
00337       }
00338 
00339       // ------ Random access iterator requirements ------
00340       reference
00341       operator[](const difference_type& __n) const _GLIBCXX_NOEXCEPT
00342       {
00343     _GLIBCXX_DEBUG_VERIFY(this->_M_can_advance(__n)
00344                   && this->_M_can_advance(__n+1),
00345                   _M_message(__msg_iter_subscript_oob)
00346                   ._M_iterator(*this)._M_integer(__n));
00347 
00348     return _M_current[__n];
00349       }
00350 
00351       _Safe_iterator&
00352       operator+=(const difference_type& __n) _GLIBCXX_NOEXCEPT
00353       {
00354     _GLIBCXX_DEBUG_VERIFY(this->_M_can_advance(__n),
00355                   _M_message(__msg_advance_oob)
00356                   ._M_iterator(*this)._M_integer(__n));
00357     _M_current += __n;
00358     return *this;
00359       }
00360 
00361       _Safe_iterator
00362       operator+(const difference_type& __n) const _GLIBCXX_NOEXCEPT
00363       {
00364     _Safe_iterator __tmp(*this);
00365     __tmp += __n;
00366     return __tmp;
00367       }
00368 
00369       _Safe_iterator&
00370       operator-=(const difference_type& __n) _GLIBCXX_NOEXCEPT
00371       {
00372     _GLIBCXX_DEBUG_VERIFY(this->_M_can_advance(-__n),
00373                   _M_message(__msg_retreat_oob)
00374                   ._M_iterator(*this)._M_integer(__n));
00375     _M_current += -__n;
00376     return *this;
00377       }
00378 
00379       _Safe_iterator
00380       operator-(const difference_type& __n) const _GLIBCXX_NOEXCEPT
00381       {
00382     _Safe_iterator __tmp(*this);
00383     __tmp -= __n;
00384     return __tmp;
00385       }
00386 
00387       // ------ Utilities ------
00388       /**
00389        * @brief Return the underlying iterator
00390        */
00391       _Iterator
00392       base() const _GLIBCXX_NOEXCEPT { return _M_current; }
00393 
00394       /**
00395        * @brief Conversion to underlying non-debug iterator to allow
00396        * better interaction with non-debug containers.
00397        */
00398       operator _Iterator() const _GLIBCXX_NOEXCEPT { return _M_current; }
00399 
00400       /** Attach iterator to the given sequence. */
00401       void
00402       _M_attach(_Safe_sequence_base* __seq)
00403       {
00404     _Safe_iterator_base::_M_attach(__seq, _M_constant());
00405       }
00406 
00407       /** Likewise, but not thread-safe. */
00408       void
00409       _M_attach_single(_Safe_sequence_base* __seq)
00410       {
00411     _Safe_iterator_base::_M_attach_single(__seq, _M_constant());
00412       }
00413 
00414       /// Is the iterator dereferenceable?
00415       bool
00416       _M_dereferenceable() const
00417       { return !this->_M_singular() && !_M_is_end() && !_M_is_before_begin(); }
00418 
00419       /// Is the iterator before a dereferenceable one?
00420       bool
00421       _M_before_dereferenceable() const
00422       {
00423     if (this->_M_incrementable())
00424     {
00425       _Iterator __base = base();
00426       return ++__base != _M_get_sequence()->_M_base().end();
00427     }
00428     return false;
00429       }
00430 
00431       /// Is the iterator incrementable?
00432       bool
00433       _M_incrementable() const
00434       { return !this->_M_singular() && !_M_is_end(); }
00435 
00436       // Is the iterator decrementable?
00437       bool
00438       _M_decrementable() const { return !_M_singular() && !_M_is_begin(); }
00439 
00440       // Can we advance the iterator @p __n steps (@p __n may be negative)
00441       bool
00442       _M_can_advance(const difference_type& __n) const;
00443 
00444       // Is the iterator range [*this, __rhs) valid?
00445       bool
00446       _M_valid_range(const _Safe_iterator& __rhs) const;
00447 
00448       // The sequence this iterator references.
00449       typename
00450       __gnu_cxx::__conditional_type<std::__are_same<_Const_iterator,
00451                             _Safe_iterator>::__value,
00452                     const _Sequence*,
00453                     _Sequence*>::__type
00454       _M_get_sequence() const
00455       { return static_cast<_Sequence*>(_M_sequence); }
00456 
00457       /// Is this iterator equal to the sequence's begin() iterator?
00458       bool
00459       _M_is_begin() const
00460       { return base() == _M_get_sequence()->_M_base().begin(); }
00461 
00462       /// Is this iterator equal to the sequence's end() iterator?
00463       bool
00464       _M_is_end() const
00465       { return base() == _M_get_sequence()->_M_base().end(); }
00466 
00467       /// Is this iterator equal to the sequence's before_begin() iterator if
00468       /// any?
00469       bool
00470       _M_is_before_begin() const
00471       { return _BeforeBeginHelper<_Sequence>::_S_Is(*this); }
00472 
00473       /// Is this iterator equal to the sequence's before_begin() iterator if
00474       /// any or begin() otherwise?
00475       bool
00476       _M_is_beginnest() const
00477       { return _BeforeBeginHelper<_Sequence>::_S_Is_Beginnest(*this); }
00478     };
00479 
00480   template<typename _IteratorL, typename _IteratorR, typename _Sequence>
00481     inline bool
00482     operator==(const _Safe_iterator<_IteratorL, _Sequence>& __lhs,
00483            const _Safe_iterator<_IteratorR, _Sequence>& __rhs)
00484     _GLIBCXX_NOEXCEPT
00485     {
00486       _GLIBCXX_DEBUG_VERIFY(! __lhs._M_singular() && ! __rhs._M_singular(),
00487                 _M_message(__msg_iter_compare_bad)
00488                 ._M_iterator(__lhs, "lhs")
00489                 ._M_iterator(__rhs, "rhs"));
00490       _GLIBCXX_DEBUG_VERIFY(__lhs._M_can_compare(__rhs),
00491                 _M_message(__msg_compare_different)
00492                 ._M_iterator(__lhs, "lhs")
00493                 ._M_iterator(__rhs, "rhs"));
00494       return __lhs.base() == __rhs.base();
00495     }
00496 
00497   template<typename _Iterator, typename _Sequence>
00498     inline bool
00499     operator==(const _Safe_iterator<_Iterator, _Sequence>& __lhs,
00500                const _Safe_iterator<_Iterator, _Sequence>& __rhs)
00501     _GLIBCXX_NOEXCEPT
00502     {
00503       _GLIBCXX_DEBUG_VERIFY(! __lhs._M_singular() && ! __rhs._M_singular(),
00504                 _M_message(__msg_iter_compare_bad)
00505                 ._M_iterator(__lhs, "lhs")
00506                 ._M_iterator(__rhs, "rhs"));
00507       _GLIBCXX_DEBUG_VERIFY(__lhs._M_can_compare(__rhs),
00508                 _M_message(__msg_compare_different)
00509                 ._M_iterator(__lhs, "lhs")
00510                 ._M_iterator(__rhs, "rhs"));
00511       return __lhs.base() == __rhs.base();
00512     }
00513 
00514   template<typename _IteratorL, typename _IteratorR, typename _Sequence>
00515     inline bool
00516     operator!=(const _Safe_iterator<_IteratorL, _Sequence>& __lhs,
00517            const _Safe_iterator<_IteratorR, _Sequence>& __rhs)
00518     _GLIBCXX_NOEXCEPT
00519     {
00520       _GLIBCXX_DEBUG_VERIFY(! __lhs._M_singular() && ! __rhs._M_singular(),
00521                 _M_message(__msg_iter_compare_bad)
00522                 ._M_iterator(__lhs, "lhs")
00523                 ._M_iterator(__rhs, "rhs"));
00524       _GLIBCXX_DEBUG_VERIFY(__lhs._M_can_compare(__rhs),
00525                 _M_message(__msg_compare_different)
00526                 ._M_iterator(__lhs, "lhs")
00527                 ._M_iterator(__rhs, "rhs"));
00528       return __lhs.base() != __rhs.base();
00529     }
00530 
00531   template<typename _Iterator, typename _Sequence>
00532     inline bool
00533     operator!=(const _Safe_iterator<_Iterator, _Sequence>& __lhs,
00534                const _Safe_iterator<_Iterator, _Sequence>& __rhs)
00535     _GLIBCXX_NOEXCEPT
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     _GLIBCXX_NOEXCEPT
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     _GLIBCXX_NOEXCEPT
00570     {
00571       _GLIBCXX_DEBUG_VERIFY(! __lhs._M_singular() && ! __rhs._M_singular(),
00572                 _M_message(__msg_iter_order_bad)
00573                 ._M_iterator(__lhs, "lhs")
00574                 ._M_iterator(__rhs, "rhs"));
00575       _GLIBCXX_DEBUG_VERIFY(__lhs._M_can_compare(__rhs),
00576                 _M_message(__msg_order_different)
00577                 ._M_iterator(__lhs, "lhs")
00578                 ._M_iterator(__rhs, "rhs"));
00579       return __lhs.base() < __rhs.base();
00580     }
00581 
00582   template<typename _IteratorL, typename _IteratorR, typename _Sequence>
00583     inline bool
00584     operator<=(const _Safe_iterator<_IteratorL, _Sequence>& __lhs,
00585            const _Safe_iterator<_IteratorR, _Sequence>& __rhs)
00586     _GLIBCXX_NOEXCEPT
00587     {
00588       _GLIBCXX_DEBUG_VERIFY(! __lhs._M_singular() && ! __rhs._M_singular(),
00589                 _M_message(__msg_iter_order_bad)
00590                 ._M_iterator(__lhs, "lhs")
00591                 ._M_iterator(__rhs, "rhs"));
00592       _GLIBCXX_DEBUG_VERIFY(__lhs._M_can_compare(__rhs),
00593                 _M_message(__msg_order_different)
00594                 ._M_iterator(__lhs, "lhs")
00595                 ._M_iterator(__rhs, "rhs"));
00596       return __lhs.base() <= __rhs.base();
00597     }
00598 
00599   template<typename _Iterator, typename _Sequence>
00600     inline bool
00601     operator<=(const _Safe_iterator<_Iterator, _Sequence>& __lhs,
00602                const _Safe_iterator<_Iterator, _Sequence>& __rhs)
00603     _GLIBCXX_NOEXCEPT
00604     {
00605       _GLIBCXX_DEBUG_VERIFY(! __lhs._M_singular() && ! __rhs._M_singular(),
00606                 _M_message(__msg_iter_order_bad)
00607                 ._M_iterator(__lhs, "lhs")
00608                 ._M_iterator(__rhs, "rhs"));
00609       _GLIBCXX_DEBUG_VERIFY(__lhs._M_can_compare(__rhs),
00610                 _M_message(__msg_order_different)
00611                 ._M_iterator(__lhs, "lhs")
00612                 ._M_iterator(__rhs, "rhs"));
00613       return __lhs.base() <= __rhs.base();
00614     }
00615 
00616   template<typename _IteratorL, typename _IteratorR, typename _Sequence>
00617     inline bool
00618     operator>(const _Safe_iterator<_IteratorL, _Sequence>& __lhs,
00619           const _Safe_iterator<_IteratorR, _Sequence>& __rhs)
00620     _GLIBCXX_NOEXCEPT
00621     {
00622       _GLIBCXX_DEBUG_VERIFY(! __lhs._M_singular() && ! __rhs._M_singular(),
00623                 _M_message(__msg_iter_order_bad)
00624                 ._M_iterator(__lhs, "lhs")
00625                 ._M_iterator(__rhs, "rhs"));
00626       _GLIBCXX_DEBUG_VERIFY(__lhs._M_can_compare(__rhs),
00627                 _M_message(__msg_order_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 bool
00635     operator>(const _Safe_iterator<_Iterator, _Sequence>& __lhs,
00636           const _Safe_iterator<_Iterator, _Sequence>& __rhs)
00637     _GLIBCXX_NOEXCEPT
00638     {
00639       _GLIBCXX_DEBUG_VERIFY(! __lhs._M_singular() && ! __rhs._M_singular(),
00640                 _M_message(__msg_iter_order_bad)
00641                 ._M_iterator(__lhs, "lhs")
00642                 ._M_iterator(__rhs, "rhs"));
00643       _GLIBCXX_DEBUG_VERIFY(__lhs._M_can_compare(__rhs),
00644                 _M_message(__msg_order_different)
00645                 ._M_iterator(__lhs, "lhs")
00646                 ._M_iterator(__rhs, "rhs"));
00647       return __lhs.base() > __rhs.base();
00648     }
00649 
00650   template<typename _IteratorL, typename _IteratorR, typename _Sequence>
00651     inline bool
00652     operator>=(const _Safe_iterator<_IteratorL, _Sequence>& __lhs,
00653            const _Safe_iterator<_IteratorR, _Sequence>& __rhs)
00654     _GLIBCXX_NOEXCEPT
00655     {
00656       _GLIBCXX_DEBUG_VERIFY(! __lhs._M_singular() && ! __rhs._M_singular(),
00657                 _M_message(__msg_iter_order_bad)
00658                 ._M_iterator(__lhs, "lhs")
00659                 ._M_iterator(__rhs, "rhs"));
00660       _GLIBCXX_DEBUG_VERIFY(__lhs._M_can_compare(__rhs),
00661                 _M_message(__msg_order_different)
00662                 ._M_iterator(__lhs, "lhs")
00663                 ._M_iterator(__rhs, "rhs"));
00664       return __lhs.base() >= __rhs.base();
00665     }
00666 
00667   template<typename _Iterator, typename _Sequence>
00668     inline bool
00669     operator>=(const _Safe_iterator<_Iterator, _Sequence>& __lhs,
00670                const _Safe_iterator<_Iterator, _Sequence>& __rhs)
00671     _GLIBCXX_NOEXCEPT
00672     {
00673       _GLIBCXX_DEBUG_VERIFY(! __lhs._M_singular() && ! __rhs._M_singular(),
00674                 _M_message(__msg_iter_order_bad)
00675                 ._M_iterator(__lhs, "lhs")
00676                 ._M_iterator(__rhs, "rhs"));
00677       _GLIBCXX_DEBUG_VERIFY(__lhs._M_can_compare(__rhs),
00678                 _M_message(__msg_order_different)
00679                 ._M_iterator(__lhs, "lhs")
00680                 ._M_iterator(__rhs, "rhs"));
00681       return __lhs.base() >= __rhs.base();
00682     }
00683 
00684   // _GLIBCXX_RESOLVE_LIB_DEFECTS
00685   // According to the resolution of DR179 not only the various comparison
00686   // operators but also operator- must accept mixed iterator/const_iterator
00687   // parameters.
00688   template<typename _IteratorL, typename _IteratorR, typename _Sequence>
00689     inline typename _Safe_iterator<_IteratorL, _Sequence>::difference_type
00690     operator-(const _Safe_iterator<_IteratorL, _Sequence>& __lhs,
00691           const _Safe_iterator<_IteratorR, _Sequence>& __rhs)
00692     _GLIBCXX_NOEXCEPT
00693     {
00694       _GLIBCXX_DEBUG_VERIFY(! __lhs._M_singular() && ! __rhs._M_singular(),
00695                 _M_message(__msg_distance_bad)
00696                 ._M_iterator(__lhs, "lhs")
00697                 ._M_iterator(__rhs, "rhs"));
00698       _GLIBCXX_DEBUG_VERIFY(__lhs._M_can_compare(__rhs),
00699                 _M_message(__msg_distance_different)
00700                 ._M_iterator(__lhs, "lhs")
00701                 ._M_iterator(__rhs, "rhs"));
00702       return __lhs.base() - __rhs.base();
00703     }
00704 
00705    template<typename _Iterator, typename _Sequence>
00706      inline typename _Safe_iterator<_Iterator, _Sequence>::difference_type
00707      operator-(const _Safe_iterator<_Iterator, _Sequence>& __lhs,
00708            const _Safe_iterator<_Iterator, _Sequence>& __rhs)
00709     _GLIBCXX_NOEXCEPT
00710      {
00711        _GLIBCXX_DEBUG_VERIFY(! __lhs._M_singular() && ! __rhs._M_singular(),
00712                  _M_message(__msg_distance_bad)
00713                  ._M_iterator(__lhs, "lhs")
00714                  ._M_iterator(__rhs, "rhs"));
00715        _GLIBCXX_DEBUG_VERIFY(__lhs._M_can_compare(__rhs),
00716                  _M_message(__msg_distance_different)
00717                  ._M_iterator(__lhs, "lhs")
00718                  ._M_iterator(__rhs, "rhs"));
00719        return __lhs.base() - __rhs.base();
00720      }
00721 
00722   template<typename _Iterator, typename _Sequence>
00723     inline _Safe_iterator<_Iterator, _Sequence>
00724     operator+(typename _Safe_iterator<_Iterator,_Sequence>::difference_type __n,
00725           const _Safe_iterator<_Iterator, _Sequence>& __i) _GLIBCXX_NOEXCEPT
00726     { return __i + __n; }
00727 } // namespace __gnu_debug
00728 
00729 #include <debug/safe_iterator.tcc>
00730 
00731 #endif