home *** CD-ROM | disk | FTP | other *** search
/ Beginning C++ Through Gam…rogramming (2nd Edition) / BCGP2E.ISO / bloodshed / devcpp-4.9.9.2_setup.exe / safe_iterator.h < prev    next >
C/C++ Source or Header  |  2005-01-29  |  21KB  |  619 lines

  1. // Safe iterator implementation  -*- C++ -*-
  2.  
  3. // Copyright (C) 2003, 2004
  4. // Free Software Foundation, Inc.
  5. //
  6. // This file is part of the GNU ISO C++ Library.  This library is free
  7. // software; you can redistribute it and/or modify it under the
  8. // terms of the GNU General Public License as published by the
  9. // Free Software Foundation; either version 2, or (at your option)
  10. // any later version.
  11.  
  12. // This library is distributed in the hope that it will be useful,
  13. // but WITHOUT ANY WARRANTY; without even the implied warranty of
  14. // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  15. // GNU General Public License for more details.
  16.  
  17. // You should have received a copy of the GNU General Public License along
  18. // with this library; see the file COPYING.  If not, write to the Free
  19. // Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307,
  20. // USA.
  21.  
  22. // As a special exception, you may use this file as part of a free software
  23. // library without restriction.  Specifically, if other files instantiate
  24. // templates or use macros or inline functions from this file, or you compile
  25. // this file and link it with other files to produce an executable, this
  26. // file does not by itself cause the resulting executable to be covered by
  27. // the GNU General Public License.  This exception does not however
  28. // invalidate any other reasons why the executable file might be covered by
  29. // the GNU General Public License.
  30.  
  31. #ifndef _GLIBCXX_DEBUG_SAFE_ITERATOR_H
  32. #define _GLIBCXX_DEBUG_SAFE_ITERATOR_H 1
  33.  
  34. #include <bits/stl_pair.h>
  35. #include <debug/debug.h>
  36. #include <debug/formatter.h>
  37. #include <debug/safe_base.h>
  38. #include <bits/cpp_type_traits.h>
  39.  
  40. namespace __gnu_debug
  41. {
  42.   using std::iterator_traits;
  43.   using std::pair;
  44.  
  45.   /** Iterators that derive from _Safe_iterator_base but that aren't
  46.    *  _Safe_iterators can be determined singular or non-singular via
  47.    *  _Safe_iterator_base.
  48.    */
  49.   inline bool __check_singular_aux(const _Safe_iterator_base* __x)
  50.   { return __x->_M_singular(); }
  51.  
  52.   /** \brief Safe iterator wrapper.
  53.    *
  54.    *  The class template %_Safe_iterator is a wrapper around an
  55.    *  iterator that tracks the iterator's movement among sequences and
  56.    *  checks that operations performed on the "safe" iterator are
  57.    *  legal. In additional to the basic iterator operations (which are
  58.    *  validated, and then passed to the underlying iterator),
  59.    *  %_Safe_iterator has member functions for iterator invalidation,
  60.    *  attaching/detaching the iterator from sequences, and querying
  61.    *  the iterator's state.
  62.    */
  63.   template<typename _Iterator, typename _Sequence>
  64.     class _Safe_iterator : public _Safe_iterator_base
  65.     {
  66.       typedef _Safe_iterator _Self;
  67.  
  68.       /** The precision to which we can calculate the distance between
  69.        *  two iterators.
  70.        */
  71.       enum _Distance_precision
  72.     {
  73.       __dp_equality, //< Can compare iterator equality, only
  74.       __dp_sign,     //< Can determine equality and ordering
  75.       __dp_exact     //< Can determine distance precisely
  76.     };
  77.  
  78.       /// The underlying iterator
  79.       _Iterator _M_current;
  80.  
  81.       /// Determine if this is a constant iterator.
  82.       bool
  83.       _M_constant() const
  84.       {
  85.     typedef typename _Sequence::const_iterator const_iterator;
  86.     return __is_same<const_iterator, _Safe_iterator>::value;
  87.       }
  88.  
  89.       typedef iterator_traits<_Iterator> _Traits;
  90.  
  91.     public:
  92.       typedef _Iterator                           _Base_iterator;
  93.       typedef typename _Traits::iterator_category iterator_category;
  94.       typedef typename _Traits::value_type        value_type;
  95.       typedef typename _Traits::difference_type   difference_type;
  96.       typedef typename _Traits::reference         reference;
  97.       typedef typename _Traits::pointer           pointer;
  98.  
  99.       /// @post the iterator is singular and unattached
  100.       _Safe_iterator() : _M_current() { }
  101.  
  102.       /**
  103.        * @brief Safe iterator construction from an unsafe iterator and
  104.        * its sequence.
  105.        *
  106.        * @pre @p seq is not NULL
  107.        * @post this is not singular
  108.        */
  109.       _Safe_iterator(const _Iterator& __i, const _Sequence* __seq)
  110.       : _Safe_iterator_base(__seq, _M_constant()), _M_current(__i)
  111.       {
  112.     _GLIBCXX_DEBUG_VERIFY(! this->_M_singular(),
  113.                   _M_message(__msg_init_singular)
  114.                   ._M_iterator(*this, "this"));
  115.       }
  116.  
  117.       /**
  118.        * @brief Copy construction.
  119.        * @pre @p x is not singular
  120.        */
  121.       _Safe_iterator(const _Safe_iterator& __x)
  122.       : _Safe_iterator_base(__x, _M_constant()), _M_current(__x._M_current)
  123.       {
  124.     _GLIBCXX_DEBUG_VERIFY(!__x._M_singular(),
  125.                   _M_message(__msg_init_copy_singular)
  126.                   ._M_iterator(*this, "this")
  127.                   ._M_iterator(__x, "other"));
  128.       }
  129.  
  130.       /**
  131.        *  @brief Converting constructor from a mutable iterator to a
  132.        *  constant iterator.
  133.        *
  134.        *  @pre @p x is not singular
  135.       */
  136.       template<typename _MutableIterator>
  137.         _Safe_iterator(
  138.           const _Safe_iterator<_MutableIterator,
  139.           typename std::__enable_if<
  140.                      _Sequence,
  141.                      (std::__are_same<_MutableIterator,
  142.                       typename _Sequence::iterator::_Base_iterator>::_M_type)
  143.                    >::_M_type>& __x)
  144.     : _Safe_iterator_base(__x, _M_constant()), _M_current(__x.base())
  145.         {
  146.       _GLIBCXX_DEBUG_VERIFY(!__x._M_singular(),
  147.                 _M_message(__msg_init_const_singular)
  148.                 ._M_iterator(*this, "this")
  149.                 ._M_iterator(__x, "other"));
  150.     }
  151.  
  152.       /**
  153.        * @brief Copy assignment.
  154.        * @pre @p x is not singular
  155.        */
  156.       _Safe_iterator&
  157.       operator=(const _Safe_iterator& __x)
  158.       {
  159.     _GLIBCXX_DEBUG_VERIFY(!__x._M_singular(),
  160.                   _M_message(__msg_copy_singular)
  161.                   ._M_iterator(*this, "this")
  162.                   ._M_iterator(__x, "other"));
  163.     _M_current = __x._M_current;
  164.     this->_M_attach(static_cast<_Sequence*>(__x._M_sequence));
  165.     return *this;
  166.       }
  167.  
  168.       /**
  169.        *  @brief Iterator dereference.
  170.        *  @pre iterator is dereferenceable
  171.        */
  172.       reference
  173.       operator*() const
  174.       {
  175.  
  176.     _GLIBCXX_DEBUG_VERIFY(this->_M_dereferenceable(),
  177.                   _M_message(__msg_bad_deref)
  178.                   ._M_iterator(*this, "this"));
  179.     return *_M_current;
  180.       }
  181.  
  182.       /**
  183.        *  @brief Iterator dereference.
  184.        *  @pre iterator is dereferenceable
  185.        *  @todo Make this correct w.r.t. iterators that return proxies
  186.        *  @todo Use addressof() instead of & operator
  187.        */
  188.       pointer
  189.       operator->() const
  190.       {
  191.     _GLIBCXX_DEBUG_VERIFY(this->_M_dereferenceable(),
  192.                   _M_message(__msg_bad_deref)
  193.                   ._M_iterator(*this, "this"));
  194.     return &*_M_current;
  195.       }
  196.  
  197.       // ------ Input iterator requirements ------
  198.       /**
  199.        *  @brief Iterator preincrement
  200.        *  @pre iterator is incrementable
  201.        */
  202.       _Safe_iterator&
  203.       operator++()
  204.       {
  205.     _GLIBCXX_DEBUG_VERIFY(this->_M_incrementable(),
  206.                   _M_message(__msg_bad_inc)
  207.                   ._M_iterator(*this, "this"));
  208.     ++_M_current;
  209.     return *this;
  210.       }
  211.  
  212.       /**
  213.        *  @brief Iterator postincrement
  214.        *  @pre iterator is incrementable
  215.        */
  216.       _Safe_iterator
  217.       operator++(int)
  218.       {
  219.     _GLIBCXX_DEBUG_VERIFY(this->_M_incrementable(),
  220.                   _M_message(__msg_bad_inc)
  221.                   ._M_iterator(*this, "this"));
  222.     _Safe_iterator __tmp(*this);
  223.     ++_M_current;
  224.     return __tmp;
  225.       }
  226.  
  227.       // ------ Bidirectional iterator requirements ------
  228.       /**
  229.        *  @brief Iterator predecrement
  230.        *  @pre iterator is decrementable
  231.        */
  232.       _Safe_iterator&
  233.       operator--()
  234.       {
  235.     _GLIBCXX_DEBUG_VERIFY(this->_M_decrementable(),
  236.                   _M_message(__msg_bad_dec)
  237.                   ._M_iterator(*this, "this"));
  238.     --_M_current;
  239.     return *this;
  240.       }
  241.  
  242.       /**
  243.        *  @brief Iterator postdecrement
  244.        *  @pre iterator is decrementable
  245.        */
  246.       _Safe_iterator
  247.       operator--(int)
  248.       {
  249.     _GLIBCXX_DEBUG_VERIFY(this->_M_decrementable(),
  250.                   _M_message(__msg_bad_dec)
  251.                   ._M_iterator(*this, "this"));
  252.     _Safe_iterator __tmp(*this);
  253.     --_M_current;
  254.     return __tmp;
  255.       }
  256.  
  257.       // ------ Random access iterator requirements ------
  258.       reference
  259.       operator[](const difference_type& __n) const
  260.       {
  261.     _GLIBCXX_DEBUG_VERIFY(this->_M_can_advance(__n)
  262.                   && this->_M_can_advance(__n+1),
  263.                   _M_message(__msg_iter_subscript_oob)
  264.                   ._M_iterator(*this)._M_integer(__n));
  265.  
  266.     return _M_current[__n];
  267.       }
  268.  
  269.       _Safe_iterator&
  270.       operator+=(const difference_type& __n)
  271.       {
  272.     _GLIBCXX_DEBUG_VERIFY(this->_M_can_advance(__n),
  273.                   _M_message(__msg_advance_oob)
  274.                   ._M_iterator(*this)._M_integer(__n));
  275.     _M_current += __n;
  276.     return *this;
  277.       }
  278.  
  279.       _Safe_iterator
  280.       operator+(const difference_type& __n) const
  281.       {
  282.     _Safe_iterator __tmp(*this);
  283.     __tmp += __n;
  284.     return __tmp;
  285.       }
  286.  
  287.       _Safe_iterator&
  288.       operator-=(const difference_type& __n)
  289.       {
  290.     _GLIBCXX_DEBUG_VERIFY(this->_M_can_advance(-__n),
  291.                   _M_message(__msg_retreat_oob)
  292.                   ._M_iterator(*this)._M_integer(__n));
  293.     _M_current += -__n;
  294.     return *this;
  295.       }
  296.  
  297.       _Safe_iterator
  298.       operator-(const difference_type& __n) const
  299.       {
  300.     _Safe_iterator __tmp(*this);
  301.     __tmp -= __n;
  302.     return __tmp;
  303.       }
  304.  
  305.       // ------ Utilities ------
  306.       /**
  307.        * @brief Return the underlying iterator
  308.        */
  309.       _Iterator
  310.       base() const { return _M_current; }
  311.  
  312.       /**
  313.        * @brief Conversion to underlying non-debug iterator to allow
  314.        * better interaction with non-debug containers.
  315.        */
  316.       operator _Iterator() const { return _M_current; }
  317.  
  318.       /** Attach iterator to the given sequence. */
  319.       void
  320.       _M_attach(const _Sequence* __seq)
  321.       {
  322.     _Safe_iterator_base::_M_attach(const_cast<_Sequence*>(__seq),
  323.                        _M_constant());
  324.       }
  325.  
  326.       /** Invalidate the iterator, making it singular. */
  327.       void
  328.       _M_invalidate();
  329.  
  330.       /// Is the iterator dereferenceable?
  331.       bool
  332.       _M_dereferenceable() const
  333.       { return !this->_M_singular() && !_M_is_end(); }
  334.  
  335.       /// Is the iterator incrementable?
  336.       bool
  337.       _M_incrementable() const { return this->_M_dereferenceable(); }
  338.  
  339.       // Is the iterator decrementable?
  340.       bool
  341.       _M_decrementable() const { return !_M_singular() && !_M_is_begin(); }
  342.  
  343.       // Can we advance the iterator @p __n steps (@p __n may be negative)
  344.       bool
  345.       _M_can_advance(const difference_type& __n) const;
  346.  
  347.       // Is the iterator range [*this, __rhs) valid?
  348.       template<typename _Other>
  349.         bool
  350.         _M_valid_range(const _Safe_iterator<_Other, _Sequence>& __rhs) const;
  351.  
  352.       // The sequence this iterator references.
  353.       const _Sequence*
  354.       _M_get_sequence() const
  355.       { return static_cast<const _Sequence*>(_M_sequence); }
  356.  
  357.     /** Determine the distance between two iterators with some known
  358.      *    precision.
  359.     */
  360.     template<typename _Iterator1, typename _Iterator2>
  361.       static pair<difference_type, _Distance_precision>
  362.       _M_get_distance(const _Iterator1& __lhs, const _Iterator2& __rhs)
  363.       {
  364.         typedef typename iterator_traits<_Iterator1>::iterator_category
  365.       _Category;
  366.         return _M_get_distance(__lhs, __rhs, _Category());
  367.       }
  368.  
  369.     template<typename _Iterator1, typename _Iterator2>
  370.       static pair<difference_type, _Distance_precision>
  371.       _M_get_distance(const _Iterator1& __lhs, const _Iterator2& __rhs,
  372.               std::random_access_iterator_tag)
  373.       {
  374.         return std::make_pair(__rhs.base() - __lhs.base(), __dp_exact);
  375.       }
  376.  
  377.     template<typename _Iterator1, typename _Iterator2>
  378.       static pair<difference_type, _Distance_precision>
  379.       _M_get_distance(const _Iterator1& __lhs, const _Iterator2& __rhs,
  380.             std::forward_iterator_tag)
  381.       {
  382.         return std::make_pair(__lhs.base() == __rhs.base()? 0 : 1,
  383.                   __dp_equality);
  384.       }
  385.  
  386.       /// Is this iterator equal to the sequence's begin() iterator?
  387.       bool _M_is_begin() const
  388.       {    return *this == static_cast<const _Sequence*>(_M_sequence)->begin(); }
  389.  
  390.       /// Is this iterator equal to the sequence's end() iterator?
  391.       bool _M_is_end() const
  392.       {    return *this == static_cast<const _Sequence*>(_M_sequence)->end(); }
  393.     };
  394.  
  395.   template<typename _IteratorL, typename _IteratorR, typename _Sequence>
  396.     inline bool
  397.     operator==(const _Safe_iterator<_IteratorL, _Sequence>& __lhs,
  398.            const _Safe_iterator<_IteratorR, _Sequence>& __rhs)
  399.     {
  400.       _GLIBCXX_DEBUG_VERIFY(! __lhs._M_singular() && ! __rhs._M_singular(),
  401.                 _M_message(__msg_iter_compare_bad)
  402.                 ._M_iterator(__lhs, "lhs")
  403.                 ._M_iterator(__rhs, "rhs"));
  404.       _GLIBCXX_DEBUG_VERIFY(__lhs._M_can_compare(__rhs),
  405.                 _M_message(__msg_compare_different)
  406.                 ._M_iterator(__lhs, "lhs")
  407.                 ._M_iterator(__rhs, "rhs"));
  408.       return __lhs.base() == __rhs.base();
  409.     }
  410.  
  411.   template<typename _Iterator, typename _Sequence>
  412.     inline bool
  413.     operator==(const _Safe_iterator<_Iterator, _Sequence>& __lhs,
  414.                const _Safe_iterator<_Iterator, _Sequence>& __rhs)
  415.     {
  416.       _GLIBCXX_DEBUG_VERIFY(! __lhs._M_singular() && ! __rhs._M_singular(),
  417.                 _M_message(__msg_iter_compare_bad)
  418.                 ._M_iterator(__lhs, "lhs")
  419.                 ._M_iterator(__rhs, "rhs"));
  420.       _GLIBCXX_DEBUG_VERIFY(__lhs._M_can_compare(__rhs),
  421.                 _M_message(__msg_compare_different)
  422.                 ._M_iterator(__lhs, "lhs")
  423.                 ._M_iterator(__rhs, "rhs"));
  424.       return __lhs.base() == __rhs.base();
  425.     }
  426.  
  427.   template<typename _IteratorL, typename _IteratorR, typename _Sequence>
  428.     inline bool
  429.     operator!=(const _Safe_iterator<_IteratorL, _Sequence>& __lhs,
  430.            const _Safe_iterator<_IteratorR, _Sequence>& __rhs)
  431.     {
  432.       _GLIBCXX_DEBUG_VERIFY(! __lhs._M_singular() && ! __rhs._M_singular(),
  433.                 _M_message(__msg_iter_compare_bad)
  434.                 ._M_iterator(__lhs, "lhs")
  435.                 ._M_iterator(__rhs, "rhs"));
  436.       _GLIBCXX_DEBUG_VERIFY(__lhs._M_can_compare(__rhs),
  437.                 _M_message(__msg_compare_different)
  438.                 ._M_iterator(__lhs, "lhs")
  439.                 ._M_iterator(__rhs, "rhs"));
  440.       return __lhs.base() != __rhs.base();
  441.     }
  442.  
  443.   template<typename _Iterator, typename _Sequence>
  444.     inline bool
  445.     operator!=(const _Safe_iterator<_Iterator, _Sequence>& __lhs,
  446.                const _Safe_iterator<_Iterator, _Sequence>& __rhs)
  447.     {
  448.       _GLIBCXX_DEBUG_VERIFY(! __lhs._M_singular() && ! __rhs._M_singular(),
  449.                 _M_message(__msg_iter_compare_bad)
  450.                 ._M_iterator(__lhs, "lhs")
  451.                 ._M_iterator(__rhs, "rhs"));
  452.       _GLIBCXX_DEBUG_VERIFY(__lhs._M_can_compare(__rhs),
  453.                 _M_message(__msg_compare_different)
  454.                 ._M_iterator(__lhs, "lhs")
  455.                 ._M_iterator(__rhs, "rhs"));
  456.       return __lhs.base() != __rhs.base();
  457.     }
  458.  
  459.   template<typename _IteratorL, typename _IteratorR, typename _Sequence>
  460.     inline bool
  461.     operator<(const _Safe_iterator<_IteratorL, _Sequence>& __lhs,
  462.           const _Safe_iterator<_IteratorR, _Sequence>& __rhs)
  463.     {
  464.       _GLIBCXX_DEBUG_VERIFY(! __lhs._M_singular() && ! __rhs._M_singular(),
  465.                 _M_message(__msg_iter_order_bad)
  466.                 ._M_iterator(__lhs, "lhs")
  467.                 ._M_iterator(__rhs, "rhs"));
  468.       _GLIBCXX_DEBUG_VERIFY(__lhs._M_can_compare(__rhs),
  469.                 _M_message(__msg_order_different)
  470.                 ._M_iterator(__lhs, "lhs")
  471.                 ._M_iterator(__rhs, "rhs"));
  472.       return __lhs.base() < __rhs.base();
  473.     }
  474.  
  475.   template<typename _Iterator, typename _Sequence>
  476.     inline bool
  477.     operator<(const _Safe_iterator<_Iterator, _Sequence>& __lhs,
  478.           const _Safe_iterator<_Iterator, _Sequence>& __rhs)
  479.     {
  480.       _GLIBCXX_DEBUG_VERIFY(! __lhs._M_singular() && ! __rhs._M_singular(),
  481.                 _M_message(__msg_iter_order_bad)
  482.                 ._M_iterator(__lhs, "lhs")
  483.                 ._M_iterator(__rhs, "rhs"));
  484.       _GLIBCXX_DEBUG_VERIFY(__lhs._M_can_compare(__rhs),
  485.                 _M_message(__msg_order_different)
  486.                 ._M_iterator(__lhs, "lhs")
  487.                 ._M_iterator(__rhs, "rhs"));
  488.       return __lhs.base() < __rhs.base();
  489.     }
  490.  
  491.   template<typename _IteratorL, typename _IteratorR, typename _Sequence>
  492.     inline bool
  493.     operator<=(const _Safe_iterator<_IteratorL, _Sequence>& __lhs,
  494.            const _Safe_iterator<_IteratorR, _Sequence>& __rhs)
  495.     {
  496.       _GLIBCXX_DEBUG_VERIFY(! __lhs._M_singular() && ! __rhs._M_singular(),
  497.                 _M_message(__msg_iter_order_bad)
  498.                 ._M_iterator(__lhs, "lhs")
  499.                 ._M_iterator(__rhs, "rhs"));
  500.       _GLIBCXX_DEBUG_VERIFY(__lhs._M_can_compare(__rhs),
  501.                 _M_message(__msg_order_different)
  502.                 ._M_iterator(__lhs, "lhs")
  503.                 ._M_iterator(__rhs, "rhs"));
  504.       return __lhs.base() <= __rhs.base();
  505.     }
  506.  
  507.   template<typename _Iterator, typename _Sequence>
  508.     inline bool
  509.     operator<=(const _Safe_iterator<_Iterator, _Sequence>& __lhs,
  510.                const _Safe_iterator<_Iterator, _Sequence>& __rhs)
  511.     {
  512.       _GLIBCXX_DEBUG_VERIFY(! __lhs._M_singular() && ! __rhs._M_singular(),
  513.                 _M_message(__msg_iter_order_bad)
  514.                 ._M_iterator(__lhs, "lhs")
  515.                 ._M_iterator(__rhs, "rhs"));
  516.       _GLIBCXX_DEBUG_VERIFY(__lhs._M_can_compare(__rhs),
  517.                 _M_message(__msg_order_different)
  518.                 ._M_iterator(__lhs, "lhs")
  519.                 ._M_iterator(__rhs, "rhs"));
  520.       return __lhs.base() <= __rhs.base();
  521.     }
  522.  
  523.   template<typename _IteratorL, typename _IteratorR, typename _Sequence>
  524.     inline bool
  525.     operator>(const _Safe_iterator<_IteratorL, _Sequence>& __lhs,
  526.           const _Safe_iterator<_IteratorR, _Sequence>& __rhs)
  527.     {
  528.       _GLIBCXX_DEBUG_VERIFY(! __lhs._M_singular() && ! __rhs._M_singular(),
  529.                 _M_message(__msg_iter_order_bad)
  530.                 ._M_iterator(__lhs, "lhs")
  531.                 ._M_iterator(__rhs, "rhs"));
  532.       _GLIBCXX_DEBUG_VERIFY(__lhs._M_can_compare(__rhs),
  533.                 _M_message(__msg_order_different)
  534.                 ._M_iterator(__lhs, "lhs")
  535.                 ._M_iterator(__rhs, "rhs"));
  536.       return __lhs.base() > __rhs.base();
  537.     }
  538.  
  539.   template<typename _Iterator, typename _Sequence>
  540.     inline bool
  541.     operator>(const _Safe_iterator<_Iterator, _Sequence>& __lhs,
  542.           const _Safe_iterator<_Iterator, _Sequence>& __rhs)
  543.     {
  544.       _GLIBCXX_DEBUG_VERIFY(! __lhs._M_singular() && ! __rhs._M_singular(),
  545.                 _M_message(__msg_iter_order_bad)
  546.                 ._M_iterator(__lhs, "lhs")
  547.                 ._M_iterator(__rhs, "rhs"));
  548.       _GLIBCXX_DEBUG_VERIFY(__lhs._M_can_compare(__rhs),
  549.                 _M_message(__msg_order_different)
  550.                 ._M_iterator(__lhs, "lhs")
  551.                 ._M_iterator(__rhs, "rhs"));
  552.       return __lhs.base() > __rhs.base();
  553.     }
  554.  
  555.   template<typename _IteratorL, typename _IteratorR, typename _Sequence>
  556.     inline bool
  557.     operator>=(const _Safe_iterator<_IteratorL, _Sequence>& __lhs,
  558.            const _Safe_iterator<_IteratorR, _Sequence>& __rhs)
  559.     {
  560.       _GLIBCXX_DEBUG_VERIFY(! __lhs._M_singular() && ! __rhs._M_singular(),
  561.                 _M_message(__msg_iter_order_bad)
  562.                 ._M_iterator(__lhs, "lhs")
  563.                 ._M_iterator(__rhs, "rhs"));
  564.       _GLIBCXX_DEBUG_VERIFY(__lhs._M_can_compare(__rhs),
  565.                 _M_message(__msg_order_different)
  566.                 ._M_iterator(__lhs, "lhs")
  567.                 ._M_iterator(__rhs, "rhs"));
  568.       return __lhs.base() >= __rhs.base();
  569.     }
  570.  
  571.   template<typename _Iterator, typename _Sequence>
  572.     inline bool
  573.     operator>=(const _Safe_iterator<_Iterator, _Sequence>& __lhs,
  574.                const _Safe_iterator<_Iterator, _Sequence>& __rhs)
  575.     {
  576.       _GLIBCXX_DEBUG_VERIFY(! __lhs._M_singular() && ! __rhs._M_singular(),
  577.                 _M_message(__msg_iter_order_bad)
  578.                 ._M_iterator(__lhs, "lhs")
  579.                 ._M_iterator(__rhs, "rhs"));
  580.       _GLIBCXX_DEBUG_VERIFY(__lhs._M_can_compare(__rhs),
  581.                 _M_message(__msg_order_different)
  582.                 ._M_iterator(__lhs, "lhs")
  583.                 ._M_iterator(__rhs, "rhs"));
  584.       return __lhs.base() >= __rhs.base();
  585.     }
  586.  
  587.   // _GLIBCXX_RESOLVE_LIB_DEFECTS
  588.   // According to the resolution of DR179 not only the various comparison
  589.   // operators but also operator- must accept mixed iterator/const_iterator
  590.   // parameters.
  591.   template<typename _IteratorL, typename _IteratorR, typename _Sequence>
  592.     inline typename _Safe_iterator<_IteratorL, _Sequence>::difference_type
  593.     operator-(const _Safe_iterator<_IteratorL, _Sequence>& __lhs,
  594.           const _Safe_iterator<_IteratorR, _Sequence>& __rhs)
  595.     {
  596.       _GLIBCXX_DEBUG_VERIFY(! __lhs._M_singular() && ! __rhs._M_singular(),
  597.                 _M_message(__msg_distance_bad)
  598.                 ._M_iterator(__lhs, "lhs")
  599.                 ._M_iterator(__rhs, "rhs"));
  600.       _GLIBCXX_DEBUG_VERIFY(__lhs._M_can_compare(__rhs),
  601.                 _M_message(__msg_distance_different)
  602.                 ._M_iterator(__lhs, "lhs")
  603.                 ._M_iterator(__rhs, "rhs"));
  604.       return __lhs.base() - __rhs.base();
  605.     }
  606.  
  607.   template<typename _Iterator, typename _Sequence>
  608.     inline _Safe_iterator<_Iterator, _Sequence>
  609.     operator+(typename _Safe_iterator<_Iterator,_Sequence>::difference_type __n,
  610.           const _Safe_iterator<_Iterator, _Sequence>& __i)
  611.     { return __i + __n; }
  612. } // namespace __gnu_debug
  613.  
  614. #ifndef _GLIBCXX_EXPORT_TEMPLATE
  615. #  include <debug/safe_iterator.tcc>
  616. #endif
  617.  
  618. #endif
  619.