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