libstdc++
safe_iterator.h
Go to the documentation of this file.
00001 // Safe iterator implementation  -*- C++ -*-
00002 
00003 // Copyright (C) 2003-2015 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    *  Note that _Iterator must be the first base class so that it gets
00114    *  initialized before the iterator is being attached to the container's list
00115    *  of iterators and it is being detached before _Iterator get
00116    *  destroyed. Otherwise it would result in a data race.
00117    */
00118   template<typename _Iterator, typename _Sequence>
00119     class _Safe_iterator
00120     : private _Iterator,
00121       public _Safe_iterator_base
00122     {
00123       typedef _Iterator _Iter_base;
00124       typedef _Safe_iterator_base _Safe_base;
00125       typedef typename _Sequence::const_iterator _Const_iterator;
00126 
00127       /// Determine if this is a constant iterator.
00128       bool
00129       _M_constant() const
00130       { return std::__are_same<_Const_iterator, _Safe_iterator>::__value; }
00131 
00132       typedef std::iterator_traits<_Iterator> _Traits;
00133 
00134       struct _Attach_single
00135       { };
00136 
00137       _Safe_iterator(const _Iterator& __i, _Safe_sequence_base* __seq,
00138                      _Attach_single)
00139       _GLIBCXX_NOEXCEPT
00140       : _Iter_base(__i)
00141       { _M_attach_single(__seq); }
00142 
00143     public:
00144       typedef _Iterator                                 iterator_type;
00145       typedef typename _Traits::iterator_category       iterator_category;
00146       typedef typename _Traits::value_type              value_type;
00147       typedef typename _Traits::difference_type         difference_type;
00148       typedef typename _Traits::reference               reference;
00149       typedef typename _Traits::pointer                 pointer;
00150 
00151       /// @post the iterator is singular and unattached
00152       _Safe_iterator() _GLIBCXX_NOEXCEPT : _Iter_base() { }
00153 
00154       /**
00155        * @brief Safe iterator construction from an unsafe iterator and
00156        * its sequence.
00157        *
00158        * @pre @p seq is not NULL
00159        * @post this is not singular
00160        */
00161       _Safe_iterator(const _Iterator& __i, const _Safe_sequence_base* __seq)
00162       _GLIBCXX_NOEXCEPT
00163       : _Iter_base(__i), _Safe_base(__seq, _M_constant())
00164       {
00165         _GLIBCXX_DEBUG_VERIFY(!this->_M_singular(),
00166                               _M_message(__msg_init_singular)
00167                               ._M_iterator(*this, "this"));
00168       }
00169 
00170       /**
00171        * @brief Copy construction.
00172        */
00173       _Safe_iterator(const _Safe_iterator& __x) _GLIBCXX_NOEXCEPT
00174       : _Iter_base(__x.base())
00175       {
00176         // _GLIBCXX_RESOLVE_LIB_DEFECTS
00177         // DR 408. Is vector<reverse_iterator<char*> > forbidden?
00178         _GLIBCXX_DEBUG_VERIFY(!__x._M_singular()
00179                               || __x.base() == _Iterator(),
00180                               _M_message(__msg_init_copy_singular)
00181                               ._M_iterator(*this, "this")
00182                               ._M_iterator(__x, "other"));
00183         _M_attach(__x._M_sequence);
00184       }
00185 
00186 #if __cplusplus >= 201103L
00187       /**
00188        * @brief Move construction.
00189        * @post __x is singular and unattached
00190        */
00191       _Safe_iterator(_Safe_iterator&& __x) noexcept
00192       : _Iter_base()
00193       {
00194         _GLIBCXX_DEBUG_VERIFY(!__x._M_singular()
00195                               || __x.base() == _Iterator(),
00196                               _M_message(__msg_init_copy_singular)
00197                               ._M_iterator(*this, "this")
00198                               ._M_iterator(__x, "other"));
00199         _Safe_sequence_base* __seq = __x._M_sequence;
00200         __x._M_detach();
00201         std::swap(base(), __x.base());
00202         _M_attach(__seq);
00203       }
00204 #endif
00205 
00206       /**
00207        *  @brief Converting constructor from a mutable iterator to a
00208        *  constant iterator.
00209       */
00210       template<typename _MutableIterator>
00211         _Safe_iterator(
00212           const _Safe_iterator<_MutableIterator,
00213           typename __gnu_cxx::__enable_if<(std::__are_same<_MutableIterator,
00214                       typename _Sequence::iterator::iterator_type>::__value),
00215                    _Sequence>::__type>& __x) _GLIBCXX_NOEXCEPT
00216         : _Iter_base(__x.base())
00217         {
00218           // _GLIBCXX_RESOLVE_LIB_DEFECTS
00219           // DR 408. Is vector<reverse_iterator<char*> > forbidden?
00220           _GLIBCXX_DEBUG_VERIFY(!__x._M_singular()
00221                                 || __x.base() == _Iterator(),
00222                                 _M_message(__msg_init_const_singular)
00223                                 ._M_iterator(*this, "this")
00224                                 ._M_iterator(__x, "other"));
00225           _M_attach(__x._M_sequence);
00226         }
00227 
00228       /**
00229        * @brief Copy assignment.
00230        */
00231       _Safe_iterator&
00232       operator=(const _Safe_iterator& __x) _GLIBCXX_NOEXCEPT
00233       {
00234         // _GLIBCXX_RESOLVE_LIB_DEFECTS
00235         // DR 408. Is vector<reverse_iterator<char*> > forbidden?
00236         _GLIBCXX_DEBUG_VERIFY(!__x._M_singular()
00237                               || __x.base() == _Iterator(),
00238                               _M_message(__msg_copy_singular)
00239                               ._M_iterator(*this, "this")
00240                               ._M_iterator(__x, "other"));
00241 
00242         if (this->_M_sequence && this->_M_sequence == __x._M_sequence)
00243           {
00244             __gnu_cxx::__scoped_lock __l(this->_M_get_mutex());
00245             base() = __x.base();
00246             _M_version = __x._M_sequence->_M_version;
00247           }
00248         else
00249           {
00250             _M_detach();
00251             base() = __x.base();
00252             _M_attach(__x._M_sequence);
00253           }
00254 
00255         return *this;
00256       }
00257 
00258 #if __cplusplus >= 201103L
00259       /**
00260        * @brief Move assignment.
00261        * @post __x is singular and unattached
00262        */
00263       _Safe_iterator&
00264       operator=(_Safe_iterator&& __x) noexcept
00265       {
00266         _GLIBCXX_DEBUG_VERIFY(this != &__x,
00267                               _M_message(__msg_self_move_assign)
00268                               ._M_iterator(*this, "this"));
00269         _GLIBCXX_DEBUG_VERIFY(!__x._M_singular()
00270                               || __x.base() == _Iterator(),
00271                               _M_message(__msg_copy_singular)
00272                               ._M_iterator(*this, "this")
00273                               ._M_iterator(__x, "other"));
00274 
00275         if (this->_M_sequence && this->_M_sequence == __x._M_sequence)
00276           {
00277             __gnu_cxx::__scoped_lock __l(this->_M_get_mutex());
00278             base() = __x.base();
00279             _M_version = __x._M_sequence->_M_version;
00280           }
00281         else
00282           {
00283             _M_detach();
00284             base() = __x.base();
00285             _M_attach(__x._M_sequence);
00286           }
00287 
00288         __x._M_detach();
00289         __x.base() = _Iterator();
00290         return *this;
00291       }
00292 #endif
00293 
00294       /**
00295        *  @brief Iterator dereference.
00296        *  @pre iterator is dereferenceable
00297        */
00298       reference
00299       operator*() const _GLIBCXX_NOEXCEPT
00300       {
00301         _GLIBCXX_DEBUG_VERIFY(this->_M_dereferenceable(),
00302                               _M_message(__msg_bad_deref)
00303                               ._M_iterator(*this, "this"));
00304         return *base();
00305       }
00306 
00307       /**
00308        *  @brief Iterator dereference.
00309        *  @pre iterator is dereferenceable
00310        *  @todo Make this correct w.r.t. iterators that return proxies
00311        */
00312       pointer
00313       operator->() const _GLIBCXX_NOEXCEPT
00314       {
00315         _GLIBCXX_DEBUG_VERIFY(this->_M_dereferenceable(),
00316                               _M_message(__msg_bad_deref)
00317                               ._M_iterator(*this, "this"));
00318         return std::__addressof(*base());
00319       }
00320 
00321       // ------ Input iterator requirements ------
00322       /**
00323        *  @brief Iterator preincrement
00324        *  @pre iterator is incrementable
00325        */
00326       _Safe_iterator&
00327       operator++() _GLIBCXX_NOEXCEPT
00328       {
00329         _GLIBCXX_DEBUG_VERIFY(this->_M_incrementable(),
00330                               _M_message(__msg_bad_inc)
00331                               ._M_iterator(*this, "this"));
00332         __gnu_cxx::__scoped_lock(this->_M_get_mutex());
00333         ++base();
00334         return *this;
00335       }
00336 
00337       /**
00338        *  @brief Iterator postincrement
00339        *  @pre iterator is incrementable
00340        */
00341       _Safe_iterator
00342       operator++(int) _GLIBCXX_NOEXCEPT
00343       {
00344         _GLIBCXX_DEBUG_VERIFY(this->_M_incrementable(),
00345                               _M_message(__msg_bad_inc)
00346                               ._M_iterator(*this, "this"));
00347         __gnu_cxx::__scoped_lock __l(this->_M_get_mutex());
00348         return _Safe_iterator(base()++, this->_M_sequence, _Attach_single());
00349       }
00350 
00351       // ------ Bidirectional iterator requirements ------
00352       /**
00353        *  @brief Iterator predecrement
00354        *  @pre iterator is decrementable
00355        */
00356       _Safe_iterator&
00357       operator--() _GLIBCXX_NOEXCEPT
00358       {
00359         _GLIBCXX_DEBUG_VERIFY(this->_M_decrementable(),
00360                               _M_message(__msg_bad_dec)
00361                               ._M_iterator(*this, "this"));
00362         __gnu_cxx::__scoped_lock __l(this->_M_get_mutex());
00363         --base();
00364         return *this;
00365       }
00366 
00367       /**
00368        *  @brief Iterator postdecrement
00369        *  @pre iterator is decrementable
00370        */
00371       _Safe_iterator
00372       operator--(int) _GLIBCXX_NOEXCEPT
00373       {
00374         _GLIBCXX_DEBUG_VERIFY(this->_M_decrementable(),
00375                               _M_message(__msg_bad_dec)
00376                               ._M_iterator(*this, "this"));
00377         __gnu_cxx::__scoped_lock __l(this->_M_get_mutex());
00378         return _Safe_iterator(base()--, this->_M_sequence, _Attach_single());
00379       }
00380 
00381       // ------ Random access iterator requirements ------
00382       reference
00383       operator[](const difference_type& __n) const _GLIBCXX_NOEXCEPT
00384       {
00385         _GLIBCXX_DEBUG_VERIFY(this->_M_can_advance(__n)
00386                               && this->_M_can_advance(__n+1),
00387                               _M_message(__msg_iter_subscript_oob)
00388                               ._M_iterator(*this)._M_integer(__n));
00389         return base()[__n];
00390       }
00391 
00392       _Safe_iterator&
00393       operator+=(const difference_type& __n) _GLIBCXX_NOEXCEPT
00394       {
00395         _GLIBCXX_DEBUG_VERIFY(this->_M_can_advance(__n),
00396                               _M_message(__msg_advance_oob)
00397                               ._M_iterator(*this)._M_integer(__n));
00398         __gnu_cxx::__scoped_lock __l(this->_M_get_mutex());
00399         base() += __n;
00400         return *this;
00401       }
00402 
00403       _Safe_iterator
00404       operator+(const difference_type& __n) const _GLIBCXX_NOEXCEPT
00405       {
00406         _GLIBCXX_DEBUG_VERIFY(this->_M_can_advance(__n),
00407                               _M_message(__msg_advance_oob)
00408                               ._M_iterator(*this)._M_integer(__n));
00409         return _Safe_iterator(base() + __n, this->_M_sequence);
00410       }
00411 
00412       _Safe_iterator&
00413       operator-=(const difference_type& __n) _GLIBCXX_NOEXCEPT
00414       {
00415         _GLIBCXX_DEBUG_VERIFY(this->_M_can_advance(-__n),
00416                               _M_message(__msg_retreat_oob)
00417                               ._M_iterator(*this)._M_integer(__n));
00418         __gnu_cxx::__scoped_lock __l(this->_M_get_mutex());
00419         base() -= __n;
00420         return *this;
00421       }
00422 
00423       _Safe_iterator
00424       operator-(const difference_type& __n) const _GLIBCXX_NOEXCEPT
00425       {
00426         _GLIBCXX_DEBUG_VERIFY(this->_M_can_advance(-__n),
00427                               _M_message(__msg_retreat_oob)
00428                               ._M_iterator(*this)._M_integer(__n));
00429         return _Safe_iterator(base() - __n, this->_M_sequence);
00430       }
00431 
00432       // ------ Utilities ------
00433       /**
00434        * @brief Return the underlying iterator
00435        */
00436       _Iterator&
00437       base() _GLIBCXX_NOEXCEPT { return *this; }
00438 
00439       const _Iterator&
00440       base() const _GLIBCXX_NOEXCEPT { return *this; }
00441 
00442       /**
00443        * @brief Conversion to underlying non-debug iterator to allow
00444        * better interaction with non-debug containers.
00445        */
00446       operator _Iterator() const _GLIBCXX_NOEXCEPT { return *this; }
00447 
00448       /** Attach iterator to the given sequence. */
00449       void
00450       _M_attach(_Safe_sequence_base* __seq)
00451       { _Safe_base::_M_attach(__seq, _M_constant()); }
00452 
00453       /** Likewise, but not thread-safe. */
00454       void
00455       _M_attach_single(_Safe_sequence_base* __seq)
00456       { _Safe_base::_M_attach_single(__seq, _M_constant()); }
00457 
00458       /// Is the iterator dereferenceable?
00459       bool
00460       _M_dereferenceable() const
00461       { return !this->_M_singular() && !_M_is_end() && !_M_is_before_begin(); }
00462 
00463       /// Is the iterator before a dereferenceable one?
00464       bool
00465       _M_before_dereferenceable() const
00466       {
00467         if (this->_M_incrementable())
00468         {
00469           _Iterator __base = base();
00470           return ++__base != _M_get_sequence()->_M_base().end();
00471         }
00472         return false;
00473       }
00474 
00475       /// Is the iterator incrementable?
00476       bool
00477       _M_incrementable() const
00478       { return !this->_M_singular() && !_M_is_end(); }
00479 
00480       // Is the iterator decrementable?
00481       bool
00482       _M_decrementable() const { return !_M_singular() && !_M_is_begin(); }
00483 
00484       // Can we advance the iterator @p __n steps (@p __n may be negative)
00485       bool
00486       _M_can_advance(const difference_type& __n) const;
00487 
00488       // Is the iterator range [*this, __rhs) valid?
00489       bool
00490       _M_valid_range(const _Safe_iterator& __rhs) const;
00491 
00492       // The sequence this iterator references.
00493       typename
00494       __gnu_cxx::__conditional_type<std::__are_same<_Const_iterator,
00495                                                     _Safe_iterator>::__value,
00496                                     const _Sequence*,
00497                                     _Sequence*>::__type
00498       _M_get_sequence() const
00499       { return static_cast<_Sequence*>(_M_sequence); }
00500 
00501       /// Is this iterator equal to the sequence's begin() iterator?
00502       bool
00503       _M_is_begin() const
00504       { return base() == _M_get_sequence()->_M_base().begin(); }
00505 
00506       /// Is this iterator equal to the sequence's end() iterator?
00507       bool
00508       _M_is_end() const
00509       { return base() == _M_get_sequence()->_M_base().end(); }
00510 
00511       /// Is this iterator equal to the sequence's before_begin() iterator if
00512       /// any?
00513       bool
00514       _M_is_before_begin() const
00515       { return _BeforeBeginHelper<_Sequence>::_S_Is(*this); }
00516 
00517       /// Is this iterator equal to the sequence's before_begin() iterator if
00518       /// any or begin() otherwise?
00519       bool
00520       _M_is_beginnest() const
00521       { return _BeforeBeginHelper<_Sequence>::_S_Is_Beginnest(*this); }
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     _GLIBCXX_NOEXCEPT
00529     {
00530       _GLIBCXX_DEBUG_VERIFY(! __lhs._M_singular() && ! __rhs._M_singular(),
00531                             _M_message(__msg_iter_compare_bad)
00532                             ._M_iterator(__lhs, "lhs")
00533                             ._M_iterator(__rhs, "rhs"));
00534       _GLIBCXX_DEBUG_VERIFY(__lhs._M_can_compare(__rhs),
00535                             _M_message(__msg_compare_different)
00536                             ._M_iterator(__lhs, "lhs")
00537                             ._M_iterator(__rhs, "rhs"));
00538       return __lhs.base() == __rhs.base();
00539     }
00540 
00541   template<typename _Iterator, typename _Sequence>
00542     inline bool
00543     operator==(const _Safe_iterator<_Iterator, _Sequence>& __lhs,
00544                const _Safe_iterator<_Iterator, _Sequence>& __rhs)
00545     _GLIBCXX_NOEXCEPT
00546     {
00547       _GLIBCXX_DEBUG_VERIFY(! __lhs._M_singular() && ! __rhs._M_singular(),
00548                             _M_message(__msg_iter_compare_bad)
00549                             ._M_iterator(__lhs, "lhs")
00550                             ._M_iterator(__rhs, "rhs"));
00551       _GLIBCXX_DEBUG_VERIFY(__lhs._M_can_compare(__rhs),
00552                             _M_message(__msg_compare_different)
00553                             ._M_iterator(__lhs, "lhs")
00554                             ._M_iterator(__rhs, "rhs"));
00555       return __lhs.base() == __rhs.base();
00556     }
00557 
00558   template<typename _IteratorL, typename _IteratorR, typename _Sequence>
00559     inline bool
00560     operator!=(const _Safe_iterator<_IteratorL, _Sequence>& __lhs,
00561                const _Safe_iterator<_IteratorR, _Sequence>& __rhs)
00562     _GLIBCXX_NOEXCEPT
00563     {
00564       _GLIBCXX_DEBUG_VERIFY(! __lhs._M_singular() && ! __rhs._M_singular(),
00565                             _M_message(__msg_iter_compare_bad)
00566                             ._M_iterator(__lhs, "lhs")
00567                             ._M_iterator(__rhs, "rhs"));
00568       _GLIBCXX_DEBUG_VERIFY(__lhs._M_can_compare(__rhs),
00569                             _M_message(__msg_compare_different)
00570                             ._M_iterator(__lhs, "lhs")
00571                             ._M_iterator(__rhs, "rhs"));
00572       return __lhs.base() != __rhs.base();
00573     }
00574 
00575   template<typename _Iterator, typename _Sequence>
00576     inline bool
00577     operator!=(const _Safe_iterator<_Iterator, _Sequence>& __lhs,
00578                const _Safe_iterator<_Iterator, _Sequence>& __rhs)
00579     _GLIBCXX_NOEXCEPT
00580     {
00581       _GLIBCXX_DEBUG_VERIFY(! __lhs._M_singular() && ! __rhs._M_singular(),
00582                             _M_message(__msg_iter_compare_bad)
00583                             ._M_iterator(__lhs, "lhs")
00584                             ._M_iterator(__rhs, "rhs"));
00585       _GLIBCXX_DEBUG_VERIFY(__lhs._M_can_compare(__rhs),
00586                             _M_message(__msg_compare_different)
00587                             ._M_iterator(__lhs, "lhs")
00588                             ._M_iterator(__rhs, "rhs"));
00589       return __lhs.base() != __rhs.base();
00590     }
00591 
00592   template<typename _IteratorL, typename _IteratorR, typename _Sequence>
00593     inline bool
00594     operator<(const _Safe_iterator<_IteratorL, _Sequence>& __lhs,
00595               const _Safe_iterator<_IteratorR, _Sequence>& __rhs)
00596     _GLIBCXX_NOEXCEPT
00597     {
00598       _GLIBCXX_DEBUG_VERIFY(! __lhs._M_singular() && ! __rhs._M_singular(),
00599                             _M_message(__msg_iter_order_bad)
00600                             ._M_iterator(__lhs, "lhs")
00601                             ._M_iterator(__rhs, "rhs"));
00602       _GLIBCXX_DEBUG_VERIFY(__lhs._M_can_compare(__rhs),
00603                             _M_message(__msg_order_different)
00604                             ._M_iterator(__lhs, "lhs")
00605                             ._M_iterator(__rhs, "rhs"));
00606       return __lhs.base() < __rhs.base();
00607     }
00608 
00609   template<typename _Iterator, typename _Sequence>
00610     inline bool
00611     operator<(const _Safe_iterator<_Iterator, _Sequence>& __lhs,
00612               const _Safe_iterator<_Iterator, _Sequence>& __rhs)
00613     _GLIBCXX_NOEXCEPT
00614     {
00615       _GLIBCXX_DEBUG_VERIFY(! __lhs._M_singular() && ! __rhs._M_singular(),
00616                             _M_message(__msg_iter_order_bad)
00617                             ._M_iterator(__lhs, "lhs")
00618                             ._M_iterator(__rhs, "rhs"));
00619       _GLIBCXX_DEBUG_VERIFY(__lhs._M_can_compare(__rhs),
00620                             _M_message(__msg_order_different)
00621                             ._M_iterator(__lhs, "lhs")
00622                             ._M_iterator(__rhs, "rhs"));
00623       return __lhs.base() < __rhs.base();
00624     }
00625 
00626   template<typename _IteratorL, typename _IteratorR, typename _Sequence>
00627     inline bool
00628     operator<=(const _Safe_iterator<_IteratorL, _Sequence>& __lhs,
00629                const _Safe_iterator<_IteratorR, _Sequence>& __rhs)
00630     _GLIBCXX_NOEXCEPT
00631     {
00632       _GLIBCXX_DEBUG_VERIFY(! __lhs._M_singular() && ! __rhs._M_singular(),
00633                             _M_message(__msg_iter_order_bad)
00634                             ._M_iterator(__lhs, "lhs")
00635                             ._M_iterator(__rhs, "rhs"));
00636       _GLIBCXX_DEBUG_VERIFY(__lhs._M_can_compare(__rhs),
00637                             _M_message(__msg_order_different)
00638                             ._M_iterator(__lhs, "lhs")
00639                             ._M_iterator(__rhs, "rhs"));
00640       return __lhs.base() <= __rhs.base();
00641     }
00642 
00643   template<typename _Iterator, typename _Sequence>
00644     inline bool
00645     operator<=(const _Safe_iterator<_Iterator, _Sequence>& __lhs,
00646                const _Safe_iterator<_Iterator, _Sequence>& __rhs)
00647     _GLIBCXX_NOEXCEPT
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 _IteratorL, typename _IteratorR, typename _Sequence>
00661     inline bool
00662     operator>(const _Safe_iterator<_IteratorL, _Sequence>& __lhs,
00663               const _Safe_iterator<_IteratorR, _Sequence>& __rhs)
00664     _GLIBCXX_NOEXCEPT
00665     {
00666       _GLIBCXX_DEBUG_VERIFY(! __lhs._M_singular() && ! __rhs._M_singular(),
00667                             _M_message(__msg_iter_order_bad)
00668                             ._M_iterator(__lhs, "lhs")
00669                             ._M_iterator(__rhs, "rhs"));
00670       _GLIBCXX_DEBUG_VERIFY(__lhs._M_can_compare(__rhs),
00671                             _M_message(__msg_order_different)
00672                             ._M_iterator(__lhs, "lhs")
00673                             ._M_iterator(__rhs, "rhs"));
00674       return __lhs.base() > __rhs.base();
00675     }
00676 
00677   template<typename _Iterator, typename _Sequence>
00678     inline bool
00679     operator>(const _Safe_iterator<_Iterator, _Sequence>& __lhs,
00680               const _Safe_iterator<_Iterator, _Sequence>& __rhs)
00681     _GLIBCXX_NOEXCEPT
00682     {
00683       _GLIBCXX_DEBUG_VERIFY(! __lhs._M_singular() && ! __rhs._M_singular(),
00684                             _M_message(__msg_iter_order_bad)
00685                             ._M_iterator(__lhs, "lhs")
00686                             ._M_iterator(__rhs, "rhs"));
00687       _GLIBCXX_DEBUG_VERIFY(__lhs._M_can_compare(__rhs),
00688                             _M_message(__msg_order_different)
00689                             ._M_iterator(__lhs, "lhs")
00690                             ._M_iterator(__rhs, "rhs"));
00691       return __lhs.base() > __rhs.base();
00692     }
00693 
00694   template<typename _IteratorL, typename _IteratorR, typename _Sequence>
00695     inline bool
00696     operator>=(const _Safe_iterator<_IteratorL, _Sequence>& __lhs,
00697                const _Safe_iterator<_IteratorR, _Sequence>& __rhs)
00698     _GLIBCXX_NOEXCEPT
00699     {
00700       _GLIBCXX_DEBUG_VERIFY(! __lhs._M_singular() && ! __rhs._M_singular(),
00701                             _M_message(__msg_iter_order_bad)
00702                             ._M_iterator(__lhs, "lhs")
00703                             ._M_iterator(__rhs, "rhs"));
00704       _GLIBCXX_DEBUG_VERIFY(__lhs._M_can_compare(__rhs),
00705                             _M_message(__msg_order_different)
00706                             ._M_iterator(__lhs, "lhs")
00707                             ._M_iterator(__rhs, "rhs"));
00708       return __lhs.base() >= __rhs.base();
00709     }
00710 
00711   template<typename _Iterator, typename _Sequence>
00712     inline bool
00713     operator>=(const _Safe_iterator<_Iterator, _Sequence>& __lhs,
00714                const _Safe_iterator<_Iterator, _Sequence>& __rhs)
00715     _GLIBCXX_NOEXCEPT
00716     {
00717       _GLIBCXX_DEBUG_VERIFY(! __lhs._M_singular() && ! __rhs._M_singular(),
00718                             _M_message(__msg_iter_order_bad)
00719                             ._M_iterator(__lhs, "lhs")
00720                             ._M_iterator(__rhs, "rhs"));
00721       _GLIBCXX_DEBUG_VERIFY(__lhs._M_can_compare(__rhs),
00722                             _M_message(__msg_order_different)
00723                             ._M_iterator(__lhs, "lhs")
00724                             ._M_iterator(__rhs, "rhs"));
00725       return __lhs.base() >= __rhs.base();
00726     }
00727 
00728   // _GLIBCXX_RESOLVE_LIB_DEFECTS
00729   // According to the resolution of DR179 not only the various comparison
00730   // operators but also operator- must accept mixed iterator/const_iterator
00731   // parameters.
00732   template<typename _IteratorL, typename _IteratorR, typename _Sequence>
00733     inline typename _Safe_iterator<_IteratorL, _Sequence>::difference_type
00734     operator-(const _Safe_iterator<_IteratorL, _Sequence>& __lhs,
00735               const _Safe_iterator<_IteratorR, _Sequence>& __rhs)
00736     _GLIBCXX_NOEXCEPT
00737     {
00738       _GLIBCXX_DEBUG_VERIFY(! __lhs._M_singular() && ! __rhs._M_singular(),
00739                             _M_message(__msg_distance_bad)
00740                             ._M_iterator(__lhs, "lhs")
00741                             ._M_iterator(__rhs, "rhs"));
00742       _GLIBCXX_DEBUG_VERIFY(__lhs._M_can_compare(__rhs),
00743                             _M_message(__msg_distance_different)
00744                             ._M_iterator(__lhs, "lhs")
00745                             ._M_iterator(__rhs, "rhs"));
00746       return __lhs.base() - __rhs.base();
00747     }
00748 
00749    template<typename _Iterator, typename _Sequence>
00750      inline typename _Safe_iterator<_Iterator, _Sequence>::difference_type
00751      operator-(const _Safe_iterator<_Iterator, _Sequence>& __lhs,
00752                const _Safe_iterator<_Iterator, _Sequence>& __rhs)
00753     _GLIBCXX_NOEXCEPT
00754      {
00755        _GLIBCXX_DEBUG_VERIFY(! __lhs._M_singular() && ! __rhs._M_singular(),
00756                              _M_message(__msg_distance_bad)
00757                              ._M_iterator(__lhs, "lhs")
00758                              ._M_iterator(__rhs, "rhs"));
00759        _GLIBCXX_DEBUG_VERIFY(__lhs._M_can_compare(__rhs),
00760                              _M_message(__msg_distance_different)
00761                              ._M_iterator(__lhs, "lhs")
00762                              ._M_iterator(__rhs, "rhs"));
00763        return __lhs.base() - __rhs.base();
00764      }
00765 
00766   template<typename _Iterator, typename _Sequence>
00767     inline _Safe_iterator<_Iterator, _Sequence>
00768     operator+(typename _Safe_iterator<_Iterator,_Sequence>::difference_type __n,
00769               const _Safe_iterator<_Iterator, _Sequence>& __i) _GLIBCXX_NOEXCEPT
00770     { return __i + __n; }
00771 } // namespace __gnu_debug
00772 
00773 #include <debug/safe_iterator.tcc>
00774 
00775 #endif