1 // Safe iterator implementation -*- C++ -*- 2 3 // Copyright (C) 2003-2015 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 * Note that _Iterator must be the first base class so that it gets 114 * initialized before the iterator is being attached to the container's list 115 * of iterators and it is being detached before _Iterator get 116 * destroyed. Otherwise it would result in a data race. 117 */ 118 template<typename _Iterator, typename _Sequence> 119 class _Safe_iterator 120 : private _Iterator, 121 public _Safe_iterator_base 122 { 123 typedef _Iterator _Iter_base; 124 typedef _Safe_iterator_base _Safe_base; 125 typedef typename _Sequence::const_iterator _Const_iterator; 126 127 /// Determine if this is a constant iterator. 128 bool 129 _M_constant() const 130 { return std::__are_same<_Const_iterator, _Safe_iterator>::__value; } 131 132 typedef std::iterator_traits<_Iterator> _Traits; 133 134 struct _Attach_single 135 { }; 136 137 _Safe_iterator(const _Iterator& __i, _Safe_sequence_base* __seq, 138 _Attach_single) 139 _GLIBCXX_NOEXCEPT 140 : _Iter_base(__i) 141 { _M_attach_single(__seq); } 142 143 public: 144 typedef _Iterator iterator_type; 145 typedef typename _Traits::iterator_category iterator_category; 146 typedef typename _Traits::value_type value_type; 147 typedef typename _Traits::difference_type difference_type; 148 typedef typename _Traits::reference reference; 149 typedef typename _Traits::pointer pointer; 150 151 /// @post the iterator is singular and unattached 152 _Safe_iterator() _GLIBCXX_NOEXCEPT : _Iter_base() { } 153 154 /** 155 * @brief Safe iterator construction from an unsafe iterator and 156 * its sequence. 157 * 158 * @pre @p seq is not NULL 159 * @post this is not singular 160 */ 161 _Safe_iterator(const _Iterator& __i, const _Safe_sequence_base* __seq) 162 _GLIBCXX_NOEXCEPT 163 : _Iter_base(__i), _Safe_base(__seq, _M_constant()) 164 { 165 _GLIBCXX_DEBUG_VERIFY(!this->_M_singular(), 166 _M_message(__msg_init_singular) 167 ._M_iterator(*this, "this")); 168 } 169 170 /** 171 * @brief Copy construction. 172 */ 173 _Safe_iterator(const _Safe_iterator& __x) _GLIBCXX_NOEXCEPT 174 : _Iter_base(__x.base()) 175 { 176 // _GLIBCXX_RESOLVE_LIB_DEFECTS 177 // DR 408. Is vector<reverse_iterator<char*> > forbidden? 178 _GLIBCXX_DEBUG_VERIFY(!__x._M_singular() 179 || __x.base() == _Iterator(), 180 _M_message(__msg_init_copy_singular) 181 ._M_iterator(*this, "this") 182 ._M_iterator(__x, "other")); 183 _M_attach(__x._M_sequence); 184 } 185 186 #if __cplusplus >= 201103L 187 /** 188 * @brief Move construction. 189 * @post __x is singular and unattached 190 */ 191 _Safe_iterator(_Safe_iterator&& __x) noexcept 192 : _Iter_base() 193 { 194 _GLIBCXX_DEBUG_VERIFY(!__x._M_singular() 195 || __x.base() == _Iterator(), 196 _M_message(__msg_init_copy_singular) 197 ._M_iterator(*this, "this") 198 ._M_iterator(__x, "other")); 199 _Safe_sequence_base* __seq = __x._M_sequence; 200 __x._M_detach(); 201 std::swap(base(), __x.base()); 202 _M_attach(__seq); 203 } 204 #endif 205 206 /** 207 * @brief Converting constructor from a mutable iterator to a 208 * constant iterator. 209 */ 210 template<typename _MutableIterator> 211 _Safe_iterator( 212 const _Safe_iterator<_MutableIterator, 213 typename __gnu_cxx::__enable_if<(std::__are_same<_MutableIterator, 214 typename _Sequence::iterator::iterator_type>::__value), 215 _Sequence>::__type>& __x) _GLIBCXX_NOEXCEPT 216 : _Iter_base(__x.base()) 217 { 218 // _GLIBCXX_RESOLVE_LIB_DEFECTS 219 // DR 408. Is vector<reverse_iterator<char*> > forbidden? 220 _GLIBCXX_DEBUG_VERIFY(!__x._M_singular() 221 || __x.base() == _Iterator(), 222 _M_message(__msg_init_const_singular) 223 ._M_iterator(*this, "this") 224 ._M_iterator(__x, "other")); 225 _M_attach(__x._M_sequence); 226 } 227 228 /** 229 * @brief Copy assignment. 230 */ 231 _Safe_iterator& 232 operator=(const _Safe_iterator& __x) _GLIBCXX_NOEXCEPT 233 { 234 // _GLIBCXX_RESOLVE_LIB_DEFECTS 235 // DR 408. Is vector<reverse_iterator<char*> > forbidden? 236 _GLIBCXX_DEBUG_VERIFY(!__x._M_singular() 237 || __x.base() == _Iterator(), 238 _M_message(__msg_copy_singular) 239 ._M_iterator(*this, "this") 240 ._M_iterator(__x, "other")); 241 242 if (this->_M_sequence && this->_M_sequence == __x._M_sequence) 243 { 244 __gnu_cxx::__scoped_lock __l(this->_M_get_mutex()); 245 base() = __x.base(); 246 _M_version = __x._M_sequence->_M_version; 247 } 248 else 249 { 250 _M_detach(); 251 base() = __x.base(); 252 _M_attach(__x._M_sequence); 253 } 254 255 return *this; 256 } 257 258 #if __cplusplus >= 201103L 259 /** 260 * @brief Move assignment. 261 * @post __x is singular and unattached 262 */ 263 _Safe_iterator& 264 operator=(_Safe_iterator&& __x) noexcept 265 { 266 _GLIBCXX_DEBUG_VERIFY(this != &__x, 267 _M_message(__msg_self_move_assign) 268 ._M_iterator(*this, "this")); 269 _GLIBCXX_DEBUG_VERIFY(!__x._M_singular() 270 || __x.base() == _Iterator(), 271 _M_message(__msg_copy_singular) 272 ._M_iterator(*this, "this") 273 ._M_iterator(__x, "other")); 274 275 if (this->_M_sequence && this->_M_sequence == __x._M_sequence) 276 { 277 __gnu_cxx::__scoped_lock __l(this->_M_get_mutex()); 278 base() = __x.base(); 279 _M_version = __x._M_sequence->_M_version; 280 } 281 else 282 { 283 _M_detach(); 284 base() = __x.base(); 285 _M_attach(__x._M_sequence); 286 } 287 288 __x._M_detach(); 289 __x.base() = _Iterator(); 290 return *this; 291 } 292 #endif 293 294 /** 295 * @brief Iterator dereference. 296 * @pre iterator is dereferenceable 297 */ 298 reference 299 operator*() const _GLIBCXX_NOEXCEPT 300 { 301 _GLIBCXX_DEBUG_VERIFY(this->_M_dereferenceable(), 302 _M_message(__msg_bad_deref) 303 ._M_iterator(*this, "this")); 304 return *base(); 305 } 306 307 /** 308 * @brief Iterator dereference. 309 * @pre iterator is dereferenceable 310 * @todo Make this correct w.r.t. iterators that return proxies 311 */ 312 pointer 313 operator->() const _GLIBCXX_NOEXCEPT 314 { 315 _GLIBCXX_DEBUG_VERIFY(this->_M_dereferenceable(), 316 _M_message(__msg_bad_deref) 317 ._M_iterator(*this, "this")); 318 return std::__addressof(*base()); 319 } 320 321 // ------ Input iterator requirements ------ 322 /** 323 * @brief Iterator preincrement 324 * @pre iterator is incrementable 325 */ 326 _Safe_iterator& 327 operator++() _GLIBCXX_NOEXCEPT 328 { 329 _GLIBCXX_DEBUG_VERIFY(this->_M_incrementable(), 330 _M_message(__msg_bad_inc) 331 ._M_iterator(*this, "this")); 332 __gnu_cxx::__scoped_lock __l(this->_M_get_mutex()); 333 ++base(); 334 return *this; 335 } 336 337 /** 338 * @brief Iterator postincrement 339 * @pre iterator is incrementable 340 */ 341 _Safe_iterator 342 operator++(int) _GLIBCXX_NOEXCEPT 343 { 344 _GLIBCXX_DEBUG_VERIFY(this->_M_incrementable(), 345 _M_message(__msg_bad_inc) 346 ._M_iterator(*this, "this")); 347 __gnu_cxx::__scoped_lock __l(this->_M_get_mutex()); 348 return _Safe_iterator(base()++, this->_M_sequence, _Attach_single()); 349 } 350 351 // ------ Bidirectional iterator requirements ------ 352 /** 353 * @brief Iterator predecrement 354 * @pre iterator is decrementable 355 */ 356 _Safe_iterator& 357 operator--() _GLIBCXX_NOEXCEPT 358 { 359 _GLIBCXX_DEBUG_VERIFY(this->_M_decrementable(), 360 _M_message(__msg_bad_dec) 361 ._M_iterator(*this, "this")); 362 __gnu_cxx::__scoped_lock __l(this->_M_get_mutex()); 363 --base(); 364 return *this; 365 } 366 367 /** 368 * @brief Iterator postdecrement 369 * @pre iterator is decrementable 370 */ 371 _Safe_iterator 372 operator--(int) _GLIBCXX_NOEXCEPT 373 { 374 _GLIBCXX_DEBUG_VERIFY(this->_M_decrementable(), 375 _M_message(__msg_bad_dec) 376 ._M_iterator(*this, "this")); 377 __gnu_cxx::__scoped_lock __l(this->_M_get_mutex()); 378 return _Safe_iterator(base()--, this->_M_sequence, _Attach_single()); 379 } 380 381 // ------ Random access iterator requirements ------ 382 reference 383 operator[](const difference_type& __n) const _GLIBCXX_NOEXCEPT 384 { 385 _GLIBCXX_DEBUG_VERIFY(this->_M_can_advance(__n) 386 && this->_M_can_advance(__n+1), 387 _M_message(__msg_iter_subscript_oob) 388 ._M_iterator(*this)._M_integer(__n)); 389 return base()[__n]; 390 } 391 392 _Safe_iterator& 393 operator+=(const difference_type& __n) _GLIBCXX_NOEXCEPT 394 { 395 _GLIBCXX_DEBUG_VERIFY(this->_M_can_advance(__n), 396 _M_message(__msg_advance_oob) 397 ._M_iterator(*this)._M_integer(__n)); 398 __gnu_cxx::__scoped_lock __l(this->_M_get_mutex()); 399 base() += __n; 400 return *this; 401 } 402 403 _Safe_iterator 404 operator+(const difference_type& __n) const _GLIBCXX_NOEXCEPT 405 { 406 _GLIBCXX_DEBUG_VERIFY(this->_M_can_advance(__n), 407 _M_message(__msg_advance_oob) 408 ._M_iterator(*this)._M_integer(__n)); 409 return _Safe_iterator(base() + __n, this->_M_sequence); 410 } 411 412 _Safe_iterator& 413 operator-=(const difference_type& __n) _GLIBCXX_NOEXCEPT 414 { 415 _GLIBCXX_DEBUG_VERIFY(this->_M_can_advance(-__n), 416 _M_message(__msg_retreat_oob) 417 ._M_iterator(*this)._M_integer(__n)); 418 __gnu_cxx::__scoped_lock __l(this->_M_get_mutex()); 419 base() -= __n; 420 return *this; 421 } 422 423 _Safe_iterator 424 operator-(const difference_type& __n) const _GLIBCXX_NOEXCEPT 425 { 426 _GLIBCXX_DEBUG_VERIFY(this->_M_can_advance(-__n), 427 _M_message(__msg_retreat_oob) 428 ._M_iterator(*this)._M_integer(__n)); 429 return _Safe_iterator(base() - __n, this->_M_sequence); 430 } 431 432 // ------ Utilities ------ 433 /** 434 * @brief Return the underlying iterator 435 */ 436 _Iterator& 437 base() _GLIBCXX_NOEXCEPT { return *this; } 438 439 const _Iterator& 440 base() const _GLIBCXX_NOEXCEPT { return *this; } 441 442 /** 443 * @brief Conversion to underlying non-debug iterator to allow 444 * better interaction with non-debug containers. 445 */ 446 operator _Iterator() const _GLIBCXX_NOEXCEPT { return *this; } 447 448 /** Attach iterator to the given sequence. */ 449 void 450 _M_attach(_Safe_sequence_base* __seq) 451 { _Safe_base::_M_attach(__seq, _M_constant()); } 452 453 /** Likewise, but not thread-safe. */ 454 void 455 _M_attach_single(_Safe_sequence_base* __seq) 456 { _Safe_base::_M_attach_single(__seq, _M_constant()); } 457 458 /// Is the iterator dereferenceable? 459 bool 460 _M_dereferenceable() const 461 { return !this->_M_singular() && !_M_is_end() && !_M_is_before_begin(); } 462 463 /// Is the iterator before a dereferenceable one? 464 bool 465 _M_before_dereferenceable() const 466 { 467 if (this->_M_incrementable()) 468 { 469 _Iterator __base = base(); 470 return ++__base != _M_get_sequence()->_M_base().end(); 471 } 472 return false; 473 } 474 475 /// Is the iterator incrementable? 476 bool 477 _M_incrementable() const 478 { return !this->_M_singular() && !_M_is_end(); } 479 480 // Is the iterator decrementable? 481 bool 482 _M_decrementable() const { return !_M_singular() && !_M_is_begin(); } 483 484 // Can we advance the iterator @p __n steps (@p __n may be negative) 485 bool 486 _M_can_advance(const difference_type& __n) const; 487 488 // Is the iterator range [*this, __rhs) valid? 489 bool 490 _M_valid_range(const _Safe_iterator& __rhs) const; 491 492 // The sequence this iterator references. 493 typename 494 __gnu_cxx::__conditional_type<std::__are_same<_Const_iterator, 495 _Safe_iterator>::__value, 496 const _Sequence*, 497 _Sequence*>::__type 498 _M_get_sequence() const 499 { return static_cast<_Sequence*>(_M_sequence); } 500 501 /// Is this iterator equal to the sequence's begin() iterator? 502 bool 503 _M_is_begin() const 504 { return base() == _M_get_sequence()->_M_base().begin(); } 505 506 /// Is this iterator equal to the sequence's end() iterator? 507 bool 508 _M_is_end() const 509 { return base() == _M_get_sequence()->_M_base().end(); } 510 511 /// Is this iterator equal to the sequence's before_begin() iterator if 512 /// any? 513 bool 514 _M_is_before_begin() const 515 { return _BeforeBeginHelper<_Sequence>::_S_Is(*this); } 516 517 /// Is this iterator equal to the sequence's before_begin() iterator if 518 /// any or begin() otherwise? 519 bool 520 _M_is_beginnest() const 521 { return _BeforeBeginHelper<_Sequence>::_S_Is_Beginnest(*this); } 522 }; 523 524 template<typename _IteratorL, typename _IteratorR, typename _Sequence> 525 inline bool 526 operator==(const _Safe_iterator<_IteratorL, _Sequence>& __lhs, 527 const _Safe_iterator<_IteratorR, _Sequence>& __rhs) 528 _GLIBCXX_NOEXCEPT 529 { 530 _GLIBCXX_DEBUG_VERIFY(! __lhs._M_singular() && ! __rhs._M_singular(), 531 _M_message(__msg_iter_compare_bad) 532 ._M_iterator(__lhs, "lhs") 533 ._M_iterator(__rhs, "rhs")); 534 _GLIBCXX_DEBUG_VERIFY(__lhs._M_can_compare(__rhs), 535 _M_message(__msg_compare_different) 536 ._M_iterator(__lhs, "lhs") 537 ._M_iterator(__rhs, "rhs")); 538 return __lhs.base() == __rhs.base(); 539 } 540 541 template<typename _Iterator, typename _Sequence> 542 inline bool 543 operator==(const _Safe_iterator<_Iterator, _Sequence>& __lhs, 544 const _Safe_iterator<_Iterator, _Sequence>& __rhs) 545 _GLIBCXX_NOEXCEPT 546 { 547 _GLIBCXX_DEBUG_VERIFY(! __lhs._M_singular() && ! __rhs._M_singular(), 548 _M_message(__msg_iter_compare_bad) 549 ._M_iterator(__lhs, "lhs") 550 ._M_iterator(__rhs, "rhs")); 551 _GLIBCXX_DEBUG_VERIFY(__lhs._M_can_compare(__rhs), 552 _M_message(__msg_compare_different) 553 ._M_iterator(__lhs, "lhs") 554 ._M_iterator(__rhs, "rhs")); 555 return __lhs.base() == __rhs.base(); 556 } 557 558 template<typename _IteratorL, typename _IteratorR, typename _Sequence> 559 inline bool 560 operator!=(const _Safe_iterator<_IteratorL, _Sequence>& __lhs, 561 const _Safe_iterator<_IteratorR, _Sequence>& __rhs) 562 _GLIBCXX_NOEXCEPT 563 { 564 _GLIBCXX_DEBUG_VERIFY(! __lhs._M_singular() && ! __rhs._M_singular(), 565 _M_message(__msg_iter_compare_bad) 566 ._M_iterator(__lhs, "lhs") 567 ._M_iterator(__rhs, "rhs")); 568 _GLIBCXX_DEBUG_VERIFY(__lhs._M_can_compare(__rhs), 569 _M_message(__msg_compare_different) 570 ._M_iterator(__lhs, "lhs") 571 ._M_iterator(__rhs, "rhs")); 572 return __lhs.base() != __rhs.base(); 573 } 574 575 template<typename _Iterator, typename _Sequence> 576 inline bool 577 operator!=(const _Safe_iterator<_Iterator, _Sequence>& __lhs, 578 const _Safe_iterator<_Iterator, _Sequence>& __rhs) 579 _GLIBCXX_NOEXCEPT 580 { 581 _GLIBCXX_DEBUG_VERIFY(! __lhs._M_singular() && ! __rhs._M_singular(), 582 _M_message(__msg_iter_compare_bad) 583 ._M_iterator(__lhs, "lhs") 584 ._M_iterator(__rhs, "rhs")); 585 _GLIBCXX_DEBUG_VERIFY(__lhs._M_can_compare(__rhs), 586 _M_message(__msg_compare_different) 587 ._M_iterator(__lhs, "lhs") 588 ._M_iterator(__rhs, "rhs")); 589 return __lhs.base() != __rhs.base(); 590 } 591 592 template<typename _IteratorL, typename _IteratorR, typename _Sequence> 593 inline bool 594 operator<(const _Safe_iterator<_IteratorL, _Sequence>& __lhs, 595 const _Safe_iterator<_IteratorR, _Sequence>& __rhs) 596 _GLIBCXX_NOEXCEPT 597 { 598 _GLIBCXX_DEBUG_VERIFY(! __lhs._M_singular() && ! __rhs._M_singular(), 599 _M_message(__msg_iter_order_bad) 600 ._M_iterator(__lhs, "lhs") 601 ._M_iterator(__rhs, "rhs")); 602 _GLIBCXX_DEBUG_VERIFY(__lhs._M_can_compare(__rhs), 603 _M_message(__msg_order_different) 604 ._M_iterator(__lhs, "lhs") 605 ._M_iterator(__rhs, "rhs")); 606 return __lhs.base() < __rhs.base(); 607 } 608 609 template<typename _Iterator, typename _Sequence> 610 inline bool 611 operator<(const _Safe_iterator<_Iterator, _Sequence>& __lhs, 612 const _Safe_iterator<_Iterator, _Sequence>& __rhs) 613 _GLIBCXX_NOEXCEPT 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 _IteratorL, typename _IteratorR, typename _Sequence> 627 inline bool 628 operator<=(const _Safe_iterator<_IteratorL, _Sequence>& __lhs, 629 const _Safe_iterator<_IteratorR, _Sequence>& __rhs) 630 _GLIBCXX_NOEXCEPT 631 { 632 _GLIBCXX_DEBUG_VERIFY(! __lhs._M_singular() && ! __rhs._M_singular(), 633 _M_message(__msg_iter_order_bad) 634 ._M_iterator(__lhs, "lhs") 635 ._M_iterator(__rhs, "rhs")); 636 _GLIBCXX_DEBUG_VERIFY(__lhs._M_can_compare(__rhs), 637 _M_message(__msg_order_different) 638 ._M_iterator(__lhs, "lhs") 639 ._M_iterator(__rhs, "rhs")); 640 return __lhs.base() <= __rhs.base(); 641 } 642 643 template<typename _Iterator, typename _Sequence> 644 inline bool 645 operator<=(const _Safe_iterator<_Iterator, _Sequence>& __lhs, 646 const _Safe_iterator<_Iterator, _Sequence>& __rhs) 647 _GLIBCXX_NOEXCEPT 648 { 649 _GLIBCXX_DEBUG_VERIFY(! __lhs._M_singular() && ! __rhs._M_singular(), 650 _M_message(__msg_iter_order_bad) 651 ._M_iterator(__lhs, "lhs") 652 ._M_iterator(__rhs, "rhs")); 653 _GLIBCXX_DEBUG_VERIFY(__lhs._M_can_compare(__rhs), 654 _M_message(__msg_order_different) 655 ._M_iterator(__lhs, "lhs") 656 ._M_iterator(__rhs, "rhs")); 657 return __lhs.base() <= __rhs.base(); 658 } 659 660 template<typename _IteratorL, typename _IteratorR, typename _Sequence> 661 inline bool 662 operator>(const _Safe_iterator<_IteratorL, _Sequence>& __lhs, 663 const _Safe_iterator<_IteratorR, _Sequence>& __rhs) 664 _GLIBCXX_NOEXCEPT 665 { 666 _GLIBCXX_DEBUG_VERIFY(! __lhs._M_singular() && ! __rhs._M_singular(), 667 _M_message(__msg_iter_order_bad) 668 ._M_iterator(__lhs, "lhs") 669 ._M_iterator(__rhs, "rhs")); 670 _GLIBCXX_DEBUG_VERIFY(__lhs._M_can_compare(__rhs), 671 _M_message(__msg_order_different) 672 ._M_iterator(__lhs, "lhs") 673 ._M_iterator(__rhs, "rhs")); 674 return __lhs.base() > __rhs.base(); 675 } 676 677 template<typename _Iterator, typename _Sequence> 678 inline bool 679 operator>(const _Safe_iterator<_Iterator, _Sequence>& __lhs, 680 const _Safe_iterator<_Iterator, _Sequence>& __rhs) 681 _GLIBCXX_NOEXCEPT 682 { 683 _GLIBCXX_DEBUG_VERIFY(! __lhs._M_singular() && ! __rhs._M_singular(), 684 _M_message(__msg_iter_order_bad) 685 ._M_iterator(__lhs, "lhs") 686 ._M_iterator(__rhs, "rhs")); 687 _GLIBCXX_DEBUG_VERIFY(__lhs._M_can_compare(__rhs), 688 _M_message(__msg_order_different) 689 ._M_iterator(__lhs, "lhs") 690 ._M_iterator(__rhs, "rhs")); 691 return __lhs.base() > __rhs.base(); 692 } 693 694 template<typename _IteratorL, typename _IteratorR, typename _Sequence> 695 inline bool 696 operator>=(const _Safe_iterator<_IteratorL, _Sequence>& __lhs, 697 const _Safe_iterator<_IteratorR, _Sequence>& __rhs) 698 _GLIBCXX_NOEXCEPT 699 { 700 _GLIBCXX_DEBUG_VERIFY(! __lhs._M_singular() && ! __rhs._M_singular(), 701 _M_message(__msg_iter_order_bad) 702 ._M_iterator(__lhs, "lhs") 703 ._M_iterator(__rhs, "rhs")); 704 _GLIBCXX_DEBUG_VERIFY(__lhs._M_can_compare(__rhs), 705 _M_message(__msg_order_different) 706 ._M_iterator(__lhs, "lhs") 707 ._M_iterator(__rhs, "rhs")); 708 return __lhs.base() >= __rhs.base(); 709 } 710 711 template<typename _Iterator, typename _Sequence> 712 inline bool 713 operator>=(const _Safe_iterator<_Iterator, _Sequence>& __lhs, 714 const _Safe_iterator<_Iterator, _Sequence>& __rhs) 715 _GLIBCXX_NOEXCEPT 716 { 717 _GLIBCXX_DEBUG_VERIFY(! __lhs._M_singular() && ! __rhs._M_singular(), 718 _M_message(__msg_iter_order_bad) 719 ._M_iterator(__lhs, "lhs") 720 ._M_iterator(__rhs, "rhs")); 721 _GLIBCXX_DEBUG_VERIFY(__lhs._M_can_compare(__rhs), 722 _M_message(__msg_order_different) 723 ._M_iterator(__lhs, "lhs") 724 ._M_iterator(__rhs, "rhs")); 725 return __lhs.base() >= __rhs.base(); 726 } 727 728 // _GLIBCXX_RESOLVE_LIB_DEFECTS 729 // According to the resolution of DR179 not only the various comparison 730 // operators but also operator- must accept mixed iterator/const_iterator 731 // parameters. 732 template<typename _IteratorL, typename _IteratorR, typename _Sequence> 733 inline typename _Safe_iterator<_IteratorL, _Sequence>::difference_type 734 operator-(const _Safe_iterator<_IteratorL, _Sequence>& __lhs, 735 const _Safe_iterator<_IteratorR, _Sequence>& __rhs) 736 _GLIBCXX_NOEXCEPT 737 { 738 _GLIBCXX_DEBUG_VERIFY(! __lhs._M_singular() && ! __rhs._M_singular(), 739 _M_message(__msg_distance_bad) 740 ._M_iterator(__lhs, "lhs") 741 ._M_iterator(__rhs, "rhs")); 742 _GLIBCXX_DEBUG_VERIFY(__lhs._M_can_compare(__rhs), 743 _M_message(__msg_distance_different) 744 ._M_iterator(__lhs, "lhs") 745 ._M_iterator(__rhs, "rhs")); 746 return __lhs.base() - __rhs.base(); 747 } 748 749 template<typename _Iterator, typename _Sequence> 750 inline typename _Safe_iterator<_Iterator, _Sequence>::difference_type 751 operator-(const _Safe_iterator<_Iterator, _Sequence>& __lhs, 752 const _Safe_iterator<_Iterator, _Sequence>& __rhs) 753 _GLIBCXX_NOEXCEPT 754 { 755 _GLIBCXX_DEBUG_VERIFY(! __lhs._M_singular() && ! __rhs._M_singular(), 756 _M_message(__msg_distance_bad) 757 ._M_iterator(__lhs, "lhs") 758 ._M_iterator(__rhs, "rhs")); 759 _GLIBCXX_DEBUG_VERIFY(__lhs._M_can_compare(__rhs), 760 _M_message(__msg_distance_different) 761 ._M_iterator(__lhs, "lhs") 762 ._M_iterator(__rhs, "rhs")); 763 return __lhs.base() - __rhs.base(); 764 } 765 766 template<typename _Iterator, typename _Sequence> 767 inline _Safe_iterator<_Iterator, _Sequence> 768 operator+(typename _Safe_iterator<_Iterator,_Sequence>::difference_type __n, 769 const _Safe_iterator<_Iterator, _Sequence>& __i) _GLIBCXX_NOEXCEPT 770 { return __i + __n; } 771 } // namespace __gnu_debug 772 773 #include <debug/safe_iterator.tcc> 774 775 #endif 776