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