safe_iterator.h

00001 // Safe iterator implementation -*- C++ -*- 00002 00003 // Copyright (C) 2003, 2004 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 2, 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 // You should have received a copy of the GNU General Public License along 00018 // with this library; see the file COPYING. If not, write to the Free 00019 // Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, 00020 // USA. 00021 00022 // As a special exception, you may use this file as part of a free software 00023 // library without restriction. Specifically, if other files instantiate 00024 // templates or use macros or inline functions from this file, or you compile 00025 // this file and link it with other files to produce an executable, this 00026 // file does not by itself cause the resulting executable to be covered by 00027 // the GNU General Public License. This exception does not however 00028 // invalidate any other reasons why the executable file might be covered by 00029 // the GNU General Public License. 00030 00031 #ifndef _GLIBCXX_DEBUG_SAFE_ITERATOR_H 00032 #define _GLIBCXX_DEBUG_SAFE_ITERATOR_H 1 00033 00034 #include <bits/stl_pair.h> 00035 #include <debug/debug.h> 00036 #include <debug/formatter.h> 00037 #include <debug/safe_base.h> 00038 #include <bits/cpp_type_traits.h> 00039 00040 namespace __gnu_debug 00041 { 00042 using std::iterator_traits; 00043 using std::pair; 00044 00045 /** Iterators that derive from _Safe_iterator_base but that aren't 00046 * _Safe_iterators can be determined singular or non-singular via 00047 * _Safe_iterator_base. 00048 */ 00049 inline bool __check_singular_aux(const _Safe_iterator_base* __x) 00050 { return __x->_M_singular(); } 00051 00052 /** \brief Safe iterator wrapper. 00053 * 00054 * The class template %_Safe_iterator is a wrapper around an 00055 * iterator that tracks the iterator's movement among sequences and 00056 * checks that operations performed on the "safe" iterator are 00057 * legal. In additional to the basic iterator operations (which are 00058 * validated, and then passed to the underlying iterator), 00059 * %_Safe_iterator has member functions for iterator invalidation, 00060 * attaching/detaching the iterator from sequences, and querying 00061 * the iterator's state. 00062 */ 00063 template<typename _Iterator, typename _Sequence> 00064 class _Safe_iterator : public _Safe_iterator_base 00065 { 00066 typedef _Safe_iterator _Self; 00067 00068 /** The precision to which we can calculate the distance between 00069 * two iterators. 00070 */ 00071 enum _Distance_precision 00072 { 00073 __dp_equality, //< Can compare iterator equality, only 00074 __dp_sign, //< Can determine equality and ordering 00075 __dp_exact //< Can determine distance precisely 00076 }; 00077 00078 /// The underlying iterator 00079 _Iterator _M_current; 00080 00081 /// Determine if this is a constant iterator. 00082 bool 00083 _M_constant() const 00084 { 00085 typedef typename _Sequence::const_iterator const_iterator; 00086 return __is_same<const_iterator, _Safe_iterator>::value; 00087 } 00088 00089 typedef iterator_traits<_Iterator> _Traits; 00090 00091 public: 00092 typedef _Iterator _Base_iterator; 00093 typedef typename _Traits::iterator_category iterator_category; 00094 typedef typename _Traits::value_type value_type; 00095 typedef typename _Traits::difference_type difference_type; 00096 typedef typename _Traits::reference reference; 00097 typedef typename _Traits::pointer pointer; 00098 00099 /// @post the iterator is singular and unattached 00100 _Safe_iterator() : _M_current() { } 00101 00102 /** 00103 * @brief Safe iterator construction from an unsafe iterator and 00104 * its sequence. 00105 * 00106 * @pre @p seq is not NULL 00107 * @post this is not singular 00108 */ 00109 _Safe_iterator(const _Iterator& __i, const _Sequence* __seq) 00110 : _Safe_iterator_base(__seq, _M_constant()), _M_current(__i) 00111 { 00112 _GLIBCXX_DEBUG_VERIFY(! this->_M_singular(), 00113 _M_message(__msg_init_singular) 00114 ._M_iterator(*this, "this")); 00115 } 00116 00117 /** 00118 * @brief Copy construction. 00119 * @pre @p x is not singular 00120 */ 00121 _Safe_iterator(const _Safe_iterator& __x) 00122 : _Safe_iterator_base(__x, _M_constant()), _M_current(__x._M_current) 00123 { 00124 _GLIBCXX_DEBUG_VERIFY(!__x._M_singular(), 00125 _M_message(__msg_init_copy_singular) 00126 ._M_iterator(*this, "this") 00127 ._M_iterator(__x, "other")); 00128 } 00129 00130 /** 00131 * @brief Converting constructor from a mutable iterator to a 00132 * constant iterator. 00133 * 00134 * @pre @p x is not singular 00135 */ 00136 template<typename _MutableIterator> 00137 _Safe_iterator( 00138 const _Safe_iterator<_MutableIterator, 00139 typename std::__enable_if< 00140 _Sequence, 00141 (std::__are_same<_MutableIterator, 00142 typename _Sequence::iterator::_Base_iterator>::_M_type) 00143 >::_M_type>& __x) 00144 : _Safe_iterator_base(__x, _M_constant()), _M_current(__x.base()) 00145 { 00146 _GLIBCXX_DEBUG_VERIFY(!__x._M_singular(), 00147 _M_message(__msg_init_const_singular) 00148 ._M_iterator(*this, "this") 00149 ._M_iterator(__x, "other")); 00150 } 00151 00152 /** 00153 * @brief Copy assignment. 00154 * @pre @p x is not singular 00155 */ 00156 _Safe_iterator& 00157 operator=(const _Safe_iterator& __x) 00158 { 00159 _GLIBCXX_DEBUG_VERIFY(!__x._M_singular(), 00160 _M_message(__msg_copy_singular) 00161 ._M_iterator(*this, "this") 00162 ._M_iterator(__x, "other")); 00163 _M_current = __x._M_current; 00164 this->_M_attach(static_cast<_Sequence*>(__x._M_sequence)); 00165 return *this; 00166 } 00167 00168 /** 00169 * @brief Iterator dereference. 00170 * @pre iterator is dereferenceable 00171 */ 00172 reference 00173 operator*() const 00174 { 00175 00176 _GLIBCXX_DEBUG_VERIFY(this->_M_dereferenceable(), 00177 _M_message(__msg_bad_deref) 00178 ._M_iterator(*this, "this")); 00179 return *_M_current; 00180 } 00181 00182 /** 00183 * @brief Iterator dereference. 00184 * @pre iterator is dereferenceable 00185 * @todo Make this correct w.r.t. iterators that return proxies 00186 * @todo Use addressof() instead of & operator 00187 */ 00188 pointer 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 // ------ Input iterator requirements ------ 00198 /** 00199 * @brief Iterator preincrement 00200 * @pre iterator is incrementable 00201 */ 00202 _Safe_iterator& 00203 operator++() 00204 { 00205 _GLIBCXX_DEBUG_VERIFY(this->_M_incrementable(), 00206 _M_message(__msg_bad_inc) 00207 ._M_iterator(*this, "this")); 00208 ++_M_current; 00209 return *this; 00210 } 00211 00212 /** 00213 * @brief Iterator postincrement 00214 * @pre iterator is incrementable 00215 */ 00216 _Safe_iterator 00217 operator++(int) 00218 { 00219 _GLIBCXX_DEBUG_VERIFY(this->_M_incrementable(), 00220 _M_message(__msg_bad_inc) 00221 ._M_iterator(*this, "this")); 00222 _Safe_iterator __tmp(*this); 00223 ++_M_current; 00224 return __tmp; 00225 } 00226 00227 // ------ Bidirectional iterator requirements ------ 00228 /** 00229 * @brief Iterator predecrement 00230 * @pre iterator is decrementable 00231 */ 00232 _Safe_iterator& 00233 operator--() 00234 { 00235 _GLIBCXX_DEBUG_VERIFY(this->_M_decrementable(), 00236 _M_message(__msg_bad_dec) 00237 ._M_iterator(*this, "this")); 00238 --_M_current; 00239 return *this; 00240 } 00241 00242 /** 00243 * @brief Iterator postdecrement 00244 * @pre iterator is decrementable 00245 */ 00246 _Safe_iterator 00247 operator--(int) 00248 { 00249 _GLIBCXX_DEBUG_VERIFY(this->_M_decrementable(), 00250 _M_message(__msg_bad_dec) 00251 ._M_iterator(*this, "this")); 00252 _Safe_iterator __tmp(*this); 00253 --_M_current; 00254 return __tmp; 00255 } 00256 00257 // ------ Random access iterator requirements ------ 00258 reference 00259 operator[](const difference_type& __n) const 00260 { 00261 _GLIBCXX_DEBUG_VERIFY(this->_M_can_advance(__n) 00262 && this->_M_can_advance(__n+1), 00263 _M_message(__msg_iter_subscript_oob) 00264 ._M_iterator(*this)._M_integer(__n)); 00265 00266 return _M_current[__n]; 00267 } 00268 00269 _Safe_iterator& 00270 operator+=(const difference_type& __n) 00271 { 00272 _GLIBCXX_DEBUG_VERIFY(this->_M_can_advance(__n), 00273 _M_message(__msg_advance_oob) 00274 ._M_iterator(*this)._M_integer(__n)); 00275 _M_current += __n; 00276 return *this; 00277 } 00278 00279 _Safe_iterator 00280 operator+(const difference_type& __n) const 00281 { 00282 _Safe_iterator __tmp(*this); 00283 __tmp += __n; 00284 return __tmp; 00285 } 00286 00287 _Safe_iterator& 00288 operator-=(const difference_type& __n) 00289 { 00290 _GLIBCXX_DEBUG_VERIFY(this->_M_can_advance(-__n), 00291 _M_message(__msg_retreat_oob) 00292 ._M_iterator(*this)._M_integer(__n)); 00293 _M_current += -__n; 00294 return *this; 00295 } 00296 00297 _Safe_iterator 00298 operator-(const difference_type& __n) const 00299 { 00300 _Safe_iterator __tmp(*this); 00301 __tmp -= __n; 00302 return __tmp; 00303 } 00304 00305 // ------ Utilities ------ 00306 /** 00307 * @brief Return the underlying iterator 00308 */ 00309 _Iterator 00310 base() const { return _M_current; } 00311 00312 /** 00313 * @brief Conversion to underlying non-debug iterator to allow 00314 * better interaction with non-debug containers. 00315 */ 00316 operator _Iterator() const { return _M_current; } 00317 00318 /** Attach iterator to the given sequence. */ 00319 void 00320 _M_attach(const _Sequence* __seq) 00321 { 00322 _Safe_iterator_base::_M_attach(const_cast<_Sequence*>(__seq), 00323 _M_constant()); 00324 } 00325 00326 /** Invalidate the iterator, making it singular. */ 00327 void 00328 _M_invalidate(); 00329 00330 /// Is the iterator dereferenceable? 00331 bool 00332 _M_dereferenceable() const 00333 { return !this->_M_singular() && !_M_is_end(); } 00334 00335 /// Is the iterator incrementable? 00336 bool 00337 _M_incrementable() const { return this->_M_dereferenceable(); } 00338 00339 // Is the iterator decrementable? 00340 bool 00341 _M_decrementable() const { return !_M_singular() && !_M_is_begin(); } 00342 00343 // Can we advance the iterator @p __n steps (@p __n may be negative) 00344 bool 00345 _M_can_advance(const difference_type& __n) const; 00346 00347 // Is the iterator range [*this, __rhs) valid? 00348 template<typename _Other> 00349 bool 00350 _M_valid_range(const _Safe_iterator<_Other, _Sequence>& __rhs) const; 00351 00352 // The sequence this iterator references. 00353 const _Sequence* 00354 _M_get_sequence() const 00355 { return static_cast<const _Sequence*>(_M_sequence); } 00356 00357 /** Determine the distance between two iterators with some known 00358 * precision. 00359 */ 00360 template<typename _Iterator1, typename _Iterator2> 00361 static pair<difference_type, _Distance_precision> 00362 _M_get_distance(const _Iterator1& __lhs, const _Iterator2& __rhs) 00363 { 00364 typedef typename iterator_traits<_Iterator1>::iterator_category 00365 _Category; 00366 return _M_get_distance(__lhs, __rhs, _Category()); 00367 } 00368 00369 template<typename _Iterator1, typename _Iterator2> 00370 static pair<difference_type, _Distance_precision> 00371 _M_get_distance(const _Iterator1& __lhs, const _Iterator2& __rhs, 00372 std::random_access_iterator_tag) 00373 { 00374 return std::make_pair(__rhs.base() - __lhs.base(), __dp_exact); 00375 } 00376 00377 template<typename _Iterator1, typename _Iterator2> 00378 static pair<difference_type, _Distance_precision> 00379 _M_get_distance(const _Iterator1& __lhs, const _Iterator2& __rhs, 00380 std::forward_iterator_tag) 00381 { 00382 return std::make_pair(__lhs.base() == __rhs.base()? 0 : 1, 00383 __dp_equality); 00384 } 00385 00386 /// Is this iterator equal to the sequence's begin() iterator? 00387 bool _M_is_begin() const 00388 { return *this == static_cast<const _Sequence*>(_M_sequence)->begin(); } 00389 00390 /// Is this iterator equal to the sequence's end() iterator? 00391 bool _M_is_end() const 00392 { return *this == static_cast<const _Sequence*>(_M_sequence)->end(); } 00393 }; 00394 00395 template<typename _IteratorL, typename _IteratorR, typename _Sequence> 00396 inline bool 00397 operator==(const _Safe_iterator<_IteratorL, _Sequence>& __lhs, 00398 const _Safe_iterator<_IteratorR, _Sequence>& __rhs) 00399 { 00400 _GLIBCXX_DEBUG_VERIFY(! __lhs._M_singular() && ! __rhs._M_singular(), 00401 _M_message(__msg_iter_compare_bad) 00402 ._M_iterator(__lhs, "lhs") 00403 ._M_iterator(__rhs, "rhs")); 00404 _GLIBCXX_DEBUG_VERIFY(__lhs._M_can_compare(__rhs), 00405 _M_message(__msg_compare_different) 00406 ._M_iterator(__lhs, "lhs") 00407 ._M_iterator(__rhs, "rhs")); 00408 return __lhs.base() == __rhs.base(); 00409 } 00410 00411 template<typename _Iterator, typename _Sequence> 00412 inline bool 00413 operator==(const _Safe_iterator<_Iterator, _Sequence>& __lhs, 00414 const _Safe_iterator<_Iterator, _Sequence>& __rhs) 00415 { 00416 _GLIBCXX_DEBUG_VERIFY(! __lhs._M_singular() && ! __rhs._M_singular(), 00417 _M_message(__msg_iter_compare_bad) 00418 ._M_iterator(__lhs, "lhs") 00419 ._M_iterator(__rhs, "rhs")); 00420 _GLIBCXX_DEBUG_VERIFY(__lhs._M_can_compare(__rhs), 00421 _M_message(__msg_compare_different) 00422 ._M_iterator(__lhs, "lhs") 00423 ._M_iterator(__rhs, "rhs")); 00424 return __lhs.base() == __rhs.base(); 00425 } 00426 00427 template<typename _IteratorL, typename _IteratorR, typename _Sequence> 00428 inline bool 00429 operator!=(const _Safe_iterator<_IteratorL, _Sequence>& __lhs, 00430 const _Safe_iterator<_IteratorR, _Sequence>& __rhs) 00431 { 00432 _GLIBCXX_DEBUG_VERIFY(! __lhs._M_singular() && ! __rhs._M_singular(), 00433 _M_message(__msg_iter_compare_bad) 00434 ._M_iterator(__lhs, "lhs") 00435 ._M_iterator(__rhs, "rhs")); 00436 _GLIBCXX_DEBUG_VERIFY(__lhs._M_can_compare(__rhs), 00437 _M_message(__msg_compare_different) 00438 ._M_iterator(__lhs, "lhs") 00439 ._M_iterator(__rhs, "rhs")); 00440 return __lhs.base() != __rhs.base(); 00441 } 00442 00443 template<typename _Iterator, typename _Sequence> 00444 inline bool 00445 operator!=(const _Safe_iterator<_Iterator, _Sequence>& __lhs, 00446 const _Safe_iterator<_Iterator, _Sequence>& __rhs) 00447 { 00448 _GLIBCXX_DEBUG_VERIFY(! __lhs._M_singular() && ! __rhs._M_singular(), 00449 _M_message(__msg_iter_compare_bad) 00450 ._M_iterator(__lhs, "lhs") 00451 ._M_iterator(__rhs, "rhs")); 00452 _GLIBCXX_DEBUG_VERIFY(__lhs._M_can_compare(__rhs), 00453 _M_message(__msg_compare_different) 00454 ._M_iterator(__lhs, "lhs") 00455 ._M_iterator(__rhs, "rhs")); 00456 return __lhs.base() != __rhs.base(); 00457 } 00458 00459 template<typename _IteratorL, typename _IteratorR, typename _Sequence> 00460 inline bool 00461 operator<(const _Safe_iterator<_IteratorL, _Sequence>& __lhs, 00462 const _Safe_iterator<_IteratorR, _Sequence>& __rhs) 00463 { 00464 _GLIBCXX_DEBUG_VERIFY(! __lhs._M_singular() && ! __rhs._M_singular(), 00465 _M_message(__msg_iter_order_bad) 00466 ._M_iterator(__lhs, "lhs") 00467 ._M_iterator(__rhs, "rhs")); 00468 _GLIBCXX_DEBUG_VERIFY(__lhs._M_can_compare(__rhs), 00469 _M_message(__msg_order_different) 00470 ._M_iterator(__lhs, "lhs") 00471 ._M_iterator(__rhs, "rhs")); 00472 return __lhs.base() < __rhs.base(); 00473 } 00474 00475 template<typename _Iterator, typename _Sequence> 00476 inline bool 00477 operator<(const _Safe_iterator<_Iterator, _Sequence>& __lhs, 00478 const _Safe_iterator<_Iterator, _Sequence>& __rhs) 00479 { 00480 _GLIBCXX_DEBUG_VERIFY(! __lhs._M_singular() && ! __rhs._M_singular(), 00481 _M_message(__msg_iter_order_bad) 00482 ._M_iterator(__lhs, "lhs") 00483 ._M_iterator(__rhs, "rhs")); 00484 _GLIBCXX_DEBUG_VERIFY(__lhs._M_can_compare(__rhs), 00485 _M_message(__msg_order_different) 00486 ._M_iterator(__lhs, "lhs") 00487 ._M_iterator(__rhs, "rhs")); 00488 return __lhs.base() < __rhs.base(); 00489 } 00490 00491 template<typename _IteratorL, typename _IteratorR, typename _Sequence> 00492 inline bool 00493 operator<=(const _Safe_iterator<_IteratorL, _Sequence>& __lhs, 00494 const _Safe_iterator<_IteratorR, _Sequence>& __rhs) 00495 { 00496 _GLIBCXX_DEBUG_VERIFY(! __lhs._M_singular() && ! __rhs._M_singular(), 00497 _M_message(__msg_iter_order_bad) 00498 ._M_iterator(__lhs, "lhs") 00499 ._M_iterator(__rhs, "rhs")); 00500 _GLIBCXX_DEBUG_VERIFY(__lhs._M_can_compare(__rhs), 00501 _M_message(__msg_order_different) 00502 ._M_iterator(__lhs, "lhs") 00503 ._M_iterator(__rhs, "rhs")); 00504 return __lhs.base() <= __rhs.base(); 00505 } 00506 00507 template<typename _Iterator, typename _Sequence> 00508 inline bool 00509 operator<=(const _Safe_iterator<_Iterator, _Sequence>& __lhs, 00510 const _Safe_iterator<_Iterator, _Sequence>& __rhs) 00511 { 00512 _GLIBCXX_DEBUG_VERIFY(! __lhs._M_singular() && ! __rhs._M_singular(), 00513 _M_message(__msg_iter_order_bad) 00514 ._M_iterator(__lhs, "lhs") 00515 ._M_iterator(__rhs, "rhs")); 00516 _GLIBCXX_DEBUG_VERIFY(__lhs._M_can_compare(__rhs), 00517 _M_message(__msg_order_different) 00518 ._M_iterator(__lhs, "lhs") 00519 ._M_iterator(__rhs, "rhs")); 00520 return __lhs.base() <= __rhs.base(); 00521 } 00522 00523 template<typename _IteratorL, typename _IteratorR, typename _Sequence> 00524 inline bool 00525 operator>(const _Safe_iterator<_IteratorL, _Sequence>& __lhs, 00526 const _Safe_iterator<_IteratorR, _Sequence>& __rhs) 00527 { 00528 _GLIBCXX_DEBUG_VERIFY(! __lhs._M_singular() && ! __rhs._M_singular(), 00529 _M_message(__msg_iter_order_bad) 00530 ._M_iterator(__lhs, "lhs") 00531 ._M_iterator(__rhs, "rhs")); 00532 _GLIBCXX_DEBUG_VERIFY(__lhs._M_can_compare(__rhs), 00533 _M_message(__msg_order_different) 00534 ._M_iterator(__lhs, "lhs") 00535 ._M_iterator(__rhs, "rhs")); 00536 return __lhs.base() > __rhs.base(); 00537 } 00538 00539 template<typename _Iterator, typename _Sequence> 00540 inline bool 00541 operator>(const _Safe_iterator<_Iterator, _Sequence>& __lhs, 00542 const _Safe_iterator<_Iterator, _Sequence>& __rhs) 00543 { 00544 _GLIBCXX_DEBUG_VERIFY(! __lhs._M_singular() && ! __rhs._M_singular(), 00545 _M_message(__msg_iter_order_bad) 00546 ._M_iterator(__lhs, "lhs") 00547 ._M_iterator(__rhs, "rhs")); 00548 _GLIBCXX_DEBUG_VERIFY(__lhs._M_can_compare(__rhs), 00549 _M_message(__msg_order_different) 00550 ._M_iterator(__lhs, "lhs") 00551 ._M_iterator(__rhs, "rhs")); 00552 return __lhs.base() > __rhs.base(); 00553 } 00554 00555 template<typename _IteratorL, typename _IteratorR, typename _Sequence> 00556 inline bool 00557 operator>=(const _Safe_iterator<_IteratorL, _Sequence>& __lhs, 00558 const _Safe_iterator<_IteratorR, _Sequence>& __rhs) 00559 { 00560 _GLIBCXX_DEBUG_VERIFY(! __lhs._M_singular() && ! __rhs._M_singular(), 00561 _M_message(__msg_iter_order_bad) 00562 ._M_iterator(__lhs, "lhs") 00563 ._M_iterator(__rhs, "rhs")); 00564 _GLIBCXX_DEBUG_VERIFY(__lhs._M_can_compare(__rhs), 00565 _M_message(__msg_order_different) 00566 ._M_iterator(__lhs, "lhs") 00567 ._M_iterator(__rhs, "rhs")); 00568 return __lhs.base() >= __rhs.base(); 00569 } 00570 00571 template<typename _Iterator, typename _Sequence> 00572 inline bool 00573 operator>=(const _Safe_iterator<_Iterator, _Sequence>& __lhs, 00574 const _Safe_iterator<_Iterator, _Sequence>& __rhs) 00575 { 00576 _GLIBCXX_DEBUG_VERIFY(! __lhs._M_singular() && ! __rhs._M_singular(), 00577 _M_message(__msg_iter_order_bad) 00578 ._M_iterator(__lhs, "lhs") 00579 ._M_iterator(__rhs, "rhs")); 00580 _GLIBCXX_DEBUG_VERIFY(__lhs._M_can_compare(__rhs), 00581 _M_message(__msg_order_different) 00582 ._M_iterator(__lhs, "lhs") 00583 ._M_iterator(__rhs, "rhs")); 00584 return __lhs.base() >= __rhs.base(); 00585 } 00586 00587 // _GLIBCXX_RESOLVE_LIB_DEFECTS 00588 // According to the resolution of DR179 not only the various comparison 00589 // operators but also operator- must accept mixed iterator/const_iterator 00590 // parameters. 00591 template<typename _IteratorL, typename _IteratorR, typename _Sequence> 00592 inline typename _Safe_iterator<_IteratorL, _Sequence>::difference_type 00593 operator-(const _Safe_iterator<_IteratorL, _Sequence>& __lhs, 00594 const _Safe_iterator<_IteratorR, _Sequence>& __rhs) 00595 { 00596 _GLIBCXX_DEBUG_VERIFY(! __lhs._M_singular() && ! __rhs._M_singular(), 00597 _M_message(__msg_distance_bad) 00598 ._M_iterator(__lhs, "lhs") 00599 ._M_iterator(__rhs, "rhs")); 00600 _GLIBCXX_DEBUG_VERIFY(__lhs._M_can_compare(__rhs), 00601 _M_message(__msg_distance_different) 00602 ._M_iterator(__lhs, "lhs") 00603 ._M_iterator(__rhs, "rhs")); 00604 return __lhs.base() - __rhs.base(); 00605 } 00606 00607 template<typename _Iterator, typename _Sequence> 00608 inline _Safe_iterator<_Iterator, _Sequence> 00609 operator+(typename _Safe_iterator<_Iterator,_Sequence>::difference_type __n, 00610 const _Safe_iterator<_Iterator, _Sequence>& __i) 00611 { return __i + __n; } 00612 } // namespace __gnu_debug 00613 00614 #ifndef _GLIBCXX_EXPORT_TEMPLATE 00615 # include <debug/safe_iterator.tcc> 00616 #endif 00617 00618 #endif

Generated on Sun Sep 12 15:49:58 2004 for libstdc++ source by doxygen 1.3.8