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