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 /** 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"));
173 * @brief Converting constructor from a mutable iterator to a
176 template<typename _MutableIterator>
178 const _Safe_iterator<_MutableIterator,
179 typename __gnu_cxx::__enable_if<(std::__are_same<_MutableIterator,
180 typename _Sequence::iterator::iterator_type>::__value),
181 _Sequence>::__type>& __x)
182 : _Safe_iterator_base(__x, _M_constant()), _M_current(__x.base())
184 // _GLIBCXX_RESOLVE_LIB_DEFECTS
185 // DR 408. Is vector<reverse_iterator<char*> > forbidden?
186 _GLIBCXX_DEBUG_VERIFY(!__x._M_singular()
187 || __x.base() == _Iterator(),
188 _M_message(__msg_init_const_singular)
189 ._M_iterator(*this, "this")
190 ._M_iterator(__x, "other"));
194 * @brief Copy assignment.
197 operator=(const _Safe_iterator& __x)
199 // _GLIBCXX_RESOLVE_LIB_DEFECTS
200 // DR 408. Is vector<reverse_iterator<char*> > forbidden?
201 _GLIBCXX_DEBUG_VERIFY(!__x._M_singular()
202 || __x._M_current == _Iterator(),
203 _M_message(__msg_copy_singular)
204 ._M_iterator(*this, "this")
205 ._M_iterator(__x, "other"));
206 _M_current = __x._M_current;
207 this->_M_attach(__x._M_sequence);
212 * @brief Iterator dereference.
213 * @pre iterator is dereferenceable
218 _GLIBCXX_DEBUG_VERIFY(this->_M_dereferenceable(),
219 _M_message(__msg_bad_deref)
220 ._M_iterator(*this, "this"));
225 * @brief Iterator dereference.
226 * @pre iterator is dereferenceable
227 * @todo Make this correct w.r.t. iterators that return proxies
228 * @todo Use addressof() instead of & operator
233 _GLIBCXX_DEBUG_VERIFY(this->_M_dereferenceable(),
234 _M_message(__msg_bad_deref)
235 ._M_iterator(*this, "this"));
239 // ------ Input iterator requirements ------
241 * @brief Iterator preincrement
242 * @pre iterator is incrementable
247 _GLIBCXX_DEBUG_VERIFY(this->_M_incrementable(),
248 _M_message(__msg_bad_inc)
249 ._M_iterator(*this, "this"));
255 * @brief Iterator postincrement
256 * @pre iterator is incrementable
261 _GLIBCXX_DEBUG_VERIFY(this->_M_incrementable(),
262 _M_message(__msg_bad_inc)
263 ._M_iterator(*this, "this"));
264 _Safe_iterator __tmp(*this);
269 // ------ Bidirectional iterator requirements ------
271 * @brief Iterator predecrement
272 * @pre iterator is decrementable
277 _GLIBCXX_DEBUG_VERIFY(this->_M_decrementable(),
278 _M_message(__msg_bad_dec)
279 ._M_iterator(*this, "this"));
285 * @brief Iterator postdecrement
286 * @pre iterator is decrementable
291 _GLIBCXX_DEBUG_VERIFY(this->_M_decrementable(),
292 _M_message(__msg_bad_dec)
293 ._M_iterator(*this, "this"));
294 _Safe_iterator __tmp(*this);
299 // ------ Random access iterator requirements ------
301 operator[](const difference_type& __n) const
303 _GLIBCXX_DEBUG_VERIFY(this->_M_can_advance(__n)
304 && this->_M_can_advance(__n+1),
305 _M_message(__msg_iter_subscript_oob)
306 ._M_iterator(*this)._M_integer(__n));
308 return _M_current[__n];
312 operator+=(const difference_type& __n)
314 _GLIBCXX_DEBUG_VERIFY(this->_M_can_advance(__n),
315 _M_message(__msg_advance_oob)
316 ._M_iterator(*this)._M_integer(__n));
322 operator+(const difference_type& __n) const
324 _Safe_iterator __tmp(*this);
330 operator-=(const difference_type& __n)
332 _GLIBCXX_DEBUG_VERIFY(this->_M_can_advance(-__n),
333 _M_message(__msg_retreat_oob)
334 ._M_iterator(*this)._M_integer(__n));
340 operator-(const difference_type& __n) const
342 _Safe_iterator __tmp(*this);
347 // ------ Utilities ------
349 * @brief Return the underlying iterator
352 base() const { return _M_current; }
355 * @brief Conversion to underlying non-debug iterator to allow
356 * better interaction with non-debug containers.
358 operator _Iterator() const { return _M_current; }
360 /** Attach iterator to the given sequence. */
362 _M_attach(_Safe_sequence_base* __seq)
364 _Safe_iterator_base::_M_attach(__seq, _M_constant());
367 /** Likewise, but not thread-safe. */
369 _M_attach_single(_Safe_sequence_base* __seq)
371 _Safe_iterator_base::_M_attach_single(__seq, _M_constant());
374 /// Is the iterator dereferenceable?
376 _M_dereferenceable() const
377 { return !this->_M_singular() && !_M_is_end() && !_M_is_before_begin(); }
379 /// Is the iterator before a dereferenceable one?
381 _M_before_dereferenceable() const
383 if (this->_M_incrementable())
385 _Iterator __base = base();
386 return ++__base != _M_get_sequence()->_M_base().end();
391 /// Is the iterator incrementable?
393 _M_incrementable() const
394 { return !this->_M_singular() && !_M_is_end(); }
396 // Is the iterator decrementable?
398 _M_decrementable() const { return !_M_singular() && !_M_is_begin(); }
400 // Can we advance the iterator @p __n steps (@p __n may be negative)
402 _M_can_advance(const difference_type& __n) const;
404 // Is the iterator range [*this, __rhs) valid?
405 template<typename _Other>
407 _M_valid_range(const _Safe_iterator<_Other, _Sequence>& __rhs) const;
409 // The sequence this iterator references.
411 _M_get_sequence() const
412 { return static_cast<const _Sequence*>(_M_sequence); }
414 /// Is this iterator equal to the sequence's begin() iterator?
415 bool _M_is_begin() const
416 { return base() == _M_get_sequence()->_M_base().begin(); }
418 /// Is this iterator equal to the sequence's end() iterator?
419 bool _M_is_end() const
420 { return base() == _M_get_sequence()->_M_base().end(); }
422 /// Is this iterator equal to the sequence's before_begin() iterator if
424 bool _M_is_before_begin() const
425 { return _BeforeBeginHelper<_Sequence>::_M_Is(base(), _M_get_sequence()); }
428 template<typename _IteratorL, typename _IteratorR, typename _Sequence>
430 operator==(const _Safe_iterator<_IteratorL, _Sequence>& __lhs,
431 const _Safe_iterator<_IteratorR, _Sequence>& __rhs)
433 _GLIBCXX_DEBUG_VERIFY(! __lhs._M_singular() && ! __rhs._M_singular(),
434 _M_message(__msg_iter_compare_bad)
435 ._M_iterator(__lhs, "lhs")
436 ._M_iterator(__rhs, "rhs"));
437 _GLIBCXX_DEBUG_VERIFY(__lhs._M_can_compare(__rhs),
438 _M_message(__msg_compare_different)
439 ._M_iterator(__lhs, "lhs")
440 ._M_iterator(__rhs, "rhs"));
441 return __lhs.base() == __rhs.base();
444 template<typename _Iterator, typename _Sequence>
446 operator==(const _Safe_iterator<_Iterator, _Sequence>& __lhs,
447 const _Safe_iterator<_Iterator, _Sequence>& __rhs)
449 _GLIBCXX_DEBUG_VERIFY(! __lhs._M_singular() && ! __rhs._M_singular(),
450 _M_message(__msg_iter_compare_bad)
451 ._M_iterator(__lhs, "lhs")
452 ._M_iterator(__rhs, "rhs"));
453 _GLIBCXX_DEBUG_VERIFY(__lhs._M_can_compare(__rhs),
454 _M_message(__msg_compare_different)
455 ._M_iterator(__lhs, "lhs")
456 ._M_iterator(__rhs, "rhs"));
457 return __lhs.base() == __rhs.base();
460 template<typename _IteratorL, typename _IteratorR, typename _Sequence>
462 operator!=(const _Safe_iterator<_IteratorL, _Sequence>& __lhs,
463 const _Safe_iterator<_IteratorR, _Sequence>& __rhs)
465 _GLIBCXX_DEBUG_VERIFY(! __lhs._M_singular() && ! __rhs._M_singular(),
466 _M_message(__msg_iter_compare_bad)
467 ._M_iterator(__lhs, "lhs")
468 ._M_iterator(__rhs, "rhs"));
469 _GLIBCXX_DEBUG_VERIFY(__lhs._M_can_compare(__rhs),
470 _M_message(__msg_compare_different)
471 ._M_iterator(__lhs, "lhs")
472 ._M_iterator(__rhs, "rhs"));
473 return __lhs.base() != __rhs.base();
476 template<typename _Iterator, typename _Sequence>
478 operator!=(const _Safe_iterator<_Iterator, _Sequence>& __lhs,
479 const _Safe_iterator<_Iterator, _Sequence>& __rhs)
481 _GLIBCXX_DEBUG_VERIFY(! __lhs._M_singular() && ! __rhs._M_singular(),
482 _M_message(__msg_iter_compare_bad)
483 ._M_iterator(__lhs, "lhs")
484 ._M_iterator(__rhs, "rhs"));
485 _GLIBCXX_DEBUG_VERIFY(__lhs._M_can_compare(__rhs),
486 _M_message(__msg_compare_different)
487 ._M_iterator(__lhs, "lhs")
488 ._M_iterator(__rhs, "rhs"));
489 return __lhs.base() != __rhs.base();
492 template<typename _IteratorL, typename _IteratorR, typename _Sequence>
494 operator<(const _Safe_iterator<_IteratorL, _Sequence>& __lhs,
495 const _Safe_iterator<_IteratorR, _Sequence>& __rhs)
497 _GLIBCXX_DEBUG_VERIFY(! __lhs._M_singular() && ! __rhs._M_singular(),
498 _M_message(__msg_iter_order_bad)
499 ._M_iterator(__lhs, "lhs")
500 ._M_iterator(__rhs, "rhs"));
501 _GLIBCXX_DEBUG_VERIFY(__lhs._M_can_compare(__rhs),
502 _M_message(__msg_order_different)
503 ._M_iterator(__lhs, "lhs")
504 ._M_iterator(__rhs, "rhs"));
505 return __lhs.base() < __rhs.base();
508 template<typename _Iterator, typename _Sequence>
510 operator<(const _Safe_iterator<_Iterator, _Sequence>& __lhs,
511 const _Safe_iterator<_Iterator, _Sequence>& __rhs)
513 _GLIBCXX_DEBUG_VERIFY(! __lhs._M_singular() && ! __rhs._M_singular(),
514 _M_message(__msg_iter_order_bad)
515 ._M_iterator(__lhs, "lhs")
516 ._M_iterator(__rhs, "rhs"));
517 _GLIBCXX_DEBUG_VERIFY(__lhs._M_can_compare(__rhs),
518 _M_message(__msg_order_different)
519 ._M_iterator(__lhs, "lhs")
520 ._M_iterator(__rhs, "rhs"));
521 return __lhs.base() < __rhs.base();
524 template<typename _IteratorL, typename _IteratorR, typename _Sequence>
526 operator<=(const _Safe_iterator<_IteratorL, _Sequence>& __lhs,
527 const _Safe_iterator<_IteratorR, _Sequence>& __rhs)
529 _GLIBCXX_DEBUG_VERIFY(! __lhs._M_singular() && ! __rhs._M_singular(),
530 _M_message(__msg_iter_order_bad)
531 ._M_iterator(__lhs, "lhs")
532 ._M_iterator(__rhs, "rhs"));
533 _GLIBCXX_DEBUG_VERIFY(__lhs._M_can_compare(__rhs),
534 _M_message(__msg_order_different)
535 ._M_iterator(__lhs, "lhs")
536 ._M_iterator(__rhs, "rhs"));
537 return __lhs.base() <= __rhs.base();
540 template<typename _Iterator, typename _Sequence>
542 operator<=(const _Safe_iterator<_Iterator, _Sequence>& __lhs,
543 const _Safe_iterator<_Iterator, _Sequence>& __rhs)
545 _GLIBCXX_DEBUG_VERIFY(! __lhs._M_singular() && ! __rhs._M_singular(),
546 _M_message(__msg_iter_order_bad)
547 ._M_iterator(__lhs, "lhs")
548 ._M_iterator(__rhs, "rhs"));
549 _GLIBCXX_DEBUG_VERIFY(__lhs._M_can_compare(__rhs),
550 _M_message(__msg_order_different)
551 ._M_iterator(__lhs, "lhs")
552 ._M_iterator(__rhs, "rhs"));
553 return __lhs.base() <= __rhs.base();
556 template<typename _IteratorL, typename _IteratorR, typename _Sequence>
558 operator>(const _Safe_iterator<_IteratorL, _Sequence>& __lhs,
559 const _Safe_iterator<_IteratorR, _Sequence>& __rhs)
561 _GLIBCXX_DEBUG_VERIFY(! __lhs._M_singular() && ! __rhs._M_singular(),
562 _M_message(__msg_iter_order_bad)
563 ._M_iterator(__lhs, "lhs")
564 ._M_iterator(__rhs, "rhs"));
565 _GLIBCXX_DEBUG_VERIFY(__lhs._M_can_compare(__rhs),
566 _M_message(__msg_order_different)
567 ._M_iterator(__lhs, "lhs")
568 ._M_iterator(__rhs, "rhs"));
569 return __lhs.base() > __rhs.base();
572 template<typename _Iterator, typename _Sequence>
574 operator>(const _Safe_iterator<_Iterator, _Sequence>& __lhs,
575 const _Safe_iterator<_Iterator, _Sequence>& __rhs)
577 _GLIBCXX_DEBUG_VERIFY(! __lhs._M_singular() && ! __rhs._M_singular(),
578 _M_message(__msg_iter_order_bad)
579 ._M_iterator(__lhs, "lhs")
580 ._M_iterator(__rhs, "rhs"));
581 _GLIBCXX_DEBUG_VERIFY(__lhs._M_can_compare(__rhs),
582 _M_message(__msg_order_different)
583 ._M_iterator(__lhs, "lhs")
584 ._M_iterator(__rhs, "rhs"));
585 return __lhs.base() > __rhs.base();
588 template<typename _IteratorL, typename _IteratorR, typename _Sequence>
590 operator>=(const _Safe_iterator<_IteratorL, _Sequence>& __lhs,
591 const _Safe_iterator<_IteratorR, _Sequence>& __rhs)
593 _GLIBCXX_DEBUG_VERIFY(! __lhs._M_singular() && ! __rhs._M_singular(),
594 _M_message(__msg_iter_order_bad)
595 ._M_iterator(__lhs, "lhs")
596 ._M_iterator(__rhs, "rhs"));
597 _GLIBCXX_DEBUG_VERIFY(__lhs._M_can_compare(__rhs),
598 _M_message(__msg_order_different)
599 ._M_iterator(__lhs, "lhs")
600 ._M_iterator(__rhs, "rhs"));
601 return __lhs.base() >= __rhs.base();
604 template<typename _Iterator, typename _Sequence>
606 operator>=(const _Safe_iterator<_Iterator, _Sequence>& __lhs,
607 const _Safe_iterator<_Iterator, _Sequence>& __rhs)
609 _GLIBCXX_DEBUG_VERIFY(! __lhs._M_singular() && ! __rhs._M_singular(),
610 _M_message(__msg_iter_order_bad)
611 ._M_iterator(__lhs, "lhs")
612 ._M_iterator(__rhs, "rhs"));
613 _GLIBCXX_DEBUG_VERIFY(__lhs._M_can_compare(__rhs),
614 _M_message(__msg_order_different)
615 ._M_iterator(__lhs, "lhs")
616 ._M_iterator(__rhs, "rhs"));
617 return __lhs.base() >= __rhs.base();
620 // _GLIBCXX_RESOLVE_LIB_DEFECTS
621 // According to the resolution of DR179 not only the various comparison
622 // operators but also operator- must accept mixed iterator/const_iterator
624 template<typename _IteratorL, typename _IteratorR, typename _Sequence>
625 inline typename _Safe_iterator<_IteratorL, _Sequence>::difference_type
626 operator-(const _Safe_iterator<_IteratorL, _Sequence>& __lhs,
627 const _Safe_iterator<_IteratorR, _Sequence>& __rhs)
629 _GLIBCXX_DEBUG_VERIFY(! __lhs._M_singular() && ! __rhs._M_singular(),
630 _M_message(__msg_distance_bad)
631 ._M_iterator(__lhs, "lhs")
632 ._M_iterator(__rhs, "rhs"));
633 _GLIBCXX_DEBUG_VERIFY(__lhs._M_can_compare(__rhs),
634 _M_message(__msg_distance_different)
635 ._M_iterator(__lhs, "lhs")
636 ._M_iterator(__rhs, "rhs"));
637 return __lhs.base() - __rhs.base();
640 template<typename _Iterator, typename _Sequence>
641 inline typename _Safe_iterator<_Iterator, _Sequence>::difference_type
642 operator-(const _Safe_iterator<_Iterator, _Sequence>& __lhs,
643 const _Safe_iterator<_Iterator, _Sequence>& __rhs)
645 _GLIBCXX_DEBUG_VERIFY(! __lhs._M_singular() && ! __rhs._M_singular(),
646 _M_message(__msg_distance_bad)
647 ._M_iterator(__lhs, "lhs")
648 ._M_iterator(__rhs, "rhs"));
649 _GLIBCXX_DEBUG_VERIFY(__lhs._M_can_compare(__rhs),
650 _M_message(__msg_distance_different)
651 ._M_iterator(__lhs, "lhs")
652 ._M_iterator(__rhs, "rhs"));
653 return __lhs.base() - __rhs.base();
656 template<typename _Iterator, typename _Sequence>
657 inline _Safe_iterator<_Iterator, _Sequence>
658 operator+(typename _Safe_iterator<_Iterator,_Sequence>::difference_type __n,
659 const _Safe_iterator<_Iterator, _Sequence>& __i)
660 { return __i + __n; }
662 // Helper struct to detect random access safe iterators.
663 template<typename _Iterator>
664 struct __is_safe_random_iterator
666 enum { __value = 0 };
667 typedef std::__false_type __type;
670 template<typename _Iterator, typename _Sequence>
671 struct __is_safe_random_iterator<_Safe_iterator<_Iterator, _Sequence> >
672 : std::__are_same<std::random_access_iterator_tag,
673 typename std::iterator_traits<_Iterator>::
677 template<typename _Iterator>
679 : std::_Iter_base<_Iterator, __is_safe_random_iterator<_Iterator>::__value>
682 /** Helper function to extract base iterator of random access safe iterator
683 in order to reduce performance impact of debug mode. Limited to random
684 access iterator because it is the only category for which it is possible
685 to check for correct iterators order in the __valid_range function
686 thanks to the < operator.
688 template<typename _Iterator>
689 inline typename _Siter_base<_Iterator>::iterator_type
690 __base(_Iterator __it)
691 { return _Siter_base<_Iterator>::_S_base(__it); }
692 } // namespace __gnu_debug
694 #include <debug/safe_iterator.tcc>