1 // Safe iterator implementation -*- C++ -*-
3 // Copyright (C) 2003, 2004, 2005, 2006, 2009, 2010, 2011, 2012
4 // Free Software Foundation, Inc.
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)
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.
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.
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/>.
26 /** @file debug/safe_iterator.h
27 * This file is a GNU debug extension to the Standard C++ Library.
30 #ifndef _GLIBCXX_DEBUG_SAFE_ITERATOR_H
31 #define _GLIBCXX_DEBUG_SAFE_ITERATOR_H 1
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>
43 /** Helper struct to deal with sequence offering a before_begin
46 template <typename _Sequence>
47 struct _BeforeBeginHelper
49 typedef typename _Sequence::const_iterator _It;
50 typedef typename _It::iterator_type _BaseIt;
53 _S_Is(_BaseIt, const _Sequence*)
57 _S_Is_Beginnest(_BaseIt __it, const _Sequence* __seq)
58 { return __it == __seq->_M_base().begin(); }
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.
66 __check_singular_aux(const _Safe_iterator_base* __x)
67 { return __x->_M_singular(); }
69 /** The precision to which we can calculate the distance between
72 enum _Distance_precision
74 __dp_equality, //< Can compare iterator equality, only
75 __dp_sign, //< Can determine equality and ordering
76 __dp_exact //< Can determine distance precisely
79 /** Determine the distance between two iterators with some known
82 template<typename _Iterator1, typename _Iterator2>
83 inline std::pair<typename std::iterator_traits<_Iterator1>::difference_type,
85 __get_distance(const _Iterator1& __lhs, const _Iterator2& __rhs,
86 std::random_access_iterator_tag)
87 { return std::make_pair(__rhs - __lhs, __dp_exact); }
89 template<typename _Iterator1, typename _Iterator2>
90 inline std::pair<typename std::iterator_traits<_Iterator1>::difference_type,
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); }
96 template<typename _Iterator1, typename _Iterator2>
97 inline std::pair<typename std::iterator_traits<_Iterator1>::difference_type,
99 __get_distance(const _Iterator1& __lhs, const _Iterator2& __rhs)
101 typedef typename std::iterator_traits<_Iterator1>::iterator_category
103 return __get_distance(__lhs, __rhs, _Category());
106 /** \brief Safe iterator wrapper.
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.
117 template<typename _Iterator, typename _Sequence>
118 class _Safe_iterator : public _Safe_iterator_base
120 typedef _Safe_iterator _Self;
122 /// The underlying iterator
123 _Iterator _M_current;
125 /// Determine if this is a constant iterator.
129 typedef typename _Sequence::const_iterator const_iterator;
130 return std::__are_same<const_iterator, _Safe_iterator>::__value;
133 typedef std::iterator_traits<_Iterator> _Traits;
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;
143 /// @post the iterator is singular and unattached
144 _Safe_iterator() : _M_current() { }
147 * @brief Safe iterator construction from an unsafe iterator and
150 * @pre @p seq is not NULL
151 * @post this is not singular
153 _Safe_iterator(const _Iterator& __i, const _Sequence* __seq)
154 : _Safe_iterator_base(__seq, _M_constant()), _M_current(__i)
156 _GLIBCXX_DEBUG_VERIFY(! this->_M_singular(),
157 _M_message(__msg_init_singular)
158 ._M_iterator(*this, "this"));
162 * @brief Copy construction.
164 _Safe_iterator(const _Safe_iterator& __x)
165 : _Safe_iterator_base(__x, _M_constant()), _M_current(__x._M_current)
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"));
176 #ifdef __GXX_EXPERIMENTAL_CXX0X__
178 * @brief Move construction.
179 * @post __x is singular and unattached
181 _Safe_iterator(_Safe_iterator&& __x) : _M_current()
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);
195 * @brief Converting constructor from a mutable iterator to a
198 template<typename _MutableIterator>
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())
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"));
216 * @brief Copy assignment.
219 operator=(const _Safe_iterator& __x)
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);
233 #ifdef __GXX_EXPERIMENTAL_CXX0X__
235 * @brief Move assignment.
236 * @post __x is singular and unattached
239 operator=(_Safe_iterator&& __x)
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);
249 __x._M_current = _Iterator();
255 * @brief Iterator dereference.
256 * @pre iterator is dereferenceable
261 _GLIBCXX_DEBUG_VERIFY(this->_M_dereferenceable(),
262 _M_message(__msg_bad_deref)
263 ._M_iterator(*this, "this"));
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
276 _GLIBCXX_DEBUG_VERIFY(this->_M_dereferenceable(),
277 _M_message(__msg_bad_deref)
278 ._M_iterator(*this, "this"));
282 // ------ Input iterator requirements ------
284 * @brief Iterator preincrement
285 * @pre iterator is incrementable
290 _GLIBCXX_DEBUG_VERIFY(this->_M_incrementable(),
291 _M_message(__msg_bad_inc)
292 ._M_iterator(*this, "this"));
298 * @brief Iterator postincrement
299 * @pre iterator is incrementable
304 _GLIBCXX_DEBUG_VERIFY(this->_M_incrementable(),
305 _M_message(__msg_bad_inc)
306 ._M_iterator(*this, "this"));
307 _Safe_iterator __tmp(*this);
312 // ------ Bidirectional iterator requirements ------
314 * @brief Iterator predecrement
315 * @pre iterator is decrementable
320 _GLIBCXX_DEBUG_VERIFY(this->_M_decrementable(),
321 _M_message(__msg_bad_dec)
322 ._M_iterator(*this, "this"));
328 * @brief Iterator postdecrement
329 * @pre iterator is decrementable
334 _GLIBCXX_DEBUG_VERIFY(this->_M_decrementable(),
335 _M_message(__msg_bad_dec)
336 ._M_iterator(*this, "this"));
337 _Safe_iterator __tmp(*this);
342 // ------ Random access iterator requirements ------
344 operator[](const difference_type& __n) const
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));
351 return _M_current[__n];
355 operator+=(const difference_type& __n)
357 _GLIBCXX_DEBUG_VERIFY(this->_M_can_advance(__n),
358 _M_message(__msg_advance_oob)
359 ._M_iterator(*this)._M_integer(__n));
365 operator+(const difference_type& __n) const
367 _Safe_iterator __tmp(*this);
373 operator-=(const difference_type& __n)
375 _GLIBCXX_DEBUG_VERIFY(this->_M_can_advance(-__n),
376 _M_message(__msg_retreat_oob)
377 ._M_iterator(*this)._M_integer(__n));
383 operator-(const difference_type& __n) const
385 _Safe_iterator __tmp(*this);
390 // ------ Utilities ------
392 * @brief Return the underlying iterator
395 base() const { return _M_current; }
398 * @brief Conversion to underlying non-debug iterator to allow
399 * better interaction with non-debug containers.
401 operator _Iterator() const { return _M_current; }
403 /** Attach iterator to the given sequence. */
405 _M_attach(_Safe_sequence_base* __seq)
407 _Safe_iterator_base::_M_attach(__seq, _M_constant());
410 /** Likewise, but not thread-safe. */
412 _M_attach_single(_Safe_sequence_base* __seq)
414 _Safe_iterator_base::_M_attach_single(__seq, _M_constant());
417 /// Is the iterator dereferenceable?
419 _M_dereferenceable() const
420 { return !this->_M_singular() && !_M_is_end() && !_M_is_before_begin(); }
422 /// Is the iterator before a dereferenceable one?
424 _M_before_dereferenceable() const
426 if (this->_M_incrementable())
428 _Iterator __base = base();
429 return ++__base != _M_get_sequence()->_M_base().end();
434 /// Is the iterator incrementable?
436 _M_incrementable() const
437 { return !this->_M_singular() && !_M_is_end(); }
439 // Is the iterator decrementable?
441 _M_decrementable() const { return !_M_singular() && !_M_is_begin(); }
443 // Can we advance the iterator @p __n steps (@p __n may be negative)
445 _M_can_advance(const difference_type& __n) const;
447 // Is the iterator range [*this, __rhs) valid?
448 template<typename _Other>
450 _M_valid_range(const _Safe_iterator<_Other, _Sequence>& __rhs) const;
452 // The sequence this iterator references.
454 _M_get_sequence() const
455 { return static_cast<const _Sequence*>(_M_sequence); }
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(); }
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(); }
465 /// Is this iterator equal to the sequence's before_begin() iterator if
467 bool _M_is_before_begin() const
469 return _BeforeBeginHelper<_Sequence>::_S_Is(base(), _M_get_sequence());
472 /// Is this iterator equal to the sequence's before_begin() iterator if
473 /// any or begin() otherwise?
474 bool _M_is_beginnest() const
476 return _BeforeBeginHelper<_Sequence>::_S_Is_Beginnest(base(),
481 template<typename _IteratorL, typename _IteratorR, typename _Sequence>
483 operator==(const _Safe_iterator<_IteratorL, _Sequence>& __lhs,
484 const _Safe_iterator<_IteratorR, _Sequence>& __rhs)
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();
497 template<typename _Iterator, typename _Sequence>
499 operator==(const _Safe_iterator<_Iterator, _Sequence>& __lhs,
500 const _Safe_iterator<_Iterator, _Sequence>& __rhs)
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();
513 template<typename _IteratorL, typename _IteratorR, typename _Sequence>
515 operator!=(const _Safe_iterator<_IteratorL, _Sequence>& __lhs,
516 const _Safe_iterator<_IteratorR, _Sequence>& __rhs)
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();
529 template<typename _Iterator, typename _Sequence>
531 operator!=(const _Safe_iterator<_Iterator, _Sequence>& __lhs,
532 const _Safe_iterator<_Iterator, _Sequence>& __rhs)
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();
545 template<typename _IteratorL, typename _IteratorR, typename _Sequence>
547 operator<(const _Safe_iterator<_IteratorL, _Sequence>& __lhs,
548 const _Safe_iterator<_IteratorR, _Sequence>& __rhs)
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();
561 template<typename _Iterator, typename _Sequence>
563 operator<(const _Safe_iterator<_Iterator, _Sequence>& __lhs,
564 const _Safe_iterator<_Iterator, _Sequence>& __rhs)
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();
577 template<typename _IteratorL, typename _IteratorR, typename _Sequence>
579 operator<=(const _Safe_iterator<_IteratorL, _Sequence>& __lhs,
580 const _Safe_iterator<_IteratorR, _Sequence>& __rhs)
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();
593 template<typename _Iterator, typename _Sequence>
595 operator<=(const _Safe_iterator<_Iterator, _Sequence>& __lhs,
596 const _Safe_iterator<_Iterator, _Sequence>& __rhs)
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();
609 template<typename _IteratorL, typename _IteratorR, typename _Sequence>
611 operator>(const _Safe_iterator<_IteratorL, _Sequence>& __lhs,
612 const _Safe_iterator<_IteratorR, _Sequence>& __rhs)
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();
625 template<typename _Iterator, typename _Sequence>
627 operator>(const _Safe_iterator<_Iterator, _Sequence>& __lhs,
628 const _Safe_iterator<_Iterator, _Sequence>& __rhs)
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();
641 template<typename _IteratorL, typename _IteratorR, typename _Sequence>
643 operator>=(const _Safe_iterator<_IteratorL, _Sequence>& __lhs,
644 const _Safe_iterator<_IteratorR, _Sequence>& __rhs)
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();
657 template<typename _Iterator, typename _Sequence>
659 operator>=(const _Safe_iterator<_Iterator, _Sequence>& __lhs,
660 const _Safe_iterator<_Iterator, _Sequence>& __rhs)
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();
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
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)
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();
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)
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();
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; }
715 // Helper struct to detect random access safe iterators.
716 template<typename _Iterator>
717 struct __is_safe_random_iterator
719 enum { __value = 0 };
720 typedef std::__false_type __type;
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>::
730 template<typename _Iterator>
732 : std::_Iter_base<_Iterator, __is_safe_random_iterator<_Iterator>::__value>
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.
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
747 #include <debug/safe_iterator.tcc>