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