1*e4b17023SJohn Marino // Safe iterator implementation -*- C++ -*- 2*e4b17023SJohn Marino 3*e4b17023SJohn Marino // Copyright (C) 2011 Free Software Foundation, Inc. 4*e4b17023SJohn Marino // 5*e4b17023SJohn Marino // This file is part of the GNU ISO C++ Library. This library is free 6*e4b17023SJohn Marino // software; you can redistribute it and/or modify it under the 7*e4b17023SJohn Marino // terms of the GNU General Public License as published by the 8*e4b17023SJohn Marino // Free Software Foundation; either version 3, or (at your option) 9*e4b17023SJohn Marino // any later version. 10*e4b17023SJohn Marino 11*e4b17023SJohn Marino // This library is distributed in the hope that it will be useful, 12*e4b17023SJohn Marino // but WITHOUT ANY WARRANTY; without even the implied warranty of 13*e4b17023SJohn Marino // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14*e4b17023SJohn Marino // GNU General Public License for more details. 15*e4b17023SJohn Marino 16*e4b17023SJohn Marino // Under Section 7 of GPL version 3, you are granted additional 17*e4b17023SJohn Marino // permissions described in the GCC Runtime Library Exception, version 18*e4b17023SJohn Marino // 3.1, as published by the Free Software Foundation. 19*e4b17023SJohn Marino 20*e4b17023SJohn Marino // You should have received a copy of the GNU General Public License and 21*e4b17023SJohn Marino // a copy of the GCC Runtime Library Exception along with this program; 22*e4b17023SJohn Marino // see the files COPYING3 and COPYING.RUNTIME respectively. If not, see 23*e4b17023SJohn Marino // <http://www.gnu.org/licenses/>. 24*e4b17023SJohn Marino 25*e4b17023SJohn Marino /** @file debug/safe_local_iterator.h 26*e4b17023SJohn Marino * This file is a GNU debug extension to the Standard C++ Library. 27*e4b17023SJohn Marino */ 28*e4b17023SJohn Marino 29*e4b17023SJohn Marino #ifndef _GLIBCXX_DEBUG_SAFE_LOCAL_ITERATOR_H 30*e4b17023SJohn Marino #define _GLIBCXX_DEBUG_SAFE_LOCAL_ITERATOR_H 1 31*e4b17023SJohn Marino 32*e4b17023SJohn Marino #include <debug/debug.h> 33*e4b17023SJohn Marino #include <debug/macros.h> 34*e4b17023SJohn Marino #include <debug/functions.h> 35*e4b17023SJohn Marino #include <debug/safe_unordered_base.h> 36*e4b17023SJohn Marino #include <ext/type_traits.h> 37*e4b17023SJohn Marino 38*e4b17023SJohn Marino namespace __gnu_debug 39*e4b17023SJohn Marino { 40*e4b17023SJohn Marino /** \brief Safe iterator wrapper. 41*e4b17023SJohn Marino * 42*e4b17023SJohn Marino * The class template %_Safe_local_iterator is a wrapper around an 43*e4b17023SJohn Marino * iterator that tracks the iterator's movement among sequences and 44*e4b17023SJohn Marino * checks that operations performed on the "safe" iterator are 45*e4b17023SJohn Marino * legal. In additional to the basic iterator operations (which are 46*e4b17023SJohn Marino * validated, and then passed to the underlying iterator), 47*e4b17023SJohn Marino * %_Safe_local_iterator has member functions for iterator invalidation, 48*e4b17023SJohn Marino * attaching/detaching the iterator from sequences, and querying 49*e4b17023SJohn Marino * the iterator's state. 50*e4b17023SJohn Marino */ 51*e4b17023SJohn Marino template<typename _Iterator, typename _Sequence> 52*e4b17023SJohn Marino class _Safe_local_iterator : public _Safe_local_iterator_base 53*e4b17023SJohn Marino { 54*e4b17023SJohn Marino typedef _Safe_local_iterator _Self; 55*e4b17023SJohn Marino typedef typename _Sequence::size_type size_type; 56*e4b17023SJohn Marino 57*e4b17023SJohn Marino /// The underlying iterator 58*e4b17023SJohn Marino _Iterator _M_current; 59*e4b17023SJohn Marino 60*e4b17023SJohn Marino /// The bucket this local iterator belongs to 61*e4b17023SJohn Marino size_type _M_bucket; 62*e4b17023SJohn Marino 63*e4b17023SJohn Marino /// Determine if this is a constant iterator. 64*e4b17023SJohn Marino bool _M_constant()65*e4b17023SJohn Marino _M_constant() const 66*e4b17023SJohn Marino { 67*e4b17023SJohn Marino typedef typename _Sequence::const_local_iterator const_iterator; 68*e4b17023SJohn Marino return std::__are_same<const_iterator, _Safe_local_iterator>::__value; 69*e4b17023SJohn Marino } 70*e4b17023SJohn Marino 71*e4b17023SJohn Marino typedef std::iterator_traits<_Iterator> _Traits; 72*e4b17023SJohn Marino 73*e4b17023SJohn Marino public: 74*e4b17023SJohn Marino typedef _Iterator iterator_type; 75*e4b17023SJohn Marino typedef typename _Traits::iterator_category iterator_category; 76*e4b17023SJohn Marino typedef typename _Traits::value_type value_type; 77*e4b17023SJohn Marino typedef typename _Traits::difference_type difference_type; 78*e4b17023SJohn Marino typedef typename _Traits::reference reference; 79*e4b17023SJohn Marino typedef typename _Traits::pointer pointer; 80*e4b17023SJohn Marino 81*e4b17023SJohn Marino /// @post the iterator is singular and unattached _Safe_local_iterator()82*e4b17023SJohn Marino _Safe_local_iterator() : _M_current() { } 83*e4b17023SJohn Marino 84*e4b17023SJohn Marino /** 85*e4b17023SJohn Marino * @brief Safe iterator construction from an unsafe iterator and 86*e4b17023SJohn Marino * its sequence. 87*e4b17023SJohn Marino * 88*e4b17023SJohn Marino * @pre @p seq is not NULL 89*e4b17023SJohn Marino * @post this is not singular 90*e4b17023SJohn Marino */ _Safe_local_iterator(const _Iterator & __i,size_type __bucket,const _Sequence * __seq)91*e4b17023SJohn Marino _Safe_local_iterator(const _Iterator& __i, size_type __bucket, 92*e4b17023SJohn Marino const _Sequence* __seq) 93*e4b17023SJohn Marino : _Safe_local_iterator_base(__seq, _M_constant()), _M_current(__i), 94*e4b17023SJohn Marino _M_bucket(__bucket) 95*e4b17023SJohn Marino { 96*e4b17023SJohn Marino _GLIBCXX_DEBUG_VERIFY(!this->_M_singular(), 97*e4b17023SJohn Marino _M_message(__msg_init_singular) 98*e4b17023SJohn Marino ._M_iterator(*this, "this")); 99*e4b17023SJohn Marino } 100*e4b17023SJohn Marino 101*e4b17023SJohn Marino /** 102*e4b17023SJohn Marino * @brief Copy construction. 103*e4b17023SJohn Marino */ _Safe_local_iterator(const _Safe_local_iterator & __x)104*e4b17023SJohn Marino _Safe_local_iterator(const _Safe_local_iterator& __x) 105*e4b17023SJohn Marino : _Safe_local_iterator_base(__x, _M_constant()), 106*e4b17023SJohn Marino _M_current(__x._M_current), _M_bucket(__x._M_bucket) 107*e4b17023SJohn Marino { 108*e4b17023SJohn Marino // _GLIBCXX_RESOLVE_LIB_DEFECTS 109*e4b17023SJohn Marino // DR 408. Is vector<reverse_iterator<char*> > forbidden? 110*e4b17023SJohn Marino _GLIBCXX_DEBUG_VERIFY(!__x._M_singular() 111*e4b17023SJohn Marino || __x._M_current == _Iterator(), 112*e4b17023SJohn Marino _M_message(__msg_init_copy_singular) 113*e4b17023SJohn Marino ._M_iterator(*this, "this") 114*e4b17023SJohn Marino ._M_iterator(__x, "other")); 115*e4b17023SJohn Marino } 116*e4b17023SJohn Marino 117*e4b17023SJohn Marino /** 118*e4b17023SJohn Marino * @brief Converting constructor from a mutable iterator to a 119*e4b17023SJohn Marino * constant iterator. 120*e4b17023SJohn Marino */ 121*e4b17023SJohn Marino template<typename _MutableIterator> _Safe_local_iterator(const _Safe_local_iterator<_MutableIterator,typename __gnu_cxx::__enable_if<std::__are_same<_MutableIterator,typename _Sequence::local_iterator::iterator_type>::__value,_Sequence>::__type> & __x)122*e4b17023SJohn Marino _Safe_local_iterator( 123*e4b17023SJohn Marino const _Safe_local_iterator<_MutableIterator, 124*e4b17023SJohn Marino typename __gnu_cxx::__enable_if<std::__are_same< 125*e4b17023SJohn Marino _MutableIterator, 126*e4b17023SJohn Marino typename _Sequence::local_iterator::iterator_type>::__value, 127*e4b17023SJohn Marino _Sequence>::__type>& __x) 128*e4b17023SJohn Marino : _Safe_local_iterator_base(__x, _M_constant()), 129*e4b17023SJohn Marino _M_current(__x.base()), _M_bucket(__x._M_bucket) 130*e4b17023SJohn Marino { 131*e4b17023SJohn Marino // _GLIBCXX_RESOLVE_LIB_DEFECTS 132*e4b17023SJohn Marino // DR 408. Is vector<reverse_iterator<char*> > forbidden? 133*e4b17023SJohn Marino _GLIBCXX_DEBUG_VERIFY(!__x._M_singular() 134*e4b17023SJohn Marino || __x.base() == _Iterator(), 135*e4b17023SJohn Marino _M_message(__msg_init_const_singular) 136*e4b17023SJohn Marino ._M_iterator(*this, "this") 137*e4b17023SJohn Marino ._M_iterator(__x, "other")); 138*e4b17023SJohn Marino } 139*e4b17023SJohn Marino 140*e4b17023SJohn Marino /** 141*e4b17023SJohn Marino * @brief Copy assignment. 142*e4b17023SJohn Marino */ 143*e4b17023SJohn Marino _Safe_local_iterator& 144*e4b17023SJohn Marino operator=(const _Safe_local_iterator& __x) 145*e4b17023SJohn Marino { 146*e4b17023SJohn Marino // _GLIBCXX_RESOLVE_LIB_DEFECTS 147*e4b17023SJohn Marino // DR 408. Is vector<reverse_iterator<char*> > forbidden? 148*e4b17023SJohn Marino _GLIBCXX_DEBUG_VERIFY(!__x._M_singular() 149*e4b17023SJohn Marino || __x._M_current == _Iterator(), 150*e4b17023SJohn Marino _M_message(__msg_copy_singular) 151*e4b17023SJohn Marino ._M_iterator(*this, "this") 152*e4b17023SJohn Marino ._M_iterator(__x, "other")); 153*e4b17023SJohn Marino _M_current = __x._M_current; 154*e4b17023SJohn Marino _M_bucket = __x._M_bucket; 155*e4b17023SJohn Marino this->_M_attach(__x._M_sequence); 156*e4b17023SJohn Marino return *this; 157*e4b17023SJohn Marino } 158*e4b17023SJohn Marino 159*e4b17023SJohn Marino /** 160*e4b17023SJohn Marino * @brief Iterator dereference. 161*e4b17023SJohn Marino * @pre iterator is dereferenceable 162*e4b17023SJohn Marino */ 163*e4b17023SJohn Marino reference 164*e4b17023SJohn Marino operator*() const 165*e4b17023SJohn Marino { 166*e4b17023SJohn Marino _GLIBCXX_DEBUG_VERIFY(this->_M_dereferenceable(), 167*e4b17023SJohn Marino _M_message(__msg_bad_deref) 168*e4b17023SJohn Marino ._M_iterator(*this, "this")); 169*e4b17023SJohn Marino return *_M_current; 170*e4b17023SJohn Marino } 171*e4b17023SJohn Marino 172*e4b17023SJohn Marino /** 173*e4b17023SJohn Marino * @brief Iterator dereference. 174*e4b17023SJohn Marino * @pre iterator is dereferenceable 175*e4b17023SJohn Marino * @todo Make this correct w.r.t. iterators that return proxies 176*e4b17023SJohn Marino * @todo Use addressof() instead of & operator 177*e4b17023SJohn Marino */ 178*e4b17023SJohn Marino pointer 179*e4b17023SJohn Marino operator->() const 180*e4b17023SJohn Marino { 181*e4b17023SJohn Marino _GLIBCXX_DEBUG_VERIFY(this->_M_dereferenceable(), 182*e4b17023SJohn Marino _M_message(__msg_bad_deref) 183*e4b17023SJohn Marino ._M_iterator(*this, "this")); 184*e4b17023SJohn Marino return &*_M_current; 185*e4b17023SJohn Marino } 186*e4b17023SJohn Marino 187*e4b17023SJohn Marino // ------ Input iterator requirements ------ 188*e4b17023SJohn Marino /** 189*e4b17023SJohn Marino * @brief Iterator preincrement 190*e4b17023SJohn Marino * @pre iterator is incrementable 191*e4b17023SJohn Marino */ 192*e4b17023SJohn Marino _Safe_local_iterator& 193*e4b17023SJohn Marino operator++() 194*e4b17023SJohn Marino { 195*e4b17023SJohn Marino _GLIBCXX_DEBUG_VERIFY(this->_M_incrementable(), 196*e4b17023SJohn Marino _M_message(__msg_bad_inc) 197*e4b17023SJohn Marino ._M_iterator(*this, "this")); 198*e4b17023SJohn Marino ++_M_current; 199*e4b17023SJohn Marino return *this; 200*e4b17023SJohn Marino } 201*e4b17023SJohn Marino 202*e4b17023SJohn Marino /** 203*e4b17023SJohn Marino * @brief Iterator postincrement 204*e4b17023SJohn Marino * @pre iterator is incrementable 205*e4b17023SJohn Marino */ 206*e4b17023SJohn Marino _Safe_local_iterator 207*e4b17023SJohn Marino operator++(int) 208*e4b17023SJohn Marino { 209*e4b17023SJohn Marino _GLIBCXX_DEBUG_VERIFY(this->_M_incrementable(), 210*e4b17023SJohn Marino _M_message(__msg_bad_inc) 211*e4b17023SJohn Marino ._M_iterator(*this, "this")); 212*e4b17023SJohn Marino _Safe_local_iterator __tmp(*this); 213*e4b17023SJohn Marino ++_M_current; 214*e4b17023SJohn Marino return __tmp; 215*e4b17023SJohn Marino } 216*e4b17023SJohn Marino 217*e4b17023SJohn Marino // ------ Utilities ------ 218*e4b17023SJohn Marino /** 219*e4b17023SJohn Marino * @brief Return the underlying iterator 220*e4b17023SJohn Marino */ 221*e4b17023SJohn Marino _Iterator base()222*e4b17023SJohn Marino base() const { return _M_current; } 223*e4b17023SJohn Marino 224*e4b17023SJohn Marino /** 225*e4b17023SJohn Marino * @brief Return the bucket 226*e4b17023SJohn Marino */ 227*e4b17023SJohn Marino size_type bucket()228*e4b17023SJohn Marino bucket() const { return _M_bucket; } 229*e4b17023SJohn Marino 230*e4b17023SJohn Marino /** 231*e4b17023SJohn Marino * @brief Conversion to underlying non-debug iterator to allow 232*e4b17023SJohn Marino * better interaction with non-debug containers. 233*e4b17023SJohn Marino */ _Iterator()234*e4b17023SJohn Marino operator _Iterator() const { return _M_current; } 235*e4b17023SJohn Marino 236*e4b17023SJohn Marino /** Attach iterator to the given sequence. */ 237*e4b17023SJohn Marino void _M_attach(_Safe_sequence_base * __seq)238*e4b17023SJohn Marino _M_attach(_Safe_sequence_base* __seq) 239*e4b17023SJohn Marino { _Safe_iterator_base::_M_attach(__seq, _M_constant()); } 240*e4b17023SJohn Marino 241*e4b17023SJohn Marino /** Likewise, but not thread-safe. */ 242*e4b17023SJohn Marino void _M_attach_single(_Safe_sequence_base * __seq)243*e4b17023SJohn Marino _M_attach_single(_Safe_sequence_base* __seq) 244*e4b17023SJohn Marino { _Safe_iterator_base::_M_attach_single(__seq, _M_constant()); } 245*e4b17023SJohn Marino 246*e4b17023SJohn Marino /// Is the iterator dereferenceable? 247*e4b17023SJohn Marino bool _M_dereferenceable()248*e4b17023SJohn Marino _M_dereferenceable() const 249*e4b17023SJohn Marino { return !this->_M_singular() && !_M_is_end(); } 250*e4b17023SJohn Marino 251*e4b17023SJohn Marino /// Is the iterator incrementable? 252*e4b17023SJohn Marino bool _M_incrementable()253*e4b17023SJohn Marino _M_incrementable() const 254*e4b17023SJohn Marino { return !this->_M_singular() && !_M_is_end(); } 255*e4b17023SJohn Marino 256*e4b17023SJohn Marino // Is the iterator range [*this, __rhs) valid? 257*e4b17023SJohn Marino template<typename _Other> 258*e4b17023SJohn Marino bool 259*e4b17023SJohn Marino _M_valid_range(const _Safe_local_iterator<_Other, 260*e4b17023SJohn Marino _Sequence>& __rhs) const; 261*e4b17023SJohn Marino 262*e4b17023SJohn Marino // The sequence this iterator references. 263*e4b17023SJohn Marino const _Sequence* _M_get_sequence()264*e4b17023SJohn Marino _M_get_sequence() const 265*e4b17023SJohn Marino { return static_cast<const _Sequence*>(_M_sequence); } 266*e4b17023SJohn Marino 267*e4b17023SJohn Marino /// Is this iterator equal to the sequence's begin() iterator? _M_is_begin()268*e4b17023SJohn Marino bool _M_is_begin() const 269*e4b17023SJohn Marino { return base() == _M_get_sequence()->_M_base().begin(_M_bucket); } 270*e4b17023SJohn Marino 271*e4b17023SJohn Marino /// Is this iterator equal to the sequence's end() iterator? _M_is_end()272*e4b17023SJohn Marino bool _M_is_end() const 273*e4b17023SJohn Marino { return base() == _M_get_sequence()->_M_base().end(_M_bucket); } 274*e4b17023SJohn Marino 275*e4b17023SJohn Marino /// Is this iterator part of the same bucket as the other one? 276*e4b17023SJohn Marino template <typename _Other> _M_in_same_bucket(const _Safe_local_iterator<_Other,_Sequence> & __other)277*e4b17023SJohn Marino bool _M_in_same_bucket(const _Safe_local_iterator<_Other, 278*e4b17023SJohn Marino _Sequence>& __other) const 279*e4b17023SJohn Marino { return _M_bucket == __other.bucket(); } 280*e4b17023SJohn Marino }; 281*e4b17023SJohn Marino 282*e4b17023SJohn Marino template<typename _IteratorL, typename _IteratorR, typename _Sequence> 283*e4b17023SJohn Marino inline bool 284*e4b17023SJohn Marino operator==(const _Safe_local_iterator<_IteratorL, _Sequence>& __lhs, 285*e4b17023SJohn Marino const _Safe_local_iterator<_IteratorR, _Sequence>& __rhs) 286*e4b17023SJohn Marino { 287*e4b17023SJohn Marino _GLIBCXX_DEBUG_VERIFY(! __lhs._M_singular() && ! __rhs._M_singular(), 288*e4b17023SJohn Marino _M_message(__msg_iter_compare_bad) 289*e4b17023SJohn Marino ._M_iterator(__lhs, "lhs") 290*e4b17023SJohn Marino ._M_iterator(__rhs, "rhs")); 291*e4b17023SJohn Marino _GLIBCXX_DEBUG_VERIFY(__lhs._M_can_compare(__rhs), 292*e4b17023SJohn Marino _M_message(__msg_compare_different) 293*e4b17023SJohn Marino ._M_iterator(__lhs, "lhs") 294*e4b17023SJohn Marino ._M_iterator(__rhs, "rhs")); 295*e4b17023SJohn Marino _GLIBCXX_DEBUG_VERIFY(__lhs._M_can_compare(__rhs), 296*e4b17023SJohn Marino _M_message(__msg_compare_different) 297*e4b17023SJohn Marino ._M_iterator(__lhs, "lhs") 298*e4b17023SJohn Marino ._M_iterator(__rhs, "rhs")); 299*e4b17023SJohn Marino _GLIBCXX_DEBUG_VERIFY(__lhs._M_in_same_bucket(__rhs), 300*e4b17023SJohn Marino _M_message(__msg_local_iter_compare_bad) 301*e4b17023SJohn Marino ._M_iterator(__lhs, "lhs") 302*e4b17023SJohn Marino ._M_iterator(__rhs, "rhs")); 303*e4b17023SJohn Marino return __lhs.base() == __rhs.base(); 304*e4b17023SJohn Marino } 305*e4b17023SJohn Marino 306*e4b17023SJohn Marino template<typename _Iterator, typename _Sequence> 307*e4b17023SJohn Marino inline bool 308*e4b17023SJohn Marino operator==(const _Safe_local_iterator<_Iterator, _Sequence>& __lhs, 309*e4b17023SJohn Marino const _Safe_local_iterator<_Iterator, _Sequence>& __rhs) 310*e4b17023SJohn Marino { 311*e4b17023SJohn Marino _GLIBCXX_DEBUG_VERIFY(! __lhs._M_singular() && ! __rhs._M_singular(), 312*e4b17023SJohn Marino _M_message(__msg_iter_compare_bad) 313*e4b17023SJohn Marino ._M_iterator(__lhs, "lhs") 314*e4b17023SJohn Marino ._M_iterator(__rhs, "rhs")); 315*e4b17023SJohn Marino _GLIBCXX_DEBUG_VERIFY(__lhs._M_can_compare(__rhs), 316*e4b17023SJohn Marino _M_message(__msg_compare_different) 317*e4b17023SJohn Marino ._M_iterator(__lhs, "lhs") 318*e4b17023SJohn Marino ._M_iterator(__rhs, "rhs")); 319*e4b17023SJohn Marino _GLIBCXX_DEBUG_VERIFY(__lhs._M_in_same_bucket(__rhs), 320*e4b17023SJohn Marino _M_message(__msg_local_iter_compare_bad) 321*e4b17023SJohn Marino ._M_iterator(__lhs, "lhs") 322*e4b17023SJohn Marino ._M_iterator(__rhs, "rhs")); 323*e4b17023SJohn Marino return __lhs.base() == __rhs.base(); 324*e4b17023SJohn Marino } 325*e4b17023SJohn Marino 326*e4b17023SJohn Marino template<typename _IteratorL, typename _IteratorR, typename _Sequence> 327*e4b17023SJohn Marino inline bool 328*e4b17023SJohn Marino operator!=(const _Safe_local_iterator<_IteratorL, _Sequence>& __lhs, 329*e4b17023SJohn Marino const _Safe_local_iterator<_IteratorR, _Sequence>& __rhs) 330*e4b17023SJohn Marino { 331*e4b17023SJohn Marino _GLIBCXX_DEBUG_VERIFY(! __lhs._M_singular() && ! __rhs._M_singular(), 332*e4b17023SJohn Marino _M_message(__msg_iter_compare_bad) 333*e4b17023SJohn Marino ._M_iterator(__lhs, "lhs") 334*e4b17023SJohn Marino ._M_iterator(__rhs, "rhs")); 335*e4b17023SJohn Marino _GLIBCXX_DEBUG_VERIFY(__lhs._M_can_compare(__rhs), 336*e4b17023SJohn Marino _M_message(__msg_compare_different) 337*e4b17023SJohn Marino ._M_iterator(__lhs, "lhs") 338*e4b17023SJohn Marino ._M_iterator(__rhs, "rhs")); 339*e4b17023SJohn Marino _GLIBCXX_DEBUG_VERIFY(__lhs._M_in_same_bucket(__rhs), 340*e4b17023SJohn Marino _M_message(__msg_local_iter_compare_bad) 341*e4b17023SJohn Marino ._M_iterator(__lhs, "lhs") 342*e4b17023SJohn Marino ._M_iterator(__rhs, "rhs")); 343*e4b17023SJohn Marino return __lhs.base() != __rhs.base(); 344*e4b17023SJohn Marino } 345*e4b17023SJohn Marino 346*e4b17023SJohn Marino template<typename _Iterator, typename _Sequence> 347*e4b17023SJohn Marino inline bool 348*e4b17023SJohn Marino operator!=(const _Safe_local_iterator<_Iterator, _Sequence>& __lhs, 349*e4b17023SJohn Marino const _Safe_local_iterator<_Iterator, _Sequence>& __rhs) 350*e4b17023SJohn Marino { 351*e4b17023SJohn Marino _GLIBCXX_DEBUG_VERIFY(! __lhs._M_singular() && ! __rhs._M_singular(), 352*e4b17023SJohn Marino _M_message(__msg_iter_compare_bad) 353*e4b17023SJohn Marino ._M_iterator(__lhs, "lhs") 354*e4b17023SJohn Marino ._M_iterator(__rhs, "rhs")); 355*e4b17023SJohn Marino _GLIBCXX_DEBUG_VERIFY(__lhs._M_can_compare(__rhs), 356*e4b17023SJohn Marino _M_message(__msg_compare_different) 357*e4b17023SJohn Marino ._M_iterator(__lhs, "lhs") 358*e4b17023SJohn Marino ._M_iterator(__rhs, "rhs")); 359*e4b17023SJohn Marino _GLIBCXX_DEBUG_VERIFY(__lhs._M_in_same_bucket(__rhs), 360*e4b17023SJohn Marino _M_message(__msg_local_iter_compare_bad) 361*e4b17023SJohn Marino ._M_iterator(__lhs, "lhs") 362*e4b17023SJohn Marino ._M_iterator(__rhs, "rhs")); 363*e4b17023SJohn Marino return __lhs.base() != __rhs.base(); 364*e4b17023SJohn Marino } 365*e4b17023SJohn Marino } // namespace __gnu_debug 366*e4b17023SJohn Marino 367*e4b17023SJohn Marino #include <debug/safe_local_iterator.tcc> 368*e4b17023SJohn Marino 369*e4b17023SJohn Marino #endif 370