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