2012-02-06 François Dumont <fdumont@gcc.gnu.org>
[official-gcc.git] / libstdc++-v3 / include / debug / safe_iterator.h
blobe7cfe9c9d53b8564cee49fac52cbf0059ba7a236
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 if (this->_M_incrementable())
385 _Iterator __base = base();
386 return ++__base != _M_get_sequence()->_M_base().end();
388 return false;
391 /// Is the iterator incrementable?
392 bool
393 _M_incrementable() const
394 { return !this->_M_singular() && !_M_is_end(); }
396 // Is the iterator decrementable?
397 bool
398 _M_decrementable() const { return !_M_singular() && !_M_is_begin(); }
400 // Can we advance the iterator @p __n steps (@p __n may be negative)
401 bool
402 _M_can_advance(const difference_type& __n) const;
404 // Is the iterator range [*this, __rhs) valid?
405 template<typename _Other>
406 bool
407 _M_valid_range(const _Safe_iterator<_Other, _Sequence>& __rhs) const;
409 // The sequence this iterator references.
410 const _Sequence*
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
423 /// any?
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>
429 inline bool
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>
445 inline bool
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>
461 inline bool
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>
477 inline bool
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>
493 inline bool
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>
509 inline bool
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>
525 inline bool
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>
541 inline bool
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>
557 inline bool
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>
573 inline bool
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>
589 inline bool
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>
605 inline bool
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
623 // parameters.
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>::
674 iterator_category>
675 { };
677 template<typename _Iterator>
678 struct _Siter_base
679 : std::_Iter_base<_Iterator, __is_safe_random_iterator<_Iterator>::__value>
680 { };
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>
696 #endif