1 // Safe iterator implementation -*- C++ -*-
3 // Copyright (C) 2003, 2004, 2005, 2006, 2009, 2010, 2011
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 /** \brief Safe iterator wrapper.
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.
76 template<typename _Iterator
, typename _Sequence
>
77 class _Safe_iterator
: public _Safe_iterator_base
79 typedef _Safe_iterator _Self
;
81 /** The precision to which we can calculate the distance between
84 enum _Distance_precision
86 __dp_equality
, //< Can compare iterator equality, only
87 __dp_sign
, //< Can determine equality and ordering
88 __dp_exact
//< Can determine distance precisely
91 /// The underlying iterator
94 /// Determine if this is a constant iterator.
98 typedef typename
_Sequence::const_iterator const_iterator
;
99 return std::__are_same
<const_iterator
, _Safe_iterator
>::__value
;
102 typedef std::iterator_traits
<_Iterator
> _Traits
;
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
;
112 /// @post the iterator is singular and unattached
113 _Safe_iterator() : _M_current() { }
116 * @brief Safe iterator construction from an unsafe iterator and
119 * @pre @p seq is not NULL
120 * @post this is not singular
122 _Safe_iterator(const _Iterator
& __i
, const _Sequence
* __seq
)
123 : _Safe_iterator_base(__seq
, _M_constant()), _M_current(__i
)
125 _GLIBCXX_DEBUG_VERIFY(! this->_M_singular(),
126 _M_message(__msg_init_singular
)
127 ._M_iterator(*this, "this"));
131 * @brief Copy construction.
133 _Safe_iterator(const _Safe_iterator
& __x
)
134 : _Safe_iterator_base(__x
, _M_constant()), _M_current(__x
._M_current
)
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"));
146 * @brief Converting constructor from a mutable iterator to a
149 template<typename _MutableIterator
>
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())
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"));
167 * @brief Copy assignment.
170 operator=(const _Safe_iterator
& __x
)
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
);
185 * @brief Iterator dereference.
186 * @pre iterator is dereferenceable
191 _GLIBCXX_DEBUG_VERIFY(this->_M_dereferenceable(),
192 _M_message(__msg_bad_deref
)
193 ._M_iterator(*this, "this"));
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
206 _GLIBCXX_DEBUG_VERIFY(this->_M_dereferenceable(),
207 _M_message(__msg_bad_deref
)
208 ._M_iterator(*this, "this"));
212 // ------ Input iterator requirements ------
214 * @brief Iterator preincrement
215 * @pre iterator is incrementable
220 _GLIBCXX_DEBUG_VERIFY(this->_M_incrementable(),
221 _M_message(__msg_bad_inc
)
222 ._M_iterator(*this, "this"));
228 * @brief Iterator postincrement
229 * @pre iterator is incrementable
234 _GLIBCXX_DEBUG_VERIFY(this->_M_incrementable(),
235 _M_message(__msg_bad_inc
)
236 ._M_iterator(*this, "this"));
237 _Safe_iterator
__tmp(*this);
242 // ------ Bidirectional iterator requirements ------
244 * @brief Iterator predecrement
245 * @pre iterator is decrementable
250 _GLIBCXX_DEBUG_VERIFY(this->_M_decrementable(),
251 _M_message(__msg_bad_dec
)
252 ._M_iterator(*this, "this"));
258 * @brief Iterator postdecrement
259 * @pre iterator is decrementable
264 _GLIBCXX_DEBUG_VERIFY(this->_M_decrementable(),
265 _M_message(__msg_bad_dec
)
266 ._M_iterator(*this, "this"));
267 _Safe_iterator
__tmp(*this);
272 // ------ Random access iterator requirements ------
274 operator[](const difference_type
& __n
) const
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
));
281 return _M_current
[__n
];
285 operator+=(const difference_type
& __n
)
287 _GLIBCXX_DEBUG_VERIFY(this->_M_can_advance(__n
),
288 _M_message(__msg_advance_oob
)
289 ._M_iterator(*this)._M_integer(__n
));
295 operator+(const difference_type
& __n
) const
297 _Safe_iterator
__tmp(*this);
303 operator-=(const difference_type
& __n
)
305 _GLIBCXX_DEBUG_VERIFY(this->_M_can_advance(-__n
),
306 _M_message(__msg_retreat_oob
)
307 ._M_iterator(*this)._M_integer(__n
));
313 operator-(const difference_type
& __n
) const
315 _Safe_iterator
__tmp(*this);
320 // ------ Utilities ------
322 * @brief Return the underlying iterator
325 base() const { return _M_current
; }
328 * @brief Conversion to underlying non-debug iterator to allow
329 * better interaction with non-debug containers.
331 operator _Iterator() const { return _M_current
; }
333 /** Attach iterator to the given sequence. */
335 _M_attach(_Safe_sequence_base
* __seq
)
337 _Safe_iterator_base::_M_attach(__seq
, _M_constant());
340 /** Likewise, but not thread-safe. */
342 _M_attach_single(_Safe_sequence_base
* __seq
)
344 _Safe_iterator_base::_M_attach_single(__seq
, _M_constant());
347 /// Is the iterator dereferenceable?
349 _M_dereferenceable() const
350 { return !this->_M_singular() && !_M_is_end() && !_M_is_before_begin(); }
352 /// Is the iterator before a dereferenceable one?
354 _M_before_dereferenceable() const
357 return __it
._M_incrementable() && (++__it
)._M_dereferenceable();
360 /// Is the iterator incrementable?
362 _M_incrementable() const
363 { return !this->_M_singular() && !_M_is_end(); }
365 // Is the iterator decrementable?
367 _M_decrementable() const { return !_M_singular() && !_M_is_begin(); }
369 // Can we advance the iterator @p __n steps (@p __n may be negative)
371 _M_can_advance(const difference_type
& __n
) const;
373 // Is the iterator range [*this, __rhs) valid?
374 template<typename _Other
>
376 _M_valid_range(const _Safe_iterator
<_Other
, _Sequence
>& __rhs
) const;
378 // The sequence this iterator references.
380 _M_get_sequence() const
381 { return static_cast<const _Sequence
*>(_M_sequence
); }
383 /** Determine the distance between two iterators with some known
386 template<typename _Iterator1
, typename _Iterator2
>
387 static std::pair
<difference_type
, _Distance_precision
>
388 _M_get_distance(const _Iterator1
& __lhs
, const _Iterator2
& __rhs
)
390 typedef typename
std::iterator_traits
<_Iterator1
>::iterator_category
392 return _M_get_distance(__lhs
, __rhs
, _Category());
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
); }
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
); }
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(); }
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(); }
415 /// Is this iterator equal to the sequence's before_begin() iterator if
417 bool _M_is_before_begin() const
418 { return _BeforeBeginHelper
<_Sequence
>::_M_Is(base(), _M_get_sequence()); }
421 template<typename _IteratorL
, typename _IteratorR
, typename _Sequence
>
423 operator==(const _Safe_iterator
<_IteratorL
, _Sequence
>& __lhs
,
424 const _Safe_iterator
<_IteratorR
, _Sequence
>& __rhs
)
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();
437 template<typename _Iterator
, typename _Sequence
>
439 operator==(const _Safe_iterator
<_Iterator
, _Sequence
>& __lhs
,
440 const _Safe_iterator
<_Iterator
, _Sequence
>& __rhs
)
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();
453 template<typename _IteratorL
, typename _IteratorR
, typename _Sequence
>
455 operator!=(const _Safe_iterator
<_IteratorL
, _Sequence
>& __lhs
,
456 const _Safe_iterator
<_IteratorR
, _Sequence
>& __rhs
)
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();
469 template<typename _Iterator
, typename _Sequence
>
471 operator!=(const _Safe_iterator
<_Iterator
, _Sequence
>& __lhs
,
472 const _Safe_iterator
<_Iterator
, _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 _IteratorL
, typename _IteratorR
, typename _Sequence
>
487 operator<(const _Safe_iterator
<_IteratorL
, _Sequence
>& __lhs
,
488 const _Safe_iterator
<_IteratorR
, _Sequence
>& __rhs
)
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();
501 template<typename _Iterator
, typename _Sequence
>
503 operator<(const _Safe_iterator
<_Iterator
, _Sequence
>& __lhs
,
504 const _Safe_iterator
<_Iterator
, _Sequence
>& __rhs
)
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();
517 template<typename _IteratorL
, typename _IteratorR
, typename _Sequence
>
519 operator<=(const _Safe_iterator
<_IteratorL
, _Sequence
>& __lhs
,
520 const _Safe_iterator
<_IteratorR
, _Sequence
>& __rhs
)
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();
533 template<typename _Iterator
, typename _Sequence
>
535 operator<=(const _Safe_iterator
<_Iterator
, _Sequence
>& __lhs
,
536 const _Safe_iterator
<_Iterator
, _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 _IteratorL
, typename _IteratorR
, typename _Sequence
>
551 operator>(const _Safe_iterator
<_IteratorL
, _Sequence
>& __lhs
,
552 const _Safe_iterator
<_IteratorR
, _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 _Iterator
, typename _Sequence
>
567 operator>(const _Safe_iterator
<_Iterator
, _Sequence
>& __lhs
,
568 const _Safe_iterator
<_Iterator
, _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 _IteratorL
, typename _IteratorR
, typename _Sequence
>
583 operator>=(const _Safe_iterator
<_IteratorL
, _Sequence
>& __lhs
,
584 const _Safe_iterator
<_IteratorR
, _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 _Iterator
, typename _Sequence
>
599 operator>=(const _Safe_iterator
<_Iterator
, _Sequence
>& __lhs
,
600 const _Safe_iterator
<_Iterator
, _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 // _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
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
)
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();
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
)
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();
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
; }
655 // Helper struct to detect random access safe iterators.
656 template<typename _Iterator
>
657 struct __is_safe_random_iterator
659 enum { __value
= 0 };
660 typedef std::__false_type __type
;
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
>::
670 template<typename _Iterator
>
672 : std::_Iter_base
<_Iterator
, __is_safe_random_iterator
<_Iterator
>::__value
>
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.
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
687 #include <debug/safe_iterator.tcc>