2012-01-05 Paul Thomas <pault@gcc.gnu.org>
[official-gcc.git] / libstdc++-v3 / include / debug / safe_iterator.h
blob016ec7b9418ca52f1cecaf7ca8a3594b21edd20e
1 // Safe iterator implementation -*- C++ -*-
3 // Copyright (C) 2003, 2004, 2005, 2006, 2009, 2010, 2011
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.
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>
41 namespace __gnu_debug
43 /** Helper struct to deal with sequence offering a before_begin
44 * iterator.
45 **/
46 template <typename _Sequence>
47 struct _BeforeBeginHelper
49 typedef typename _Sequence::const_iterator _It;
50 typedef typename _It::iterator_type _BaseIt;
52 static bool
53 _M_Is(_BaseIt __it, const _Sequence* __seq)
54 { return false; }
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.
61 inline bool
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
66 * two iterators.
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
76 * precision.
78 template<typename _Iterator1, typename _Iterator2>
79 inline std::pair<typename std::iterator_traits<_Iterator1>::difference_type,
80 _Distance_precision>
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,
87 _Distance_precision>
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,
94 _Distance_precision>
95 __get_distance(const _Iterator1& __lhs, const _Iterator2& __rhs)
97 typedef typename std::iterator_traits<_Iterator1>::iterator_category
98 _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.
122 bool
123 _M_constant() const
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;
131 public:
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
144 * its sequence.
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
174 * constant iterator.
176 template<typename _MutableIterator>
177 _Safe_iterator(
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.
196 _Safe_iterator&
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);
208 return *this;
212 * @brief Iterator dereference.
213 * @pre iterator is dereferenceable
215 reference
216 operator*() const
218 _GLIBCXX_DEBUG_VERIFY(this->_M_dereferenceable(),
219 _M_message(__msg_bad_deref)
220 ._M_iterator(*this, "this"));
221 return *_M_current;
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
230 pointer
231 operator->() const
233 _GLIBCXX_DEBUG_VERIFY(this->_M_dereferenceable(),
234 _M_message(__msg_bad_deref)
235 ._M_iterator(*this, "this"));
236 return &*_M_current;
239 // ------ Input iterator requirements ------
241 * @brief Iterator preincrement
242 * @pre iterator is incrementable
244 _Safe_iterator&
245 operator++()
247 _GLIBCXX_DEBUG_VERIFY(this->_M_incrementable(),
248 _M_message(__msg_bad_inc)
249 ._M_iterator(*this, "this"));
250 ++_M_current;
251 return *this;
255 * @brief Iterator postincrement
256 * @pre iterator is incrementable
258 _Safe_iterator
259 operator++(int)
261 _GLIBCXX_DEBUG_VERIFY(this->_M_incrementable(),
262 _M_message(__msg_bad_inc)
263 ._M_iterator(*this, "this"));
264 _Safe_iterator __tmp(*this);
265 ++_M_current;
266 return __tmp;
269 // ------ Bidirectional iterator requirements ------
271 * @brief Iterator predecrement
272 * @pre iterator is decrementable
274 _Safe_iterator&
275 operator--()
277 _GLIBCXX_DEBUG_VERIFY(this->_M_decrementable(),
278 _M_message(__msg_bad_dec)
279 ._M_iterator(*this, "this"));
280 --_M_current;
281 return *this;
285 * @brief Iterator postdecrement
286 * @pre iterator is decrementable
288 _Safe_iterator
289 operator--(int)
291 _GLIBCXX_DEBUG_VERIFY(this->_M_decrementable(),
292 _M_message(__msg_bad_dec)
293 ._M_iterator(*this, "this"));
294 _Safe_iterator __tmp(*this);
295 --_M_current;
296 return __tmp;
299 // ------ Random access iterator requirements ------
300 reference
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];
311 _Safe_iterator&
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));
317 _M_current += __n;
318 return *this;
321 _Safe_iterator
322 operator+(const difference_type& __n) const
324 _Safe_iterator __tmp(*this);
325 __tmp += __n;
326 return __tmp;
329 _Safe_iterator&
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));
335 _M_current += -__n;
336 return *this;
339 _Safe_iterator
340 operator-(const difference_type& __n) const
342 _Safe_iterator __tmp(*this);
343 __tmp -= __n;
344 return __tmp;
347 // ------ Utilities ------
349 * @brief Return the underlying iterator
351 _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. */
361 void
362 _M_attach(_Safe_sequence_base* __seq)
364 _Safe_iterator_base::_M_attach(__seq, _M_constant());
367 /** Likewise, but not thread-safe. */
368 void
369 _M_attach_single(_Safe_sequence_base* __seq)
371 _Safe_iterator_base::_M_attach_single(__seq, _M_constant());
374 /// Is the iterator dereferenceable?
375 bool
376 _M_dereferenceable() const
377 { return !this->_M_singular() && !_M_is_end() && !_M_is_before_begin(); }
379 /// Is the iterator before a dereferenceable one?
380 bool
381 _M_before_dereferenceable() const
383 _Self __it = *this;
384 return __it._M_incrementable() && (++__it)._M_dereferenceable();
387 /// Is the iterator incrementable?
388 bool
389 _M_incrementable() const
390 { return !this->_M_singular() && !_M_is_end(); }
392 // Is the iterator decrementable?
393 bool
394 _M_decrementable() const { return !_M_singular() && !_M_is_begin(); }
396 // Can we advance the iterator @p __n steps (@p __n may be negative)
397 bool
398 _M_can_advance(const difference_type& __n) const;
400 // Is the iterator range [*this, __rhs) valid?
401 template<typename _Other>
402 bool
403 _M_valid_range(const _Safe_iterator<_Other, _Sequence>& __rhs) const;
405 // The sequence this iterator references.
406 const _Sequence*
407 _M_get_sequence() const
408 { return static_cast<const _Sequence*>(_M_sequence); }
410 /// Is this iterator equal to the sequence's begin() iterator?
411 bool _M_is_begin() const
412 { return base() == _M_get_sequence()->_M_base().begin(); }
414 /// Is this iterator equal to the sequence's end() iterator?
415 bool _M_is_end() const
416 { return base() == _M_get_sequence()->_M_base().end(); }
418 /// Is this iterator equal to the sequence's before_begin() iterator if
419 /// any?
420 bool _M_is_before_begin() const
421 { return _BeforeBeginHelper<_Sequence>::_M_Is(base(), _M_get_sequence()); }
424 template<typename _IteratorL, typename _IteratorR, typename _Sequence>
425 inline bool
426 operator==(const _Safe_iterator<_IteratorL, _Sequence>& __lhs,
427 const _Safe_iterator<_IteratorR, _Sequence>& __rhs)
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();
440 template<typename _Iterator, typename _Sequence>
441 inline bool
442 operator==(const _Safe_iterator<_Iterator, _Sequence>& __lhs,
443 const _Safe_iterator<_Iterator, _Sequence>& __rhs)
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();
456 template<typename _IteratorL, typename _IteratorR, typename _Sequence>
457 inline bool
458 operator!=(const _Safe_iterator<_IteratorL, _Sequence>& __lhs,
459 const _Safe_iterator<_IteratorR, _Sequence>& __rhs)
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();
472 template<typename _Iterator, typename _Sequence>
473 inline bool
474 operator!=(const _Safe_iterator<_Iterator, _Sequence>& __lhs,
475 const _Safe_iterator<_Iterator, _Sequence>& __rhs)
477 _GLIBCXX_DEBUG_VERIFY(! __lhs._M_singular() && ! __rhs._M_singular(),
478 _M_message(__msg_iter_compare_bad)
479 ._M_iterator(__lhs, "lhs")
480 ._M_iterator(__rhs, "rhs"));
481 _GLIBCXX_DEBUG_VERIFY(__lhs._M_can_compare(__rhs),
482 _M_message(__msg_compare_different)
483 ._M_iterator(__lhs, "lhs")
484 ._M_iterator(__rhs, "rhs"));
485 return __lhs.base() != __rhs.base();
488 template<typename _IteratorL, typename _IteratorR, typename _Sequence>
489 inline bool
490 operator<(const _Safe_iterator<_IteratorL, _Sequence>& __lhs,
491 const _Safe_iterator<_IteratorR, _Sequence>& __rhs)
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();
504 template<typename _Iterator, typename _Sequence>
505 inline bool
506 operator<(const _Safe_iterator<_Iterator, _Sequence>& __lhs,
507 const _Safe_iterator<_Iterator, _Sequence>& __rhs)
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();
520 template<typename _IteratorL, typename _IteratorR, typename _Sequence>
521 inline bool
522 operator<=(const _Safe_iterator<_IteratorL, _Sequence>& __lhs,
523 const _Safe_iterator<_IteratorR, _Sequence>& __rhs)
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();
536 template<typename _Iterator, typename _Sequence>
537 inline bool
538 operator<=(const _Safe_iterator<_Iterator, _Sequence>& __lhs,
539 const _Safe_iterator<_Iterator, _Sequence>& __rhs)
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();
552 template<typename _IteratorL, typename _IteratorR, typename _Sequence>
553 inline bool
554 operator>(const _Safe_iterator<_IteratorL, _Sequence>& __lhs,
555 const _Safe_iterator<_IteratorR, _Sequence>& __rhs)
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();
568 template<typename _Iterator, typename _Sequence>
569 inline bool
570 operator>(const _Safe_iterator<_Iterator, _Sequence>& __lhs,
571 const _Safe_iterator<_Iterator, _Sequence>& __rhs)
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();
584 template<typename _IteratorL, typename _IteratorR, typename _Sequence>
585 inline bool
586 operator>=(const _Safe_iterator<_IteratorL, _Sequence>& __lhs,
587 const _Safe_iterator<_IteratorR, _Sequence>& __rhs)
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();
600 template<typename _Iterator, typename _Sequence>
601 inline bool
602 operator>=(const _Safe_iterator<_Iterator, _Sequence>& __lhs,
603 const _Safe_iterator<_Iterator, _Sequence>& __rhs)
605 _GLIBCXX_DEBUG_VERIFY(! __lhs._M_singular() && ! __rhs._M_singular(),
606 _M_message(__msg_iter_order_bad)
607 ._M_iterator(__lhs, "lhs")
608 ._M_iterator(__rhs, "rhs"));
609 _GLIBCXX_DEBUG_VERIFY(__lhs._M_can_compare(__rhs),
610 _M_message(__msg_order_different)
611 ._M_iterator(__lhs, "lhs")
612 ._M_iterator(__rhs, "rhs"));
613 return __lhs.base() >= __rhs.base();
616 // _GLIBCXX_RESOLVE_LIB_DEFECTS
617 // According to the resolution of DR179 not only the various comparison
618 // operators but also operator- must accept mixed iterator/const_iterator
619 // parameters.
620 template<typename _IteratorL, typename _IteratorR, typename _Sequence>
621 inline typename _Safe_iterator<_IteratorL, _Sequence>::difference_type
622 operator-(const _Safe_iterator<_IteratorL, _Sequence>& __lhs,
623 const _Safe_iterator<_IteratorR, _Sequence>& __rhs)
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();
636 template<typename _Iterator, typename _Sequence>
637 inline typename _Safe_iterator<_Iterator, _Sequence>::difference_type
638 operator-(const _Safe_iterator<_Iterator, _Sequence>& __lhs,
639 const _Safe_iterator<_Iterator, _Sequence>& __rhs)
641 _GLIBCXX_DEBUG_VERIFY(! __lhs._M_singular() && ! __rhs._M_singular(),
642 _M_message(__msg_distance_bad)
643 ._M_iterator(__lhs, "lhs")
644 ._M_iterator(__rhs, "rhs"));
645 _GLIBCXX_DEBUG_VERIFY(__lhs._M_can_compare(__rhs),
646 _M_message(__msg_distance_different)
647 ._M_iterator(__lhs, "lhs")
648 ._M_iterator(__rhs, "rhs"));
649 return __lhs.base() - __rhs.base();
652 template<typename _Iterator, typename _Sequence>
653 inline _Safe_iterator<_Iterator, _Sequence>
654 operator+(typename _Safe_iterator<_Iterator,_Sequence>::difference_type __n,
655 const _Safe_iterator<_Iterator, _Sequence>& __i)
656 { return __i + __n; }
658 // Helper struct to detect random access safe iterators.
659 template<typename _Iterator>
660 struct __is_safe_random_iterator
662 enum { __value = 0 };
663 typedef std::__false_type __type;
666 template<typename _Iterator, typename _Sequence>
667 struct __is_safe_random_iterator<_Safe_iterator<_Iterator, _Sequence> >
668 : std::__are_same<std::random_access_iterator_tag,
669 typename std::iterator_traits<_Iterator>::
670 iterator_category>
671 { };
673 template<typename _Iterator>
674 struct _Siter_base
675 : std::_Iter_base<_Iterator, __is_safe_random_iterator<_Iterator>::__value>
676 { };
678 /** Helper function to extract base iterator of random access safe iterator
679 in order to reduce performance impact of debug mode. Limited to random
680 access iterator because it is the only category for which it is possible
681 to check for correct iterators order in the __valid_range function
682 thanks to the < operator.
684 template<typename _Iterator>
685 inline typename _Siter_base<_Iterator>::iterator_type
686 __base(_Iterator __it)
687 { return _Siter_base<_Iterator>::_S_base(__it); }
688 } // namespace __gnu_debug
690 #include <debug/safe_iterator.tcc>
692 #endif