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