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