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 _M_Is(_BaseIt __it, const _Sequence* __seq)
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.
62 __check_singular_aux(const _Safe_iterator_base* __x)
63 { return __x->_M_singular(); }
65 /** The precision to which we can calculate the distance between
68 enum _Distance_precision
70 __dp_equality, //< Can compare iterator equality, only
71 __dp_sign, //< Can determine equality and ordering
72 __dp_exact //< Can determine distance precisely
75 /** Determine the distance between two iterators with some known
78 template<typename _Iterator1, typename _Iterator2>
79 inline std::pair<typename std::iterator_traits<_Iterator1>::difference_type,
81 __get_distance(const _Iterator1& __lhs, const _Iterator2& __rhs,
82 std::random_access_iterator_tag)
83 { return std::make_pair(__rhs - __lhs, __dp_exact); }
85 template<typename _Iterator1, typename _Iterator2>
86 inline std::pair<typename std::iterator_traits<_Iterator1>::difference_type,
88 __get_distance(const _Iterator1& __lhs, const _Iterator2& __rhs,
89 std::forward_iterator_tag)
90 { return std::make_pair(__lhs == __rhs? 0 : 1, __dp_equality); }
92 template<typename _Iterator1, typename _Iterator2>
93 inline std::pair<typename std::iterator_traits<_Iterator1>::difference_type,
95 __get_distance(const _Iterator1& __lhs, const _Iterator2& __rhs)
97 typedef typename std::iterator_traits<_Iterator1>::iterator_category
99 return __get_distance(__lhs, __rhs, _Category());
102 /** \brief Safe iterator wrapper.
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.
113 template<typename _Iterator, typename _Sequence>
114 class _Safe_iterator : public _Safe_iterator_base
116 typedef _Safe_iterator _Self;
118 /// The underlying iterator
119 _Iterator _M_current;
121 /// Determine if this is a constant iterator.
125 typedef typename _Sequence::const_iterator const_iterator;
126 return std::__are_same<const_iterator, _Safe_iterator>::__value;
129 typedef std::iterator_traits<_Iterator> _Traits;
132 typedef _Iterator iterator_type;
133 typedef typename _Traits::iterator_category iterator_category;
134 typedef typename _Traits::value_type value_type;
135 typedef typename _Traits::difference_type difference_type;
136 typedef typename _Traits::reference reference;
137 typedef typename _Traits::pointer pointer;
139 /// @post the iterator is singular and unattached
140 _Safe_iterator() : _M_current() { }
143 * @brief Safe iterator construction from an unsafe iterator and
146 * @pre @p seq is not NULL
147 * @post this is not singular
149 _Safe_iterator(const _Iterator& __i, const _Sequence* __seq)
150 : _Safe_iterator_base(__seq, _M_constant()), _M_current(__i)
152 _GLIBCXX_DEBUG_VERIFY(! this->_M_singular(),
153 _M_message(__msg_init_singular)
154 ._M_iterator(*this, "this"));
158 * @brief Copy construction.
160 _Safe_iterator(const _Safe_iterator& __x)
161 : _Safe_iterator_base(__x, _M_constant()), _M_current(__x._M_current)
163 // _GLIBCXX_RESOLVE_LIB_DEFECTS
164 // DR 408. Is vector<reverse_iterator<char*> > forbidden?
165 _GLIBCXX_DEBUG_VERIFY(!__x._M_singular()
166 || __x._M_current == _Iterator(),
167 _M_message(__msg_init_copy_singular)
168 ._M_iterator(*this, "this")
169 ._M_iterator(__x, "other"));
172 #ifdef __GXX_EXPERIMENTAL_CXX0X__
174 * @brief Move construction.
175 * @post __x is singular and unattached
177 _Safe_iterator(_Safe_iterator&& __x) : _M_current()
179 _GLIBCXX_DEBUG_VERIFY(!__x._M_singular()
180 || __x._M_current == _Iterator(),
181 _M_message(__msg_init_copy_singular)
182 ._M_iterator(*this, "this")
183 ._M_iterator(__x, "other"));
184 std::swap(_M_current, __x._M_current);
185 this->_M_attach(__x._M_sequence);
191 * @brief Converting constructor from a mutable iterator to a
194 template<typename _MutableIterator>
196 const _Safe_iterator<_MutableIterator,
197 typename __gnu_cxx::__enable_if<(std::__are_same<_MutableIterator,
198 typename _Sequence::iterator::iterator_type>::__value),
199 _Sequence>::__type>& __x)
200 : _Safe_iterator_base(__x, _M_constant()), _M_current(__x.base())
202 // _GLIBCXX_RESOLVE_LIB_DEFECTS
203 // DR 408. Is vector<reverse_iterator<char*> > forbidden?
204 _GLIBCXX_DEBUG_VERIFY(!__x._M_singular()
205 || __x.base() == _Iterator(),
206 _M_message(__msg_init_const_singular)
207 ._M_iterator(*this, "this")
208 ._M_iterator(__x, "other"));
212 * @brief Copy assignment.
215 operator=(const _Safe_iterator& __x)
217 // _GLIBCXX_RESOLVE_LIB_DEFECTS
218 // DR 408. Is vector<reverse_iterator<char*> > forbidden?
219 _GLIBCXX_DEBUG_VERIFY(!__x._M_singular()
220 || __x._M_current == _Iterator(),
221 _M_message(__msg_copy_singular)
222 ._M_iterator(*this, "this")
223 ._M_iterator(__x, "other"));
224 _M_current = __x._M_current;
225 this->_M_attach(__x._M_sequence);
229 #ifdef __GXX_EXPERIMENTAL_CXX0X__
231 * @brief Move assignment.
232 * @post __x is singular and unattached
235 operator=(_Safe_iterator&& __x)
237 _GLIBCXX_DEBUG_VERIFY(!__x._M_singular()
238 || __x._M_current == _Iterator(),
239 _M_message(__msg_copy_singular)
240 ._M_iterator(*this, "this")
241 ._M_iterator(__x, "other"));
242 _M_current = __x._M_current;
243 _M_attach(__x._M_sequence);
245 __x._M_current = _Iterator();
251 * @brief Iterator dereference.
252 * @pre iterator is dereferenceable
257 _GLIBCXX_DEBUG_VERIFY(this->_M_dereferenceable(),
258 _M_message(__msg_bad_deref)
259 ._M_iterator(*this, "this"));
264 * @brief Iterator dereference.
265 * @pre iterator is dereferenceable
266 * @todo Make this correct w.r.t. iterators that return proxies
267 * @todo Use addressof() instead of & operator
272 _GLIBCXX_DEBUG_VERIFY(this->_M_dereferenceable(),
273 _M_message(__msg_bad_deref)
274 ._M_iterator(*this, "this"));
278 // ------ Input iterator requirements ------
280 * @brief Iterator preincrement
281 * @pre iterator is incrementable
286 _GLIBCXX_DEBUG_VERIFY(this->_M_incrementable(),
287 _M_message(__msg_bad_inc)
288 ._M_iterator(*this, "this"));
294 * @brief Iterator postincrement
295 * @pre iterator is incrementable
300 _GLIBCXX_DEBUG_VERIFY(this->_M_incrementable(),
301 _M_message(__msg_bad_inc)
302 ._M_iterator(*this, "this"));
303 _Safe_iterator __tmp(*this);
308 // ------ Bidirectional iterator requirements ------
310 * @brief Iterator predecrement
311 * @pre iterator is decrementable
316 _GLIBCXX_DEBUG_VERIFY(this->_M_decrementable(),
317 _M_message(__msg_bad_dec)
318 ._M_iterator(*this, "this"));
324 * @brief Iterator postdecrement
325 * @pre iterator is decrementable
330 _GLIBCXX_DEBUG_VERIFY(this->_M_decrementable(),
331 _M_message(__msg_bad_dec)
332 ._M_iterator(*this, "this"));
333 _Safe_iterator __tmp(*this);
338 // ------ Random access iterator requirements ------
340 operator[](const difference_type& __n) const
342 _GLIBCXX_DEBUG_VERIFY(this->_M_can_advance(__n)
343 && this->_M_can_advance(__n+1),
344 _M_message(__msg_iter_subscript_oob)
345 ._M_iterator(*this)._M_integer(__n));
347 return _M_current[__n];
351 operator+=(const difference_type& __n)
353 _GLIBCXX_DEBUG_VERIFY(this->_M_can_advance(__n),
354 _M_message(__msg_advance_oob)
355 ._M_iterator(*this)._M_integer(__n));
361 operator+(const difference_type& __n) const
363 _Safe_iterator __tmp(*this);
369 operator-=(const difference_type& __n)
371 _GLIBCXX_DEBUG_VERIFY(this->_M_can_advance(-__n),
372 _M_message(__msg_retreat_oob)
373 ._M_iterator(*this)._M_integer(__n));
379 operator-(const difference_type& __n) const
381 _Safe_iterator __tmp(*this);
386 // ------ Utilities ------
388 * @brief Return the underlying iterator
391 base() const { return _M_current; }
394 * @brief Conversion to underlying non-debug iterator to allow
395 * better interaction with non-debug containers.
397 operator _Iterator() const { return _M_current; }
399 /** Attach iterator to the given sequence. */
401 _M_attach(_Safe_sequence_base* __seq)
403 _Safe_iterator_base::_M_attach(__seq, _M_constant());
406 /** Likewise, but not thread-safe. */
408 _M_attach_single(_Safe_sequence_base* __seq)
410 _Safe_iterator_base::_M_attach_single(__seq, _M_constant());
413 /// Is the iterator dereferenceable?
415 _M_dereferenceable() const
416 { return !this->_M_singular() && !_M_is_end() && !_M_is_before_begin(); }
418 /// Is the iterator before a dereferenceable one?
420 _M_before_dereferenceable() const
422 if (this->_M_incrementable())
424 _Iterator __base = base();
425 return ++__base != _M_get_sequence()->_M_base().end();
430 /// Is the iterator incrementable?
432 _M_incrementable() const
433 { return !this->_M_singular() && !_M_is_end(); }
435 // Is the iterator decrementable?
437 _M_decrementable() const { return !_M_singular() && !_M_is_begin(); }
439 // Can we advance the iterator @p __n steps (@p __n may be negative)
441 _M_can_advance(const difference_type& __n) const;
443 // Is the iterator range [*this, __rhs) valid?
444 template<typename _Other>
446 _M_valid_range(const _Safe_iterator<_Other, _Sequence>& __rhs) const;
448 // The sequence this iterator references.
450 _M_get_sequence() const
451 { return static_cast<const _Sequence*>(_M_sequence); }
453 /// Is this iterator equal to the sequence's begin() iterator?
454 bool _M_is_begin() const
455 { return base() == _M_get_sequence()->_M_base().begin(); }
457 /// Is this iterator equal to the sequence's end() iterator?
458 bool _M_is_end() const
459 { return base() == _M_get_sequence()->_M_base().end(); }
461 /// Is this iterator equal to the sequence's before_begin() iterator if
463 bool _M_is_before_begin() const
465 return _BeforeBeginHelper<_Sequence>::_M_Is(base(), _M_get_sequence());
469 template<typename _IteratorL, typename _IteratorR, typename _Sequence>
471 operator==(const _Safe_iterator<_IteratorL, _Sequence>& __lhs,
472 const _Safe_iterator<_IteratorR, _Sequence>& __rhs)
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();
485 template<typename _Iterator, typename _Sequence>
487 operator==(const _Safe_iterator<_Iterator, _Sequence>& __lhs,
488 const _Safe_iterator<_Iterator, _Sequence>& __rhs)
490 _GLIBCXX_DEBUG_VERIFY(! __lhs._M_singular() && ! __rhs._M_singular(),
491 _M_message(__msg_iter_compare_bad)
492 ._M_iterator(__lhs, "lhs")
493 ._M_iterator(__rhs, "rhs"));
494 _GLIBCXX_DEBUG_VERIFY(__lhs._M_can_compare(__rhs),
495 _M_message(__msg_compare_different)
496 ._M_iterator(__lhs, "lhs")
497 ._M_iterator(__rhs, "rhs"));
498 return __lhs.base() == __rhs.base();
501 template<typename _IteratorL, typename _IteratorR, typename _Sequence>
503 operator!=(const _Safe_iterator<_IteratorL, _Sequence>& __lhs,
504 const _Safe_iterator<_IteratorR, _Sequence>& __rhs)
506 _GLIBCXX_DEBUG_VERIFY(! __lhs._M_singular() && ! __rhs._M_singular(),
507 _M_message(__msg_iter_compare_bad)
508 ._M_iterator(__lhs, "lhs")
509 ._M_iterator(__rhs, "rhs"));
510 _GLIBCXX_DEBUG_VERIFY(__lhs._M_can_compare(__rhs),
511 _M_message(__msg_compare_different)
512 ._M_iterator(__lhs, "lhs")
513 ._M_iterator(__rhs, "rhs"));
514 return __lhs.base() != __rhs.base();
517 template<typename _Iterator, typename _Sequence>
519 operator!=(const _Safe_iterator<_Iterator, _Sequence>& __lhs,
520 const _Safe_iterator<_Iterator, _Sequence>& __rhs)
522 _GLIBCXX_DEBUG_VERIFY(! __lhs._M_singular() && ! __rhs._M_singular(),
523 _M_message(__msg_iter_compare_bad)
524 ._M_iterator(__lhs, "lhs")
525 ._M_iterator(__rhs, "rhs"));
526 _GLIBCXX_DEBUG_VERIFY(__lhs._M_can_compare(__rhs),
527 _M_message(__msg_compare_different)
528 ._M_iterator(__lhs, "lhs")
529 ._M_iterator(__rhs, "rhs"));
530 return __lhs.base() != __rhs.base();
533 template<typename _IteratorL, typename _IteratorR, typename _Sequence>
535 operator<(const _Safe_iterator<_IteratorL, _Sequence>& __lhs,
536 const _Safe_iterator<_IteratorR, _Sequence>& __rhs)
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();
549 template<typename _Iterator, typename _Sequence>
551 operator<(const _Safe_iterator<_Iterator, _Sequence>& __lhs,
552 const _Safe_iterator<_Iterator, _Sequence>& __rhs)
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();
565 template<typename _IteratorL, typename _IteratorR, typename _Sequence>
567 operator<=(const _Safe_iterator<_IteratorL, _Sequence>& __lhs,
568 const _Safe_iterator<_IteratorR, _Sequence>& __rhs)
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();
581 template<typename _Iterator, typename _Sequence>
583 operator<=(const _Safe_iterator<_Iterator, _Sequence>& __lhs,
584 const _Safe_iterator<_Iterator, _Sequence>& __rhs)
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();
597 template<typename _IteratorL, typename _IteratorR, typename _Sequence>
599 operator>(const _Safe_iterator<_IteratorL, _Sequence>& __lhs,
600 const _Safe_iterator<_IteratorR, _Sequence>& __rhs)
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();
613 template<typename _Iterator, typename _Sequence>
615 operator>(const _Safe_iterator<_Iterator, _Sequence>& __lhs,
616 const _Safe_iterator<_Iterator, _Sequence>& __rhs)
618 _GLIBCXX_DEBUG_VERIFY(! __lhs._M_singular() && ! __rhs._M_singular(),
619 _M_message(__msg_iter_order_bad)
620 ._M_iterator(__lhs, "lhs")
621 ._M_iterator(__rhs, "rhs"));
622 _GLIBCXX_DEBUG_VERIFY(__lhs._M_can_compare(__rhs),
623 _M_message(__msg_order_different)
624 ._M_iterator(__lhs, "lhs")
625 ._M_iterator(__rhs, "rhs"));
626 return __lhs.base() > __rhs.base();
629 template<typename _IteratorL, typename _IteratorR, typename _Sequence>
631 operator>=(const _Safe_iterator<_IteratorL, _Sequence>& __lhs,
632 const _Safe_iterator<_IteratorR, _Sequence>& __rhs)
634 _GLIBCXX_DEBUG_VERIFY(! __lhs._M_singular() && ! __rhs._M_singular(),
635 _M_message(__msg_iter_order_bad)
636 ._M_iterator(__lhs, "lhs")
637 ._M_iterator(__rhs, "rhs"));
638 _GLIBCXX_DEBUG_VERIFY(__lhs._M_can_compare(__rhs),
639 _M_message(__msg_order_different)
640 ._M_iterator(__lhs, "lhs")
641 ._M_iterator(__rhs, "rhs"));
642 return __lhs.base() >= __rhs.base();
645 template<typename _Iterator, typename _Sequence>
647 operator>=(const _Safe_iterator<_Iterator, _Sequence>& __lhs,
648 const _Safe_iterator<_Iterator, _Sequence>& __rhs)
650 _GLIBCXX_DEBUG_VERIFY(! __lhs._M_singular() && ! __rhs._M_singular(),
651 _M_message(__msg_iter_order_bad)
652 ._M_iterator(__lhs, "lhs")
653 ._M_iterator(__rhs, "rhs"));
654 _GLIBCXX_DEBUG_VERIFY(__lhs._M_can_compare(__rhs),
655 _M_message(__msg_order_different)
656 ._M_iterator(__lhs, "lhs")
657 ._M_iterator(__rhs, "rhs"));
658 return __lhs.base() >= __rhs.base();
661 // _GLIBCXX_RESOLVE_LIB_DEFECTS
662 // According to the resolution of DR179 not only the various comparison
663 // operators but also operator- must accept mixed iterator/const_iterator
665 template<typename _IteratorL, typename _IteratorR, typename _Sequence>
666 inline typename _Safe_iterator<_IteratorL, _Sequence>::difference_type
667 operator-(const _Safe_iterator<_IteratorL, _Sequence>& __lhs,
668 const _Safe_iterator<_IteratorR, _Sequence>& __rhs)
670 _GLIBCXX_DEBUG_VERIFY(! __lhs._M_singular() && ! __rhs._M_singular(),
671 _M_message(__msg_distance_bad)
672 ._M_iterator(__lhs, "lhs")
673 ._M_iterator(__rhs, "rhs"));
674 _GLIBCXX_DEBUG_VERIFY(__lhs._M_can_compare(__rhs),
675 _M_message(__msg_distance_different)
676 ._M_iterator(__lhs, "lhs")
677 ._M_iterator(__rhs, "rhs"));
678 return __lhs.base() - __rhs.base();
681 template<typename _Iterator, typename _Sequence>
682 inline typename _Safe_iterator<_Iterator, _Sequence>::difference_type
683 operator-(const _Safe_iterator<_Iterator, _Sequence>& __lhs,
684 const _Safe_iterator<_Iterator, _Sequence>& __rhs)
686 _GLIBCXX_DEBUG_VERIFY(! __lhs._M_singular() && ! __rhs._M_singular(),
687 _M_message(__msg_distance_bad)
688 ._M_iterator(__lhs, "lhs")
689 ._M_iterator(__rhs, "rhs"));
690 _GLIBCXX_DEBUG_VERIFY(__lhs._M_can_compare(__rhs),
691 _M_message(__msg_distance_different)
692 ._M_iterator(__lhs, "lhs")
693 ._M_iterator(__rhs, "rhs"));
694 return __lhs.base() - __rhs.base();
697 template<typename _Iterator, typename _Sequence>
698 inline _Safe_iterator<_Iterator, _Sequence>
699 operator+(typename _Safe_iterator<_Iterator,_Sequence>::difference_type __n,
700 const _Safe_iterator<_Iterator, _Sequence>& __i)
701 { return __i + __n; }
703 // Helper struct to detect random access safe iterators.
704 template<typename _Iterator>
705 struct __is_safe_random_iterator
707 enum { __value = 0 };
708 typedef std::__false_type __type;
711 template<typename _Iterator, typename _Sequence>
712 struct __is_safe_random_iterator<_Safe_iterator<_Iterator, _Sequence> >
713 : std::__are_same<std::random_access_iterator_tag,
714 typename std::iterator_traits<_Iterator>::
718 template<typename _Iterator>
720 : std::_Iter_base<_Iterator, __is_safe_random_iterator<_Iterator>::__value>
723 /** Helper function to extract base iterator of random access safe iterator
724 in order to reduce performance impact of debug mode. Limited to random
725 access iterator because it is the only category for which it is possible
726 to check for correct iterators order in the __valid_range function
727 thanks to the < operator.
729 template<typename _Iterator>
730 inline typename _Siter_base<_Iterator>::iterator_type
731 __base(_Iterator __it)
732 { return _Siter_base<_Iterator>::_S_base(__it); }
733 } // namespace __gnu_debug
735 #include <debug/safe_iterator.tcc>