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