1*e4b17023SJohn Marino // Safe iterator implementation -*- C++ -*- 2*e4b17023SJohn Marino 3*e4b17023SJohn Marino // Copyright (C) 2003, 2004, 2005, 2006, 2009, 2010, 2011, 2012 4*e4b17023SJohn Marino // Free Software Foundation, Inc. 5*e4b17023SJohn Marino // 6*e4b17023SJohn Marino // This file is part of the GNU ISO C++ Library. This library is free 7*e4b17023SJohn Marino // software; you can redistribute it and/or modify it under the 8*e4b17023SJohn Marino // terms of the GNU General Public License as published by the 9*e4b17023SJohn Marino // Free Software Foundation; either version 3, or (at your option) 10*e4b17023SJohn Marino // any later version. 11*e4b17023SJohn Marino 12*e4b17023SJohn Marino // This library is distributed in the hope that it will be useful, 13*e4b17023SJohn Marino // but WITHOUT ANY WARRANTY; without even the implied warranty of 14*e4b17023SJohn Marino // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15*e4b17023SJohn Marino // GNU General Public License for more details. 16*e4b17023SJohn Marino 17*e4b17023SJohn Marino // Under Section 7 of GPL version 3, you are granted additional 18*e4b17023SJohn Marino // permissions described in the GCC Runtime Library Exception, version 19*e4b17023SJohn Marino // 3.1, as published by the Free Software Foundation. 20*e4b17023SJohn Marino 21*e4b17023SJohn Marino // You should have received a copy of the GNU General Public License and 22*e4b17023SJohn Marino // a copy of the GCC Runtime Library Exception along with this program; 23*e4b17023SJohn Marino // see the files COPYING3 and COPYING.RUNTIME respectively. If not, see 24*e4b17023SJohn Marino // <http://www.gnu.org/licenses/>. 25*e4b17023SJohn Marino 26*e4b17023SJohn Marino /** @file debug/safe_iterator.h 27*e4b17023SJohn Marino * This file is a GNU debug extension to the Standard C++ Library. 28*e4b17023SJohn Marino */ 29*e4b17023SJohn Marino 30*e4b17023SJohn Marino #ifndef _GLIBCXX_DEBUG_SAFE_ITERATOR_H 31*e4b17023SJohn Marino #define _GLIBCXX_DEBUG_SAFE_ITERATOR_H 1 32*e4b17023SJohn Marino 33*e4b17023SJohn Marino #include <debug/debug.h> 34*e4b17023SJohn Marino #include <debug/macros.h> 35*e4b17023SJohn Marino #include <debug/functions.h> 36*e4b17023SJohn Marino #include <debug/safe_base.h> 37*e4b17023SJohn Marino #include <bits/stl_pair.h> 38*e4b17023SJohn Marino #include <bits/stl_iterator_base_types.h> // for _Iter_base 39*e4b17023SJohn Marino #include <ext/type_traits.h> 40*e4b17023SJohn Marino 41*e4b17023SJohn Marino namespace __gnu_debug 42*e4b17023SJohn Marino { 43*e4b17023SJohn Marino /** Helper struct to deal with sequence offering a before_begin 44*e4b17023SJohn Marino * iterator. 45*e4b17023SJohn Marino **/ 46*e4b17023SJohn Marino template <typename _Sequence> 47*e4b17023SJohn Marino struct _BeforeBeginHelper 48*e4b17023SJohn Marino { 49*e4b17023SJohn Marino typedef typename _Sequence::const_iterator _It; 50*e4b17023SJohn Marino typedef typename _It::iterator_type _BaseIt; 51*e4b17023SJohn Marino 52*e4b17023SJohn Marino static bool _S_Is_BeforeBeginHelper53*e4b17023SJohn Marino _S_Is(_BaseIt, const _Sequence*) 54*e4b17023SJohn Marino { return false; } 55*e4b17023SJohn Marino 56*e4b17023SJohn Marino static bool _S_Is_Beginnest_BeforeBeginHelper57*e4b17023SJohn Marino _S_Is_Beginnest(_BaseIt __it, const _Sequence* __seq) 58*e4b17023SJohn Marino { return __it == __seq->_M_base().begin(); } 59*e4b17023SJohn Marino }; 60*e4b17023SJohn Marino 61*e4b17023SJohn Marino /** Iterators that derive from _Safe_iterator_base but that aren't 62*e4b17023SJohn Marino * _Safe_iterators can be determined singular or non-singular via 63*e4b17023SJohn Marino * _Safe_iterator_base. 64*e4b17023SJohn Marino */ 65*e4b17023SJohn Marino inline bool __check_singular_aux(const _Safe_iterator_base * __x)66*e4b17023SJohn Marino __check_singular_aux(const _Safe_iterator_base* __x) 67*e4b17023SJohn Marino { return __x->_M_singular(); } 68*e4b17023SJohn Marino 69*e4b17023SJohn Marino /** The precision to which we can calculate the distance between 70*e4b17023SJohn Marino * two iterators. 71*e4b17023SJohn Marino */ 72*e4b17023SJohn Marino enum _Distance_precision 73*e4b17023SJohn Marino { 74*e4b17023SJohn Marino __dp_equality, //< Can compare iterator equality, only 75*e4b17023SJohn Marino __dp_sign, //< Can determine equality and ordering 76*e4b17023SJohn Marino __dp_exact //< Can determine distance precisely 77*e4b17023SJohn Marino }; 78*e4b17023SJohn Marino 79*e4b17023SJohn Marino /** Determine the distance between two iterators with some known 80*e4b17023SJohn Marino * precision. 81*e4b17023SJohn Marino */ 82*e4b17023SJohn Marino template<typename _Iterator1, typename _Iterator2> 83*e4b17023SJohn Marino inline std::pair<typename std::iterator_traits<_Iterator1>::difference_type, 84*e4b17023SJohn Marino _Distance_precision> __get_distance(const _Iterator1 & __lhs,const _Iterator2 & __rhs,std::random_access_iterator_tag)85*e4b17023SJohn Marino __get_distance(const _Iterator1& __lhs, const _Iterator2& __rhs, 86*e4b17023SJohn Marino std::random_access_iterator_tag) 87*e4b17023SJohn Marino { return std::make_pair(__rhs - __lhs, __dp_exact); } 88*e4b17023SJohn Marino 89*e4b17023SJohn Marino template<typename _Iterator1, typename _Iterator2> 90*e4b17023SJohn Marino inline std::pair<typename std::iterator_traits<_Iterator1>::difference_type, 91*e4b17023SJohn Marino _Distance_precision> __get_distance(const _Iterator1 & __lhs,const _Iterator2 & __rhs,std::forward_iterator_tag)92*e4b17023SJohn Marino __get_distance(const _Iterator1& __lhs, const _Iterator2& __rhs, 93*e4b17023SJohn Marino std::forward_iterator_tag) 94*e4b17023SJohn Marino { return std::make_pair(__lhs == __rhs? 0 : 1, __dp_equality); } 95*e4b17023SJohn Marino 96*e4b17023SJohn Marino template<typename _Iterator1, typename _Iterator2> 97*e4b17023SJohn Marino inline std::pair<typename std::iterator_traits<_Iterator1>::difference_type, 98*e4b17023SJohn Marino _Distance_precision> __get_distance(const _Iterator1 & __lhs,const _Iterator2 & __rhs)99*e4b17023SJohn Marino __get_distance(const _Iterator1& __lhs, const _Iterator2& __rhs) 100*e4b17023SJohn Marino { 101*e4b17023SJohn Marino typedef typename std::iterator_traits<_Iterator1>::iterator_category 102*e4b17023SJohn Marino _Category; 103*e4b17023SJohn Marino return __get_distance(__lhs, __rhs, _Category()); 104*e4b17023SJohn Marino } 105*e4b17023SJohn Marino 106*e4b17023SJohn Marino /** \brief Safe iterator wrapper. 107*e4b17023SJohn Marino * 108*e4b17023SJohn Marino * The class template %_Safe_iterator is a wrapper around an 109*e4b17023SJohn Marino * iterator that tracks the iterator's movement among sequences and 110*e4b17023SJohn Marino * checks that operations performed on the "safe" iterator are 111*e4b17023SJohn Marino * legal. In additional to the basic iterator operations (which are 112*e4b17023SJohn Marino * validated, and then passed to the underlying iterator), 113*e4b17023SJohn Marino * %_Safe_iterator has member functions for iterator invalidation, 114*e4b17023SJohn Marino * attaching/detaching the iterator from sequences, and querying 115*e4b17023SJohn Marino * the iterator's state. 116*e4b17023SJohn Marino */ 117*e4b17023SJohn Marino template<typename _Iterator, typename _Sequence> 118*e4b17023SJohn Marino class _Safe_iterator : public _Safe_iterator_base 119*e4b17023SJohn Marino { 120*e4b17023SJohn Marino typedef _Safe_iterator _Self; 121*e4b17023SJohn Marino 122*e4b17023SJohn Marino /// The underlying iterator 123*e4b17023SJohn Marino _Iterator _M_current; 124*e4b17023SJohn Marino 125*e4b17023SJohn Marino /// Determine if this is a constant iterator. 126*e4b17023SJohn Marino bool _M_constant()127*e4b17023SJohn Marino _M_constant() const 128*e4b17023SJohn Marino { 129*e4b17023SJohn Marino typedef typename _Sequence::const_iterator const_iterator; 130*e4b17023SJohn Marino return std::__are_same<const_iterator, _Safe_iterator>::__value; 131*e4b17023SJohn Marino } 132*e4b17023SJohn Marino 133*e4b17023SJohn Marino typedef std::iterator_traits<_Iterator> _Traits; 134*e4b17023SJohn Marino 135*e4b17023SJohn Marino public: 136*e4b17023SJohn Marino typedef _Iterator iterator_type; 137*e4b17023SJohn Marino typedef typename _Traits::iterator_category iterator_category; 138*e4b17023SJohn Marino typedef typename _Traits::value_type value_type; 139*e4b17023SJohn Marino typedef typename _Traits::difference_type difference_type; 140*e4b17023SJohn Marino typedef typename _Traits::reference reference; 141*e4b17023SJohn Marino typedef typename _Traits::pointer pointer; 142*e4b17023SJohn Marino 143*e4b17023SJohn Marino /// @post the iterator is singular and unattached _Safe_iterator()144*e4b17023SJohn Marino _Safe_iterator() : _M_current() { } 145*e4b17023SJohn Marino 146*e4b17023SJohn Marino /** 147*e4b17023SJohn Marino * @brief Safe iterator construction from an unsafe iterator and 148*e4b17023SJohn Marino * its sequence. 149*e4b17023SJohn Marino * 150*e4b17023SJohn Marino * @pre @p seq is not NULL 151*e4b17023SJohn Marino * @post this is not singular 152*e4b17023SJohn Marino */ _Safe_iterator(const _Iterator & __i,const _Sequence * __seq)153*e4b17023SJohn Marino _Safe_iterator(const _Iterator& __i, const _Sequence* __seq) 154*e4b17023SJohn Marino : _Safe_iterator_base(__seq, _M_constant()), _M_current(__i) 155*e4b17023SJohn Marino { 156*e4b17023SJohn Marino _GLIBCXX_DEBUG_VERIFY(! this->_M_singular(), 157*e4b17023SJohn Marino _M_message(__msg_init_singular) 158*e4b17023SJohn Marino ._M_iterator(*this, "this")); 159*e4b17023SJohn Marino } 160*e4b17023SJohn Marino 161*e4b17023SJohn Marino /** 162*e4b17023SJohn Marino * @brief Copy construction. 163*e4b17023SJohn Marino */ _Safe_iterator(const _Safe_iterator & __x)164*e4b17023SJohn Marino _Safe_iterator(const _Safe_iterator& __x) 165*e4b17023SJohn Marino : _Safe_iterator_base(__x, _M_constant()), _M_current(__x._M_current) 166*e4b17023SJohn Marino { 167*e4b17023SJohn Marino // _GLIBCXX_RESOLVE_LIB_DEFECTS 168*e4b17023SJohn Marino // DR 408. Is vector<reverse_iterator<char*> > forbidden? 169*e4b17023SJohn Marino _GLIBCXX_DEBUG_VERIFY(!__x._M_singular() 170*e4b17023SJohn Marino || __x._M_current == _Iterator(), 171*e4b17023SJohn Marino _M_message(__msg_init_copy_singular) 172*e4b17023SJohn Marino ._M_iterator(*this, "this") 173*e4b17023SJohn Marino ._M_iterator(__x, "other")); 174*e4b17023SJohn Marino } 175*e4b17023SJohn Marino 176*e4b17023SJohn Marino #ifdef __GXX_EXPERIMENTAL_CXX0X__ 177*e4b17023SJohn Marino /** 178*e4b17023SJohn Marino * @brief Move construction. 179*e4b17023SJohn Marino * @post __x is singular and unattached 180*e4b17023SJohn Marino */ _Safe_iterator(_Safe_iterator && __x)181*e4b17023SJohn Marino _Safe_iterator(_Safe_iterator&& __x) : _M_current() 182*e4b17023SJohn Marino { 183*e4b17023SJohn Marino _GLIBCXX_DEBUG_VERIFY(!__x._M_singular() 184*e4b17023SJohn Marino || __x._M_current == _Iterator(), 185*e4b17023SJohn Marino _M_message(__msg_init_copy_singular) 186*e4b17023SJohn Marino ._M_iterator(*this, "this") 187*e4b17023SJohn Marino ._M_iterator(__x, "other")); 188*e4b17023SJohn Marino std::swap(_M_current, __x._M_current); 189*e4b17023SJohn Marino this->_M_attach(__x._M_sequence); 190*e4b17023SJohn Marino __x._M_detach(); 191*e4b17023SJohn Marino } 192*e4b17023SJohn Marino #endif 193*e4b17023SJohn Marino 194*e4b17023SJohn Marino /** 195*e4b17023SJohn Marino * @brief Converting constructor from a mutable iterator to a 196*e4b17023SJohn Marino * constant iterator. 197*e4b17023SJohn Marino */ 198*e4b17023SJohn Marino template<typename _MutableIterator> _Safe_iterator(const _Safe_iterator<_MutableIterator,typename __gnu_cxx::__enable_if<(std::__are_same<_MutableIterator,typename _Sequence::iterator::iterator_type>::__value),_Sequence>::__type> & __x)199*e4b17023SJohn Marino _Safe_iterator( 200*e4b17023SJohn Marino const _Safe_iterator<_MutableIterator, 201*e4b17023SJohn Marino typename __gnu_cxx::__enable_if<(std::__are_same<_MutableIterator, 202*e4b17023SJohn Marino typename _Sequence::iterator::iterator_type>::__value), 203*e4b17023SJohn Marino _Sequence>::__type>& __x) 204*e4b17023SJohn Marino : _Safe_iterator_base(__x, _M_constant()), _M_current(__x.base()) 205*e4b17023SJohn Marino { 206*e4b17023SJohn Marino // _GLIBCXX_RESOLVE_LIB_DEFECTS 207*e4b17023SJohn Marino // DR 408. Is vector<reverse_iterator<char*> > forbidden? 208*e4b17023SJohn Marino _GLIBCXX_DEBUG_VERIFY(!__x._M_singular() 209*e4b17023SJohn Marino || __x.base() == _Iterator(), 210*e4b17023SJohn Marino _M_message(__msg_init_const_singular) 211*e4b17023SJohn Marino ._M_iterator(*this, "this") 212*e4b17023SJohn Marino ._M_iterator(__x, "other")); 213*e4b17023SJohn Marino } 214*e4b17023SJohn Marino 215*e4b17023SJohn Marino /** 216*e4b17023SJohn Marino * @brief Copy assignment. 217*e4b17023SJohn Marino */ 218*e4b17023SJohn Marino _Safe_iterator& 219*e4b17023SJohn Marino operator=(const _Safe_iterator& __x) 220*e4b17023SJohn Marino { 221*e4b17023SJohn Marino // _GLIBCXX_RESOLVE_LIB_DEFECTS 222*e4b17023SJohn Marino // DR 408. Is vector<reverse_iterator<char*> > forbidden? 223*e4b17023SJohn Marino _GLIBCXX_DEBUG_VERIFY(!__x._M_singular() 224*e4b17023SJohn Marino || __x._M_current == _Iterator(), 225*e4b17023SJohn Marino _M_message(__msg_copy_singular) 226*e4b17023SJohn Marino ._M_iterator(*this, "this") 227*e4b17023SJohn Marino ._M_iterator(__x, "other")); 228*e4b17023SJohn Marino _M_current = __x._M_current; 229*e4b17023SJohn Marino this->_M_attach(__x._M_sequence); 230*e4b17023SJohn Marino return *this; 231*e4b17023SJohn Marino } 232*e4b17023SJohn Marino 233*e4b17023SJohn Marino #ifdef __GXX_EXPERIMENTAL_CXX0X__ 234*e4b17023SJohn Marino /** 235*e4b17023SJohn Marino * @brief Move assignment. 236*e4b17023SJohn Marino * @post __x is singular and unattached 237*e4b17023SJohn Marino */ 238*e4b17023SJohn Marino _Safe_iterator& 239*e4b17023SJohn Marino operator=(_Safe_iterator&& __x) 240*e4b17023SJohn Marino { 241*e4b17023SJohn Marino _GLIBCXX_DEBUG_VERIFY(!__x._M_singular() 242*e4b17023SJohn Marino || __x._M_current == _Iterator(), 243*e4b17023SJohn Marino _M_message(__msg_copy_singular) 244*e4b17023SJohn Marino ._M_iterator(*this, "this") 245*e4b17023SJohn Marino ._M_iterator(__x, "other")); 246*e4b17023SJohn Marino _M_current = __x._M_current; 247*e4b17023SJohn Marino _M_attach(__x._M_sequence); 248*e4b17023SJohn Marino __x._M_detach(); 249*e4b17023SJohn Marino __x._M_current = _Iterator(); 250*e4b17023SJohn Marino return *this; 251*e4b17023SJohn Marino } 252*e4b17023SJohn Marino #endif 253*e4b17023SJohn Marino 254*e4b17023SJohn Marino /** 255*e4b17023SJohn Marino * @brief Iterator dereference. 256*e4b17023SJohn Marino * @pre iterator is dereferenceable 257*e4b17023SJohn Marino */ 258*e4b17023SJohn Marino reference 259*e4b17023SJohn Marino operator*() const 260*e4b17023SJohn Marino { 261*e4b17023SJohn Marino _GLIBCXX_DEBUG_VERIFY(this->_M_dereferenceable(), 262*e4b17023SJohn Marino _M_message(__msg_bad_deref) 263*e4b17023SJohn Marino ._M_iterator(*this, "this")); 264*e4b17023SJohn Marino return *_M_current; 265*e4b17023SJohn Marino } 266*e4b17023SJohn Marino 267*e4b17023SJohn Marino /** 268*e4b17023SJohn Marino * @brief Iterator dereference. 269*e4b17023SJohn Marino * @pre iterator is dereferenceable 270*e4b17023SJohn Marino * @todo Make this correct w.r.t. iterators that return proxies 271*e4b17023SJohn Marino * @todo Use addressof() instead of & operator 272*e4b17023SJohn Marino */ 273*e4b17023SJohn Marino pointer 274*e4b17023SJohn Marino operator->() const 275*e4b17023SJohn Marino { 276*e4b17023SJohn Marino _GLIBCXX_DEBUG_VERIFY(this->_M_dereferenceable(), 277*e4b17023SJohn Marino _M_message(__msg_bad_deref) 278*e4b17023SJohn Marino ._M_iterator(*this, "this")); 279*e4b17023SJohn Marino return &*_M_current; 280*e4b17023SJohn Marino } 281*e4b17023SJohn Marino 282*e4b17023SJohn Marino // ------ Input iterator requirements ------ 283*e4b17023SJohn Marino /** 284*e4b17023SJohn Marino * @brief Iterator preincrement 285*e4b17023SJohn Marino * @pre iterator is incrementable 286*e4b17023SJohn Marino */ 287*e4b17023SJohn Marino _Safe_iterator& 288*e4b17023SJohn Marino operator++() 289*e4b17023SJohn Marino { 290*e4b17023SJohn Marino _GLIBCXX_DEBUG_VERIFY(this->_M_incrementable(), 291*e4b17023SJohn Marino _M_message(__msg_bad_inc) 292*e4b17023SJohn Marino ._M_iterator(*this, "this")); 293*e4b17023SJohn Marino ++_M_current; 294*e4b17023SJohn Marino return *this; 295*e4b17023SJohn Marino } 296*e4b17023SJohn Marino 297*e4b17023SJohn Marino /** 298*e4b17023SJohn Marino * @brief Iterator postincrement 299*e4b17023SJohn Marino * @pre iterator is incrementable 300*e4b17023SJohn Marino */ 301*e4b17023SJohn Marino _Safe_iterator 302*e4b17023SJohn Marino operator++(int) 303*e4b17023SJohn Marino { 304*e4b17023SJohn Marino _GLIBCXX_DEBUG_VERIFY(this->_M_incrementable(), 305*e4b17023SJohn Marino _M_message(__msg_bad_inc) 306*e4b17023SJohn Marino ._M_iterator(*this, "this")); 307*e4b17023SJohn Marino _Safe_iterator __tmp(*this); 308*e4b17023SJohn Marino ++_M_current; 309*e4b17023SJohn Marino return __tmp; 310*e4b17023SJohn Marino } 311*e4b17023SJohn Marino 312*e4b17023SJohn Marino // ------ Bidirectional iterator requirements ------ 313*e4b17023SJohn Marino /** 314*e4b17023SJohn Marino * @brief Iterator predecrement 315*e4b17023SJohn Marino * @pre iterator is decrementable 316*e4b17023SJohn Marino */ 317*e4b17023SJohn Marino _Safe_iterator& 318*e4b17023SJohn Marino operator--() 319*e4b17023SJohn Marino { 320*e4b17023SJohn Marino _GLIBCXX_DEBUG_VERIFY(this->_M_decrementable(), 321*e4b17023SJohn Marino _M_message(__msg_bad_dec) 322*e4b17023SJohn Marino ._M_iterator(*this, "this")); 323*e4b17023SJohn Marino --_M_current; 324*e4b17023SJohn Marino return *this; 325*e4b17023SJohn Marino } 326*e4b17023SJohn Marino 327*e4b17023SJohn Marino /** 328*e4b17023SJohn Marino * @brief Iterator postdecrement 329*e4b17023SJohn Marino * @pre iterator is decrementable 330*e4b17023SJohn Marino */ 331*e4b17023SJohn Marino _Safe_iterator 332*e4b17023SJohn Marino operator--(int) 333*e4b17023SJohn Marino { 334*e4b17023SJohn Marino _GLIBCXX_DEBUG_VERIFY(this->_M_decrementable(), 335*e4b17023SJohn Marino _M_message(__msg_bad_dec) 336*e4b17023SJohn Marino ._M_iterator(*this, "this")); 337*e4b17023SJohn Marino _Safe_iterator __tmp(*this); 338*e4b17023SJohn Marino --_M_current; 339*e4b17023SJohn Marino return __tmp; 340*e4b17023SJohn Marino } 341*e4b17023SJohn Marino 342*e4b17023SJohn Marino // ------ Random access iterator requirements ------ 343*e4b17023SJohn Marino reference 344*e4b17023SJohn Marino operator[](const difference_type& __n) const 345*e4b17023SJohn Marino { 346*e4b17023SJohn Marino _GLIBCXX_DEBUG_VERIFY(this->_M_can_advance(__n) 347*e4b17023SJohn Marino && this->_M_can_advance(__n+1), 348*e4b17023SJohn Marino _M_message(__msg_iter_subscript_oob) 349*e4b17023SJohn Marino ._M_iterator(*this)._M_integer(__n)); 350*e4b17023SJohn Marino 351*e4b17023SJohn Marino return _M_current[__n]; 352*e4b17023SJohn Marino } 353*e4b17023SJohn Marino 354*e4b17023SJohn Marino _Safe_iterator& 355*e4b17023SJohn Marino operator+=(const difference_type& __n) 356*e4b17023SJohn Marino { 357*e4b17023SJohn Marino _GLIBCXX_DEBUG_VERIFY(this->_M_can_advance(__n), 358*e4b17023SJohn Marino _M_message(__msg_advance_oob) 359*e4b17023SJohn Marino ._M_iterator(*this)._M_integer(__n)); 360*e4b17023SJohn Marino _M_current += __n; 361*e4b17023SJohn Marino return *this; 362*e4b17023SJohn Marino } 363*e4b17023SJohn Marino 364*e4b17023SJohn Marino _Safe_iterator 365*e4b17023SJohn Marino operator+(const difference_type& __n) const 366*e4b17023SJohn Marino { 367*e4b17023SJohn Marino _Safe_iterator __tmp(*this); 368*e4b17023SJohn Marino __tmp += __n; 369*e4b17023SJohn Marino return __tmp; 370*e4b17023SJohn Marino } 371*e4b17023SJohn Marino 372*e4b17023SJohn Marino _Safe_iterator& 373*e4b17023SJohn Marino operator-=(const difference_type& __n) 374*e4b17023SJohn Marino { 375*e4b17023SJohn Marino _GLIBCXX_DEBUG_VERIFY(this->_M_can_advance(-__n), 376*e4b17023SJohn Marino _M_message(__msg_retreat_oob) 377*e4b17023SJohn Marino ._M_iterator(*this)._M_integer(__n)); 378*e4b17023SJohn Marino _M_current += -__n; 379*e4b17023SJohn Marino return *this; 380*e4b17023SJohn Marino } 381*e4b17023SJohn Marino 382*e4b17023SJohn Marino _Safe_iterator 383*e4b17023SJohn Marino operator-(const difference_type& __n) const 384*e4b17023SJohn Marino { 385*e4b17023SJohn Marino _Safe_iterator __tmp(*this); 386*e4b17023SJohn Marino __tmp -= __n; 387*e4b17023SJohn Marino return __tmp; 388*e4b17023SJohn Marino } 389*e4b17023SJohn Marino 390*e4b17023SJohn Marino // ------ Utilities ------ 391*e4b17023SJohn Marino /** 392*e4b17023SJohn Marino * @brief Return the underlying iterator 393*e4b17023SJohn Marino */ 394*e4b17023SJohn Marino _Iterator base()395*e4b17023SJohn Marino base() const { return _M_current; } 396*e4b17023SJohn Marino 397*e4b17023SJohn Marino /** 398*e4b17023SJohn Marino * @brief Conversion to underlying non-debug iterator to allow 399*e4b17023SJohn Marino * better interaction with non-debug containers. 400*e4b17023SJohn Marino */ _Iterator()401*e4b17023SJohn Marino operator _Iterator() const { return _M_current; } 402*e4b17023SJohn Marino 403*e4b17023SJohn Marino /** Attach iterator to the given sequence. */ 404*e4b17023SJohn Marino void _M_attach(_Safe_sequence_base * __seq)405*e4b17023SJohn Marino _M_attach(_Safe_sequence_base* __seq) 406*e4b17023SJohn Marino { 407*e4b17023SJohn Marino _Safe_iterator_base::_M_attach(__seq, _M_constant()); 408*e4b17023SJohn Marino } 409*e4b17023SJohn Marino 410*e4b17023SJohn Marino /** Likewise, but not thread-safe. */ 411*e4b17023SJohn Marino void _M_attach_single(_Safe_sequence_base * __seq)412*e4b17023SJohn Marino _M_attach_single(_Safe_sequence_base* __seq) 413*e4b17023SJohn Marino { 414*e4b17023SJohn Marino _Safe_iterator_base::_M_attach_single(__seq, _M_constant()); 415*e4b17023SJohn Marino } 416*e4b17023SJohn Marino 417*e4b17023SJohn Marino /// Is the iterator dereferenceable? 418*e4b17023SJohn Marino bool _M_dereferenceable()419*e4b17023SJohn Marino _M_dereferenceable() const 420*e4b17023SJohn Marino { return !this->_M_singular() && !_M_is_end() && !_M_is_before_begin(); } 421*e4b17023SJohn Marino 422*e4b17023SJohn Marino /// Is the iterator before a dereferenceable one? 423*e4b17023SJohn Marino bool _M_before_dereferenceable()424*e4b17023SJohn Marino _M_before_dereferenceable() const 425*e4b17023SJohn Marino { 426*e4b17023SJohn Marino if (this->_M_incrementable()) 427*e4b17023SJohn Marino { 428*e4b17023SJohn Marino _Iterator __base = base(); 429*e4b17023SJohn Marino return ++__base != _M_get_sequence()->_M_base().end(); 430*e4b17023SJohn Marino } 431*e4b17023SJohn Marino return false; 432*e4b17023SJohn Marino } 433*e4b17023SJohn Marino 434*e4b17023SJohn Marino /// Is the iterator incrementable? 435*e4b17023SJohn Marino bool _M_incrementable()436*e4b17023SJohn Marino _M_incrementable() const 437*e4b17023SJohn Marino { return !this->_M_singular() && !_M_is_end(); } 438*e4b17023SJohn Marino 439*e4b17023SJohn Marino // Is the iterator decrementable? 440*e4b17023SJohn Marino bool _M_decrementable()441*e4b17023SJohn Marino _M_decrementable() const { return !_M_singular() && !_M_is_begin(); } 442*e4b17023SJohn Marino 443*e4b17023SJohn Marino // Can we advance the iterator @p __n steps (@p __n may be negative) 444*e4b17023SJohn Marino bool 445*e4b17023SJohn Marino _M_can_advance(const difference_type& __n) const; 446*e4b17023SJohn Marino 447*e4b17023SJohn Marino // Is the iterator range [*this, __rhs) valid? 448*e4b17023SJohn Marino template<typename _Other> 449*e4b17023SJohn Marino bool 450*e4b17023SJohn Marino _M_valid_range(const _Safe_iterator<_Other, _Sequence>& __rhs) const; 451*e4b17023SJohn Marino 452*e4b17023SJohn Marino // The sequence this iterator references. 453*e4b17023SJohn Marino const _Sequence* _M_get_sequence()454*e4b17023SJohn Marino _M_get_sequence() const 455*e4b17023SJohn Marino { return static_cast<const _Sequence*>(_M_sequence); } 456*e4b17023SJohn Marino 457*e4b17023SJohn Marino /// Is this iterator equal to the sequence's begin() iterator? _M_is_begin()458*e4b17023SJohn Marino bool _M_is_begin() const 459*e4b17023SJohn Marino { return base() == _M_get_sequence()->_M_base().begin(); } 460*e4b17023SJohn Marino 461*e4b17023SJohn Marino /// Is this iterator equal to the sequence's end() iterator? _M_is_end()462*e4b17023SJohn Marino bool _M_is_end() const 463*e4b17023SJohn Marino { return base() == _M_get_sequence()->_M_base().end(); } 464*e4b17023SJohn Marino 465*e4b17023SJohn Marino /// Is this iterator equal to the sequence's before_begin() iterator if 466*e4b17023SJohn Marino /// any? _M_is_before_begin()467*e4b17023SJohn Marino bool _M_is_before_begin() const 468*e4b17023SJohn Marino { 469*e4b17023SJohn Marino return _BeforeBeginHelper<_Sequence>::_S_Is(base(), _M_get_sequence()); 470*e4b17023SJohn Marino } 471*e4b17023SJohn Marino 472*e4b17023SJohn Marino /// Is this iterator equal to the sequence's before_begin() iterator if 473*e4b17023SJohn Marino /// any or begin() otherwise? _M_is_beginnest()474*e4b17023SJohn Marino bool _M_is_beginnest() const 475*e4b17023SJohn Marino { 476*e4b17023SJohn Marino return _BeforeBeginHelper<_Sequence>::_S_Is_Beginnest(base(), 477*e4b17023SJohn Marino _M_get_sequence()); 478*e4b17023SJohn Marino } 479*e4b17023SJohn Marino }; 480*e4b17023SJohn Marino 481*e4b17023SJohn Marino template<typename _IteratorL, typename _IteratorR, typename _Sequence> 482*e4b17023SJohn Marino inline bool 483*e4b17023SJohn Marino operator==(const _Safe_iterator<_IteratorL, _Sequence>& __lhs, 484*e4b17023SJohn Marino const _Safe_iterator<_IteratorR, _Sequence>& __rhs) 485*e4b17023SJohn Marino { 486*e4b17023SJohn Marino _GLIBCXX_DEBUG_VERIFY(! __lhs._M_singular() && ! __rhs._M_singular(), 487*e4b17023SJohn Marino _M_message(__msg_iter_compare_bad) 488*e4b17023SJohn Marino ._M_iterator(__lhs, "lhs") 489*e4b17023SJohn Marino ._M_iterator(__rhs, "rhs")); 490*e4b17023SJohn Marino _GLIBCXX_DEBUG_VERIFY(__lhs._M_can_compare(__rhs), 491*e4b17023SJohn Marino _M_message(__msg_compare_different) 492*e4b17023SJohn Marino ._M_iterator(__lhs, "lhs") 493*e4b17023SJohn Marino ._M_iterator(__rhs, "rhs")); 494*e4b17023SJohn Marino return __lhs.base() == __rhs.base(); 495*e4b17023SJohn Marino } 496*e4b17023SJohn Marino 497*e4b17023SJohn Marino template<typename _Iterator, typename _Sequence> 498*e4b17023SJohn Marino inline bool 499*e4b17023SJohn Marino operator==(const _Safe_iterator<_Iterator, _Sequence>& __lhs, 500*e4b17023SJohn Marino const _Safe_iterator<_Iterator, _Sequence>& __rhs) 501*e4b17023SJohn Marino { 502*e4b17023SJohn Marino _GLIBCXX_DEBUG_VERIFY(! __lhs._M_singular() && ! __rhs._M_singular(), 503*e4b17023SJohn Marino _M_message(__msg_iter_compare_bad) 504*e4b17023SJohn Marino ._M_iterator(__lhs, "lhs") 505*e4b17023SJohn Marino ._M_iterator(__rhs, "rhs")); 506*e4b17023SJohn Marino _GLIBCXX_DEBUG_VERIFY(__lhs._M_can_compare(__rhs), 507*e4b17023SJohn Marino _M_message(__msg_compare_different) 508*e4b17023SJohn Marino ._M_iterator(__lhs, "lhs") 509*e4b17023SJohn Marino ._M_iterator(__rhs, "rhs")); 510*e4b17023SJohn Marino return __lhs.base() == __rhs.base(); 511*e4b17023SJohn Marino } 512*e4b17023SJohn Marino 513*e4b17023SJohn Marino template<typename _IteratorL, typename _IteratorR, typename _Sequence> 514*e4b17023SJohn Marino inline bool 515*e4b17023SJohn Marino operator!=(const _Safe_iterator<_IteratorL, _Sequence>& __lhs, 516*e4b17023SJohn Marino const _Safe_iterator<_IteratorR, _Sequence>& __rhs) 517*e4b17023SJohn Marino { 518*e4b17023SJohn Marino _GLIBCXX_DEBUG_VERIFY(! __lhs._M_singular() && ! __rhs._M_singular(), 519*e4b17023SJohn Marino _M_message(__msg_iter_compare_bad) 520*e4b17023SJohn Marino ._M_iterator(__lhs, "lhs") 521*e4b17023SJohn Marino ._M_iterator(__rhs, "rhs")); 522*e4b17023SJohn Marino _GLIBCXX_DEBUG_VERIFY(__lhs._M_can_compare(__rhs), 523*e4b17023SJohn Marino _M_message(__msg_compare_different) 524*e4b17023SJohn Marino ._M_iterator(__lhs, "lhs") 525*e4b17023SJohn Marino ._M_iterator(__rhs, "rhs")); 526*e4b17023SJohn Marino return __lhs.base() != __rhs.base(); 527*e4b17023SJohn Marino } 528*e4b17023SJohn Marino 529*e4b17023SJohn Marino template<typename _Iterator, typename _Sequence> 530*e4b17023SJohn Marino inline bool 531*e4b17023SJohn Marino operator!=(const _Safe_iterator<_Iterator, _Sequence>& __lhs, 532*e4b17023SJohn Marino const _Safe_iterator<_Iterator, _Sequence>& __rhs) 533*e4b17023SJohn Marino { 534*e4b17023SJohn Marino _GLIBCXX_DEBUG_VERIFY(! __lhs._M_singular() && ! __rhs._M_singular(), 535*e4b17023SJohn Marino _M_message(__msg_iter_compare_bad) 536*e4b17023SJohn Marino ._M_iterator(__lhs, "lhs") 537*e4b17023SJohn Marino ._M_iterator(__rhs, "rhs")); 538*e4b17023SJohn Marino _GLIBCXX_DEBUG_VERIFY(__lhs._M_can_compare(__rhs), 539*e4b17023SJohn Marino _M_message(__msg_compare_different) 540*e4b17023SJohn Marino ._M_iterator(__lhs, "lhs") 541*e4b17023SJohn Marino ._M_iterator(__rhs, "rhs")); 542*e4b17023SJohn Marino return __lhs.base() != __rhs.base(); 543*e4b17023SJohn Marino } 544*e4b17023SJohn Marino 545*e4b17023SJohn Marino template<typename _IteratorL, typename _IteratorR, typename _Sequence> 546*e4b17023SJohn Marino inline bool 547*e4b17023SJohn Marino operator<(const _Safe_iterator<_IteratorL, _Sequence>& __lhs, 548*e4b17023SJohn Marino const _Safe_iterator<_IteratorR, _Sequence>& __rhs) 549*e4b17023SJohn Marino { 550*e4b17023SJohn Marino _GLIBCXX_DEBUG_VERIFY(! __lhs._M_singular() && ! __rhs._M_singular(), 551*e4b17023SJohn Marino _M_message(__msg_iter_order_bad) 552*e4b17023SJohn Marino ._M_iterator(__lhs, "lhs") 553*e4b17023SJohn Marino ._M_iterator(__rhs, "rhs")); 554*e4b17023SJohn Marino _GLIBCXX_DEBUG_VERIFY(__lhs._M_can_compare(__rhs), 555*e4b17023SJohn Marino _M_message(__msg_order_different) 556*e4b17023SJohn Marino ._M_iterator(__lhs, "lhs") 557*e4b17023SJohn Marino ._M_iterator(__rhs, "rhs")); 558*e4b17023SJohn Marino return __lhs.base() < __rhs.base(); 559*e4b17023SJohn Marino } 560*e4b17023SJohn Marino 561*e4b17023SJohn Marino template<typename _Iterator, typename _Sequence> 562*e4b17023SJohn Marino inline bool 563*e4b17023SJohn Marino operator<(const _Safe_iterator<_Iterator, _Sequence>& __lhs, 564*e4b17023SJohn Marino const _Safe_iterator<_Iterator, _Sequence>& __rhs) 565*e4b17023SJohn Marino { 566*e4b17023SJohn Marino _GLIBCXX_DEBUG_VERIFY(! __lhs._M_singular() && ! __rhs._M_singular(), 567*e4b17023SJohn Marino _M_message(__msg_iter_order_bad) 568*e4b17023SJohn Marino ._M_iterator(__lhs, "lhs") 569*e4b17023SJohn Marino ._M_iterator(__rhs, "rhs")); 570*e4b17023SJohn Marino _GLIBCXX_DEBUG_VERIFY(__lhs._M_can_compare(__rhs), 571*e4b17023SJohn Marino _M_message(__msg_order_different) 572*e4b17023SJohn Marino ._M_iterator(__lhs, "lhs") 573*e4b17023SJohn Marino ._M_iterator(__rhs, "rhs")); 574*e4b17023SJohn Marino return __lhs.base() < __rhs.base(); 575*e4b17023SJohn Marino } 576*e4b17023SJohn Marino 577*e4b17023SJohn Marino template<typename _IteratorL, typename _IteratorR, typename _Sequence> 578*e4b17023SJohn Marino inline bool 579*e4b17023SJohn Marino operator<=(const _Safe_iterator<_IteratorL, _Sequence>& __lhs, 580*e4b17023SJohn Marino const _Safe_iterator<_IteratorR, _Sequence>& __rhs) 581*e4b17023SJohn Marino { 582*e4b17023SJohn Marino _GLIBCXX_DEBUG_VERIFY(! __lhs._M_singular() && ! __rhs._M_singular(), 583*e4b17023SJohn Marino _M_message(__msg_iter_order_bad) 584*e4b17023SJohn Marino ._M_iterator(__lhs, "lhs") 585*e4b17023SJohn Marino ._M_iterator(__rhs, "rhs")); 586*e4b17023SJohn Marino _GLIBCXX_DEBUG_VERIFY(__lhs._M_can_compare(__rhs), 587*e4b17023SJohn Marino _M_message(__msg_order_different) 588*e4b17023SJohn Marino ._M_iterator(__lhs, "lhs") 589*e4b17023SJohn Marino ._M_iterator(__rhs, "rhs")); 590*e4b17023SJohn Marino return __lhs.base() <= __rhs.base(); 591*e4b17023SJohn Marino } 592*e4b17023SJohn Marino 593*e4b17023SJohn Marino template<typename _Iterator, typename _Sequence> 594*e4b17023SJohn Marino inline bool 595*e4b17023SJohn Marino operator<=(const _Safe_iterator<_Iterator, _Sequence>& __lhs, 596*e4b17023SJohn Marino const _Safe_iterator<_Iterator, _Sequence>& __rhs) 597*e4b17023SJohn Marino { 598*e4b17023SJohn Marino _GLIBCXX_DEBUG_VERIFY(! __lhs._M_singular() && ! __rhs._M_singular(), 599*e4b17023SJohn Marino _M_message(__msg_iter_order_bad) 600*e4b17023SJohn Marino ._M_iterator(__lhs, "lhs") 601*e4b17023SJohn Marino ._M_iterator(__rhs, "rhs")); 602*e4b17023SJohn Marino _GLIBCXX_DEBUG_VERIFY(__lhs._M_can_compare(__rhs), 603*e4b17023SJohn Marino _M_message(__msg_order_different) 604*e4b17023SJohn Marino ._M_iterator(__lhs, "lhs") 605*e4b17023SJohn Marino ._M_iterator(__rhs, "rhs")); 606*e4b17023SJohn Marino return __lhs.base() <= __rhs.base(); 607*e4b17023SJohn Marino } 608*e4b17023SJohn Marino 609*e4b17023SJohn Marino template<typename _IteratorL, typename _IteratorR, typename _Sequence> 610*e4b17023SJohn Marino inline bool 611*e4b17023SJohn Marino operator>(const _Safe_iterator<_IteratorL, _Sequence>& __lhs, 612*e4b17023SJohn Marino const _Safe_iterator<_IteratorR, _Sequence>& __rhs) 613*e4b17023SJohn Marino { 614*e4b17023SJohn Marino _GLIBCXX_DEBUG_VERIFY(! __lhs._M_singular() && ! __rhs._M_singular(), 615*e4b17023SJohn Marino _M_message(__msg_iter_order_bad) 616*e4b17023SJohn Marino ._M_iterator(__lhs, "lhs") 617*e4b17023SJohn Marino ._M_iterator(__rhs, "rhs")); 618*e4b17023SJohn Marino _GLIBCXX_DEBUG_VERIFY(__lhs._M_can_compare(__rhs), 619*e4b17023SJohn Marino _M_message(__msg_order_different) 620*e4b17023SJohn Marino ._M_iterator(__lhs, "lhs") 621*e4b17023SJohn Marino ._M_iterator(__rhs, "rhs")); 622*e4b17023SJohn Marino return __lhs.base() > __rhs.base(); 623*e4b17023SJohn Marino } 624*e4b17023SJohn Marino 625*e4b17023SJohn Marino template<typename _Iterator, typename _Sequence> 626*e4b17023SJohn Marino inline bool 627*e4b17023SJohn Marino operator>(const _Safe_iterator<_Iterator, _Sequence>& __lhs, 628*e4b17023SJohn Marino const _Safe_iterator<_Iterator, _Sequence>& __rhs) 629*e4b17023SJohn Marino { 630*e4b17023SJohn Marino _GLIBCXX_DEBUG_VERIFY(! __lhs._M_singular() && ! __rhs._M_singular(), 631*e4b17023SJohn Marino _M_message(__msg_iter_order_bad) 632*e4b17023SJohn Marino ._M_iterator(__lhs, "lhs") 633*e4b17023SJohn Marino ._M_iterator(__rhs, "rhs")); 634*e4b17023SJohn Marino _GLIBCXX_DEBUG_VERIFY(__lhs._M_can_compare(__rhs), 635*e4b17023SJohn Marino _M_message(__msg_order_different) 636*e4b17023SJohn Marino ._M_iterator(__lhs, "lhs") 637*e4b17023SJohn Marino ._M_iterator(__rhs, "rhs")); 638*e4b17023SJohn Marino return __lhs.base() > __rhs.base(); 639*e4b17023SJohn Marino } 640*e4b17023SJohn Marino 641*e4b17023SJohn Marino template<typename _IteratorL, typename _IteratorR, typename _Sequence> 642*e4b17023SJohn Marino inline bool 643*e4b17023SJohn Marino operator>=(const _Safe_iterator<_IteratorL, _Sequence>& __lhs, 644*e4b17023SJohn Marino const _Safe_iterator<_IteratorR, _Sequence>& __rhs) 645*e4b17023SJohn Marino { 646*e4b17023SJohn Marino _GLIBCXX_DEBUG_VERIFY(! __lhs._M_singular() && ! __rhs._M_singular(), 647*e4b17023SJohn Marino _M_message(__msg_iter_order_bad) 648*e4b17023SJohn Marino ._M_iterator(__lhs, "lhs") 649*e4b17023SJohn Marino ._M_iterator(__rhs, "rhs")); 650*e4b17023SJohn Marino _GLIBCXX_DEBUG_VERIFY(__lhs._M_can_compare(__rhs), 651*e4b17023SJohn Marino _M_message(__msg_order_different) 652*e4b17023SJohn Marino ._M_iterator(__lhs, "lhs") 653*e4b17023SJohn Marino ._M_iterator(__rhs, "rhs")); 654*e4b17023SJohn Marino return __lhs.base() >= __rhs.base(); 655*e4b17023SJohn Marino } 656*e4b17023SJohn Marino 657*e4b17023SJohn Marino template<typename _Iterator, typename _Sequence> 658*e4b17023SJohn Marino inline bool 659*e4b17023SJohn Marino operator>=(const _Safe_iterator<_Iterator, _Sequence>& __lhs, 660*e4b17023SJohn Marino const _Safe_iterator<_Iterator, _Sequence>& __rhs) 661*e4b17023SJohn Marino { 662*e4b17023SJohn Marino _GLIBCXX_DEBUG_VERIFY(! __lhs._M_singular() && ! __rhs._M_singular(), 663*e4b17023SJohn Marino _M_message(__msg_iter_order_bad) 664*e4b17023SJohn Marino ._M_iterator(__lhs, "lhs") 665*e4b17023SJohn Marino ._M_iterator(__rhs, "rhs")); 666*e4b17023SJohn Marino _GLIBCXX_DEBUG_VERIFY(__lhs._M_can_compare(__rhs), 667*e4b17023SJohn Marino _M_message(__msg_order_different) 668*e4b17023SJohn Marino ._M_iterator(__lhs, "lhs") 669*e4b17023SJohn Marino ._M_iterator(__rhs, "rhs")); 670*e4b17023SJohn Marino return __lhs.base() >= __rhs.base(); 671*e4b17023SJohn Marino } 672*e4b17023SJohn Marino 673*e4b17023SJohn Marino // _GLIBCXX_RESOLVE_LIB_DEFECTS 674*e4b17023SJohn Marino // According to the resolution of DR179 not only the various comparison 675*e4b17023SJohn Marino // operators but also operator- must accept mixed iterator/const_iterator 676*e4b17023SJohn Marino // parameters. 677*e4b17023SJohn Marino template<typename _IteratorL, typename _IteratorR, typename _Sequence> 678*e4b17023SJohn Marino inline typename _Safe_iterator<_IteratorL, _Sequence>::difference_type 679*e4b17023SJohn Marino operator-(const _Safe_iterator<_IteratorL, _Sequence>& __lhs, 680*e4b17023SJohn Marino const _Safe_iterator<_IteratorR, _Sequence>& __rhs) 681*e4b17023SJohn Marino { 682*e4b17023SJohn Marino _GLIBCXX_DEBUG_VERIFY(! __lhs._M_singular() && ! __rhs._M_singular(), 683*e4b17023SJohn Marino _M_message(__msg_distance_bad) 684*e4b17023SJohn Marino ._M_iterator(__lhs, "lhs") 685*e4b17023SJohn Marino ._M_iterator(__rhs, "rhs")); 686*e4b17023SJohn Marino _GLIBCXX_DEBUG_VERIFY(__lhs._M_can_compare(__rhs), 687*e4b17023SJohn Marino _M_message(__msg_distance_different) 688*e4b17023SJohn Marino ._M_iterator(__lhs, "lhs") 689*e4b17023SJohn Marino ._M_iterator(__rhs, "rhs")); 690*e4b17023SJohn Marino return __lhs.base() - __rhs.base(); 691*e4b17023SJohn Marino } 692*e4b17023SJohn Marino 693*e4b17023SJohn Marino template<typename _Iterator, typename _Sequence> 694*e4b17023SJohn Marino inline typename _Safe_iterator<_Iterator, _Sequence>::difference_type 695*e4b17023SJohn Marino operator-(const _Safe_iterator<_Iterator, _Sequence>& __lhs, 696*e4b17023SJohn Marino const _Safe_iterator<_Iterator, _Sequence>& __rhs) 697*e4b17023SJohn Marino { 698*e4b17023SJohn Marino _GLIBCXX_DEBUG_VERIFY(! __lhs._M_singular() && ! __rhs._M_singular(), 699*e4b17023SJohn Marino _M_message(__msg_distance_bad) 700*e4b17023SJohn Marino ._M_iterator(__lhs, "lhs") 701*e4b17023SJohn Marino ._M_iterator(__rhs, "rhs")); 702*e4b17023SJohn Marino _GLIBCXX_DEBUG_VERIFY(__lhs._M_can_compare(__rhs), 703*e4b17023SJohn Marino _M_message(__msg_distance_different) 704*e4b17023SJohn Marino ._M_iterator(__lhs, "lhs") 705*e4b17023SJohn Marino ._M_iterator(__rhs, "rhs")); 706*e4b17023SJohn Marino return __lhs.base() - __rhs.base(); 707*e4b17023SJohn Marino } 708*e4b17023SJohn Marino 709*e4b17023SJohn Marino template<typename _Iterator, typename _Sequence> 710*e4b17023SJohn Marino inline _Safe_iterator<_Iterator, _Sequence> 711*e4b17023SJohn Marino operator+(typename _Safe_iterator<_Iterator,_Sequence>::difference_type __n, 712*e4b17023SJohn Marino const _Safe_iterator<_Iterator, _Sequence>& __i) 713*e4b17023SJohn Marino { return __i + __n; } 714*e4b17023SJohn Marino 715*e4b17023SJohn Marino // Helper struct to detect random access safe iterators. 716*e4b17023SJohn Marino template<typename _Iterator> 717*e4b17023SJohn Marino struct __is_safe_random_iterator 718*e4b17023SJohn Marino { 719*e4b17023SJohn Marino enum { __value = 0 }; 720*e4b17023SJohn Marino typedef std::__false_type __type; 721*e4b17023SJohn Marino }; 722*e4b17023SJohn Marino 723*e4b17023SJohn Marino template<typename _Iterator, typename _Sequence> 724*e4b17023SJohn Marino struct __is_safe_random_iterator<_Safe_iterator<_Iterator, _Sequence> > 725*e4b17023SJohn Marino : std::__are_same<std::random_access_iterator_tag, 726*e4b17023SJohn Marino typename std::iterator_traits<_Iterator>:: 727*e4b17023SJohn Marino iterator_category> 728*e4b17023SJohn Marino { }; 729*e4b17023SJohn Marino 730*e4b17023SJohn Marino template<typename _Iterator> 731*e4b17023SJohn Marino struct _Siter_base 732*e4b17023SJohn Marino : std::_Iter_base<_Iterator, __is_safe_random_iterator<_Iterator>::__value> 733*e4b17023SJohn Marino { }; 734*e4b17023SJohn Marino 735*e4b17023SJohn Marino /** Helper function to extract base iterator of random access safe iterator 736*e4b17023SJohn Marino in order to reduce performance impact of debug mode. Limited to random 737*e4b17023SJohn Marino access iterator because it is the only category for which it is possible 738*e4b17023SJohn Marino to check for correct iterators order in the __valid_range function 739*e4b17023SJohn Marino thanks to the < operator. 740*e4b17023SJohn Marino */ 741*e4b17023SJohn Marino template<typename _Iterator> 742*e4b17023SJohn Marino inline typename _Siter_base<_Iterator>::iterator_type 743*e4b17023SJohn Marino __base(_Iterator __it) 744*e4b17023SJohn Marino { return _Siter_base<_Iterator>::_S_base(__it); } 745*e4b17023SJohn Marino } // namespace __gnu_debug 746*e4b17023SJohn Marino 747*e4b17023SJohn Marino #include <debug/safe_iterator.tcc> 748*e4b17023SJohn Marino 749*e4b17023SJohn Marino #endif 750