libstdc++
safe_iterator.h
Go to the documentation of this file.
1 // Safe iterator implementation -*- C++ -*-
2 
3 // Copyright (C) 2003, 2004, 2005, 2006, 2009, 2010, 2011, 2012
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.
11 
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.
16 
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.
20 
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/>.
25 
26 /** @file debug/safe_iterator.h
27  * This file is a GNU debug extension to the Standard C++ Library.
28  */
29 
30 #ifndef _GLIBCXX_DEBUG_SAFE_ITERATOR_H
31 #define _GLIBCXX_DEBUG_SAFE_ITERATOR_H 1
32 
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>
40 
41 namespace __gnu_debug
42 {
43  /** Helper struct to deal with sequence offering a before_begin
44  * iterator.
45  **/
46  template <typename _Sequence>
48  {
49  typedef typename _Sequence::const_iterator _It;
50  typedef typename _It::iterator_type _BaseIt;
51 
52  static bool
53  _M_Is(_BaseIt __it, const _Sequence* __seq)
54  { return false; }
55  };
56 
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.
60  */
61  inline bool
62  __check_singular_aux(const _Safe_iterator_base* __x)
63  { return __x->_M_singular(); }
64 
65  /** \brief Safe iterator wrapper.
66  *
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.
75  */
76  template<typename _Iterator, typename _Sequence>
77  class _Safe_iterator : public _Safe_iterator_base
78  {
79  typedef _Safe_iterator _Self;
80 
81  /** The precision to which we can calculate the distance between
82  * two iterators.
83  */
84  enum _Distance_precision
85  {
86  __dp_equality, //< Can compare iterator equality, only
87  __dp_sign, //< Can determine equality and ordering
88  __dp_exact //< Can determine distance precisely
89  };
90 
91  /// The underlying iterator
92  _Iterator _M_current;
93 
94  /// Determine if this is a constant iterator.
95  bool
96  _M_constant() const
97  {
98  typedef typename _Sequence::const_iterator const_iterator;
99  return std::__are_same<const_iterator, _Safe_iterator>::__value;
100  }
101 
102  typedef std::iterator_traits<_Iterator> _Traits;
103 
104  public:
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;
111 
112  /// @post the iterator is singular and unattached
113  _Safe_iterator() : _M_current() { }
114 
115  /**
116  * @brief Safe iterator construction from an unsafe iterator and
117  * its sequence.
118  *
119  * @pre @p seq is not NULL
120  * @post this is not singular
121  */
122  _Safe_iterator(const _Iterator& __i, const _Sequence* __seq)
123  : _Safe_iterator_base(__seq, _M_constant()), _M_current(__i)
124  {
126  _M_message(__msg_init_singular)
127  ._M_iterator(*this, "this"));
128  }
129 
130  /**
131  * @brief Copy construction.
132  */
134  : _Safe_iterator_base(__x, _M_constant()), _M_current(__x._M_current)
135  {
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"));
143  }
144 
145 #ifdef __GXX_EXPERIMENTAL_CXX0X__
146  /**
147  * @brief Move construction.
148  * @post __x is singular and unattached
149  */
150  _Safe_iterator(_Safe_iterator&& __x) : _M_current()
151  {
152  _GLIBCXX_DEBUG_VERIFY(!__x._M_singular()
153  || __x._M_current == _Iterator(),
154  _M_message(__msg_init_copy_singular)
155  ._M_iterator(*this, "this")
156  ._M_iterator(__x, "other"));
157  std::swap(_M_current, __x._M_current);
158  this->_M_attach(__x._M_sequence);
159  __x._M_detach();
160  }
161 #endif
162 
163  /**
164  * @brief Converting constructor from a mutable iterator to a
165  * constant iterator.
166  */
167  template<typename _MutableIterator>
169  const _Safe_iterator<_MutableIterator,
170  typename __gnu_cxx::__enable_if<(std::__are_same<_MutableIterator,
171  typename _Sequence::iterator::iterator_type>::__value),
172  _Sequence>::__type>& __x)
173  : _Safe_iterator_base(__x, _M_constant()), _M_current(__x.base())
174  {
175  // _GLIBCXX_RESOLVE_LIB_DEFECTS
176  // DR 408. Is vector<reverse_iterator<char*> > forbidden?
177  _GLIBCXX_DEBUG_VERIFY(!__x._M_singular()
178  || __x.base() == _Iterator(),
179  _M_message(__msg_init_const_singular)
180  ._M_iterator(*this, "this")
181  ._M_iterator(__x, "other"));
182  }
183 
184  /**
185  * @brief Copy assignment.
186  */
189  {
190  // _GLIBCXX_RESOLVE_LIB_DEFECTS
191  // DR 408. Is vector<reverse_iterator<char*> > forbidden?
192  _GLIBCXX_DEBUG_VERIFY(!__x._M_singular()
193  || __x._M_current == _Iterator(),
194  _M_message(__msg_copy_singular)
195  ._M_iterator(*this, "this")
196  ._M_iterator(__x, "other"));
197  _M_current = __x._M_current;
198  this->_M_attach(__x._M_sequence);
199  return *this;
200  }
201 
202 #ifdef __GXX_EXPERIMENTAL_CXX0X__
203  /**
204  * @brief Move assignment.
205  * @post __x is singular and unattached
206  */
209  {
210  _GLIBCXX_DEBUG_VERIFY(!__x._M_singular()
211  || __x._M_current == _Iterator(),
212  _M_message(__msg_copy_singular)
213  ._M_iterator(*this, "this")
214  ._M_iterator(__x, "other"));
215  _M_current = __x._M_current;
216  _M_attach(__x._M_sequence);
217  __x._M_detach();
218  __x._M_current = _Iterator();
219  return *this;
220  }
221 #endif
222 
223  /**
224  * @brief Iterator dereference.
225  * @pre iterator is dereferenceable
226  */
227  reference
228  operator*() const
229  {
231  _M_message(__msg_bad_deref)
232  ._M_iterator(*this, "this"));
233  return *_M_current;
234  }
235 
236  /**
237  * @brief Iterator dereference.
238  * @pre iterator is dereferenceable
239  * @todo Make this correct w.r.t. iterators that return proxies
240  * @todo Use addressof() instead of & operator
241  */
242  pointer
243  operator->() const
244  {
246  _M_message(__msg_bad_deref)
247  ._M_iterator(*this, "this"));
248  return &*_M_current;
249  }
250 
251  // ------ Input iterator requirements ------
252  /**
253  * @brief Iterator preincrement
254  * @pre iterator is incrementable
255  */
258  {
260  _M_message(__msg_bad_inc)
261  ._M_iterator(*this, "this"));
262  ++_M_current;
263  return *this;
264  }
265 
266  /**
267  * @brief Iterator postincrement
268  * @pre iterator is incrementable
269  */
272  {
274  _M_message(__msg_bad_inc)
275  ._M_iterator(*this, "this"));
276  _Safe_iterator __tmp(*this);
277  ++_M_current;
278  return __tmp;
279  }
280 
281  // ------ Bidirectional iterator requirements ------
282  /**
283  * @brief Iterator predecrement
284  * @pre iterator is decrementable
285  */
288  {
289  _GLIBCXX_DEBUG_VERIFY(this->_M_decrementable(),
290  _M_message(__msg_bad_dec)
291  ._M_iterator(*this, "this"));
292  --_M_current;
293  return *this;
294  }
295 
296  /**
297  * @brief Iterator postdecrement
298  * @pre iterator is decrementable
299  */
302  {
303  _GLIBCXX_DEBUG_VERIFY(this->_M_decrementable(),
304  _M_message(__msg_bad_dec)
305  ._M_iterator(*this, "this"));
306  _Safe_iterator __tmp(*this);
307  --_M_current;
308  return __tmp;
309  }
310 
311  // ------ Random access iterator requirements ------
312  reference
313  operator[](const difference_type& __n) const
314  {
315  _GLIBCXX_DEBUG_VERIFY(this->_M_can_advance(__n)
316  && this->_M_can_advance(__n+1),
317  _M_message(__msg_iter_subscript_oob)
318  ._M_iterator(*this)._M_integer(__n));
319 
320  return _M_current[__n];
321  }
322 
324  operator+=(const difference_type& __n)
325  {
326  _GLIBCXX_DEBUG_VERIFY(this->_M_can_advance(__n),
327  _M_message(__msg_advance_oob)
328  ._M_iterator(*this)._M_integer(__n));
329  _M_current += __n;
330  return *this;
331  }
332 
334  operator+(const difference_type& __n) const
335  {
336  _Safe_iterator __tmp(*this);
337  __tmp += __n;
338  return __tmp;
339  }
340 
342  operator-=(const difference_type& __n)
343  {
344  _GLIBCXX_DEBUG_VERIFY(this->_M_can_advance(-__n),
345  _M_message(__msg_retreat_oob)
346  ._M_iterator(*this)._M_integer(__n));
347  _M_current += -__n;
348  return *this;
349  }
350 
352  operator-(const difference_type& __n) const
353  {
354  _Safe_iterator __tmp(*this);
355  __tmp -= __n;
356  return __tmp;
357  }
358 
359  // ------ Utilities ------
360  /**
361  * @brief Return the underlying iterator
362  */
363  _Iterator
364  base() const { return _M_current; }
365 
366  /**
367  * @brief Conversion to underlying non-debug iterator to allow
368  * better interaction with non-debug containers.
369  */
370  operator _Iterator() const { return _M_current; }
371 
372  /** Attach iterator to the given sequence. */
373  void
375  {
376  _Safe_iterator_base::_M_attach(__seq, _M_constant());
377  }
378 
379  /** Likewise, but not thread-safe. */
380  void
382  {
383  _Safe_iterator_base::_M_attach_single(__seq, _M_constant());
384  }
385 
386  /// Is the iterator dereferenceable?
387  bool
389  { return !this->_M_singular() && !_M_is_end() && !_M_is_before_begin(); }
390 
391  /// Is the iterator before a dereferenceable one?
392  bool
394  {
395  _Self __it = *this;
396  return __it._M_incrementable() && (++__it)._M_dereferenceable();
397  }
398 
399  /// Is the iterator incrementable?
400  bool
402  { return !this->_M_singular() && !_M_is_end(); }
403 
404  // Is the iterator decrementable?
405  bool
406  _M_decrementable() const { return !_M_singular() && !_M_is_begin(); }
407 
408  // Can we advance the iterator @p __n steps (@p __n may be negative)
409  bool
410  _M_can_advance(const difference_type& __n) const;
411 
412  // Is the iterator range [*this, __rhs) valid?
413  template<typename _Other>
414  bool
415  _M_valid_range(const _Safe_iterator<_Other, _Sequence>& __rhs) const;
416 
417  // The sequence this iterator references.
418  const _Sequence*
419  _M_get_sequence() const
420  { return static_cast<const _Sequence*>(_M_sequence); }
421 
422  /** Determine the distance between two iterators with some known
423  * precision.
424  */
425  template<typename _Iterator1, typename _Iterator2>
427  _M_get_distance(const _Iterator1& __lhs, const _Iterator2& __rhs)
428  {
429  typedef typename std::iterator_traits<_Iterator1>::iterator_category
430  _Category;
431  return _M_get_distance(__lhs, __rhs, _Category());
432  }
433 
434  template<typename _Iterator1, typename _Iterator2>
436  _M_get_distance(const _Iterator1& __lhs, const _Iterator2& __rhs,
438  { return std::make_pair(__rhs - __lhs, __dp_exact); }
439 
440  template<typename _Iterator1, typename _Iterator2>
442  _M_get_distance(const _Iterator1& __lhs, const _Iterator2& __rhs,
444  { return std::make_pair(__lhs == __rhs? 0 : 1, __dp_equality); }
445 
446  /// Is this iterator equal to the sequence's begin() iterator?
447  bool _M_is_begin() const
448  { return base() == _M_get_sequence()->_M_base().begin(); }
449 
450  /// Is this iterator equal to the sequence's end() iterator?
451  bool _M_is_end() const
452  { return base() == _M_get_sequence()->_M_base().end(); }
453 
454  /// Is this iterator equal to the sequence's before_begin() iterator if
455  /// any?
456  bool _M_is_before_begin() const
457  {
458  return _BeforeBeginHelper<_Sequence>::_M_Is(base(), _M_get_sequence());
459  }
460  };
461 
462  template<typename _IteratorL, typename _IteratorR, typename _Sequence>
463  inline bool
464  operator==(const _Safe_iterator<_IteratorL, _Sequence>& __lhs,
465  const _Safe_iterator<_IteratorR, _Sequence>& __rhs)
466  {
467  _GLIBCXX_DEBUG_VERIFY(! __lhs._M_singular() && ! __rhs._M_singular(),
468  _M_message(__msg_iter_compare_bad)
469  ._M_iterator(__lhs, "lhs")
470  ._M_iterator(__rhs, "rhs"));
471  _GLIBCXX_DEBUG_VERIFY(__lhs._M_can_compare(__rhs),
472  _M_message(__msg_compare_different)
473  ._M_iterator(__lhs, "lhs")
474  ._M_iterator(__rhs, "rhs"));
475  return __lhs.base() == __rhs.base();
476  }
477 
478  template<typename _Iterator, typename _Sequence>
479  inline bool
480  operator==(const _Safe_iterator<_Iterator, _Sequence>& __lhs,
481  const _Safe_iterator<_Iterator, _Sequence>& __rhs)
482  {
483  _GLIBCXX_DEBUG_VERIFY(! __lhs._M_singular() && ! __rhs._M_singular(),
484  _M_message(__msg_iter_compare_bad)
485  ._M_iterator(__lhs, "lhs")
486  ._M_iterator(__rhs, "rhs"));
487  _GLIBCXX_DEBUG_VERIFY(__lhs._M_can_compare(__rhs),
488  _M_message(__msg_compare_different)
489  ._M_iterator(__lhs, "lhs")
490  ._M_iterator(__rhs, "rhs"));
491  return __lhs.base() == __rhs.base();
492  }
493 
494  template<typename _IteratorL, typename _IteratorR, typename _Sequence>
495  inline bool
496  operator!=(const _Safe_iterator<_IteratorL, _Sequence>& __lhs,
497  const _Safe_iterator<_IteratorR, _Sequence>& __rhs)
498  {
499  _GLIBCXX_DEBUG_VERIFY(! __lhs._M_singular() && ! __rhs._M_singular(),
500  _M_message(__msg_iter_compare_bad)
501  ._M_iterator(__lhs, "lhs")
502  ._M_iterator(__rhs, "rhs"));
503  _GLIBCXX_DEBUG_VERIFY(__lhs._M_can_compare(__rhs),
504  _M_message(__msg_compare_different)
505  ._M_iterator(__lhs, "lhs")
506  ._M_iterator(__rhs, "rhs"));
507  return __lhs.base() != __rhs.base();
508  }
509 
510  template<typename _Iterator, typename _Sequence>
511  inline bool
512  operator!=(const _Safe_iterator<_Iterator, _Sequence>& __lhs,
513  const _Safe_iterator<_Iterator, _Sequence>& __rhs)
514  {
515  _GLIBCXX_DEBUG_VERIFY(! __lhs._M_singular() && ! __rhs._M_singular(),
516  _M_message(__msg_iter_compare_bad)
517  ._M_iterator(__lhs, "lhs")
518  ._M_iterator(__rhs, "rhs"));
519  _GLIBCXX_DEBUG_VERIFY(__lhs._M_can_compare(__rhs),
520  _M_message(__msg_compare_different)
521  ._M_iterator(__lhs, "lhs")
522  ._M_iterator(__rhs, "rhs"));
523  return __lhs.base() != __rhs.base();
524  }
525 
526  template<typename _IteratorL, typename _IteratorR, typename _Sequence>
527  inline bool
528  operator<(const _Safe_iterator<_IteratorL, _Sequence>& __lhs,
529  const _Safe_iterator<_IteratorR, _Sequence>& __rhs)
530  {
531  _GLIBCXX_DEBUG_VERIFY(! __lhs._M_singular() && ! __rhs._M_singular(),
532  _M_message(__msg_iter_order_bad)
533  ._M_iterator(__lhs, "lhs")
534  ._M_iterator(__rhs, "rhs"));
535  _GLIBCXX_DEBUG_VERIFY(__lhs._M_can_compare(__rhs),
536  _M_message(__msg_order_different)
537  ._M_iterator(__lhs, "lhs")
538  ._M_iterator(__rhs, "rhs"));
539  return __lhs.base() < __rhs.base();
540  }
541 
542  template<typename _Iterator, typename _Sequence>
543  inline bool
544  operator<(const _Safe_iterator<_Iterator, _Sequence>& __lhs,
545  const _Safe_iterator<_Iterator, _Sequence>& __rhs)
546  {
547  _GLIBCXX_DEBUG_VERIFY(! __lhs._M_singular() && ! __rhs._M_singular(),
548  _M_message(__msg_iter_order_bad)
549  ._M_iterator(__lhs, "lhs")
550  ._M_iterator(__rhs, "rhs"));
551  _GLIBCXX_DEBUG_VERIFY(__lhs._M_can_compare(__rhs),
552  _M_message(__msg_order_different)
553  ._M_iterator(__lhs, "lhs")
554  ._M_iterator(__rhs, "rhs"));
555  return __lhs.base() < __rhs.base();
556  }
557 
558  template<typename _IteratorL, typename _IteratorR, typename _Sequence>
559  inline bool
560  operator<=(const _Safe_iterator<_IteratorL, _Sequence>& __lhs,
561  const _Safe_iterator<_IteratorR, _Sequence>& __rhs)
562  {
563  _GLIBCXX_DEBUG_VERIFY(! __lhs._M_singular() && ! __rhs._M_singular(),
564  _M_message(__msg_iter_order_bad)
565  ._M_iterator(__lhs, "lhs")
566  ._M_iterator(__rhs, "rhs"));
567  _GLIBCXX_DEBUG_VERIFY(__lhs._M_can_compare(__rhs),
568  _M_message(__msg_order_different)
569  ._M_iterator(__lhs, "lhs")
570  ._M_iterator(__rhs, "rhs"));
571  return __lhs.base() <= __rhs.base();
572  }
573 
574  template<typename _Iterator, typename _Sequence>
575  inline bool
576  operator<=(const _Safe_iterator<_Iterator, _Sequence>& __lhs,
577  const _Safe_iterator<_Iterator, _Sequence>& __rhs)
578  {
579  _GLIBCXX_DEBUG_VERIFY(! __lhs._M_singular() && ! __rhs._M_singular(),
580  _M_message(__msg_iter_order_bad)
581  ._M_iterator(__lhs, "lhs")
582  ._M_iterator(__rhs, "rhs"));
583  _GLIBCXX_DEBUG_VERIFY(__lhs._M_can_compare(__rhs),
584  _M_message(__msg_order_different)
585  ._M_iterator(__lhs, "lhs")
586  ._M_iterator(__rhs, "rhs"));
587  return __lhs.base() <= __rhs.base();
588  }
589 
590  template<typename _IteratorL, typename _IteratorR, typename _Sequence>
591  inline bool
592  operator>(const _Safe_iterator<_IteratorL, _Sequence>& __lhs,
593  const _Safe_iterator<_IteratorR, _Sequence>& __rhs)
594  {
595  _GLIBCXX_DEBUG_VERIFY(! __lhs._M_singular() && ! __rhs._M_singular(),
596  _M_message(__msg_iter_order_bad)
597  ._M_iterator(__lhs, "lhs")
598  ._M_iterator(__rhs, "rhs"));
599  _GLIBCXX_DEBUG_VERIFY(__lhs._M_can_compare(__rhs),
600  _M_message(__msg_order_different)
601  ._M_iterator(__lhs, "lhs")
602  ._M_iterator(__rhs, "rhs"));
603  return __lhs.base() > __rhs.base();
604  }
605 
606  template<typename _Iterator, typename _Sequence>
607  inline bool
608  operator>(const _Safe_iterator<_Iterator, _Sequence>& __lhs,
609  const _Safe_iterator<_Iterator, _Sequence>& __rhs)
610  {
611  _GLIBCXX_DEBUG_VERIFY(! __lhs._M_singular() && ! __rhs._M_singular(),
612  _M_message(__msg_iter_order_bad)
613  ._M_iterator(__lhs, "lhs")
614  ._M_iterator(__rhs, "rhs"));
615  _GLIBCXX_DEBUG_VERIFY(__lhs._M_can_compare(__rhs),
616  _M_message(__msg_order_different)
617  ._M_iterator(__lhs, "lhs")
618  ._M_iterator(__rhs, "rhs"));
619  return __lhs.base() > __rhs.base();
620  }
621 
622  template<typename _IteratorL, typename _IteratorR, typename _Sequence>
623  inline bool
624  operator>=(const _Safe_iterator<_IteratorL, _Sequence>& __lhs,
625  const _Safe_iterator<_IteratorR, _Sequence>& __rhs)
626  {
627  _GLIBCXX_DEBUG_VERIFY(! __lhs._M_singular() && ! __rhs._M_singular(),
628  _M_message(__msg_iter_order_bad)
629  ._M_iterator(__lhs, "lhs")
630  ._M_iterator(__rhs, "rhs"));
631  _GLIBCXX_DEBUG_VERIFY(__lhs._M_can_compare(__rhs),
632  _M_message(__msg_order_different)
633  ._M_iterator(__lhs, "lhs")
634  ._M_iterator(__rhs, "rhs"));
635  return __lhs.base() >= __rhs.base();
636  }
637 
638  template<typename _Iterator, typename _Sequence>
639  inline bool
640  operator>=(const _Safe_iterator<_Iterator, _Sequence>& __lhs,
641  const _Safe_iterator<_Iterator, _Sequence>& __rhs)
642  {
643  _GLIBCXX_DEBUG_VERIFY(! __lhs._M_singular() && ! __rhs._M_singular(),
644  _M_message(__msg_iter_order_bad)
645  ._M_iterator(__lhs, "lhs")
646  ._M_iterator(__rhs, "rhs"));
647  _GLIBCXX_DEBUG_VERIFY(__lhs._M_can_compare(__rhs),
648  _M_message(__msg_order_different)
649  ._M_iterator(__lhs, "lhs")
650  ._M_iterator(__rhs, "rhs"));
651  return __lhs.base() >= __rhs.base();
652  }
653 
654  // _GLIBCXX_RESOLVE_LIB_DEFECTS
655  // According to the resolution of DR179 not only the various comparison
656  // operators but also operator- must accept mixed iterator/const_iterator
657  // parameters.
658  template<typename _IteratorL, typename _IteratorR, typename _Sequence>
659  inline typename _Safe_iterator<_IteratorL, _Sequence>::difference_type
660  operator-(const _Safe_iterator<_IteratorL, _Sequence>& __lhs,
661  const _Safe_iterator<_IteratorR, _Sequence>& __rhs)
662  {
663  _GLIBCXX_DEBUG_VERIFY(! __lhs._M_singular() && ! __rhs._M_singular(),
664  _M_message(__msg_distance_bad)
665  ._M_iterator(__lhs, "lhs")
666  ._M_iterator(__rhs, "rhs"));
667  _GLIBCXX_DEBUG_VERIFY(__lhs._M_can_compare(__rhs),
668  _M_message(__msg_distance_different)
669  ._M_iterator(__lhs, "lhs")
670  ._M_iterator(__rhs, "rhs"));
671  return __lhs.base() - __rhs.base();
672  }
673 
674  template<typename _Iterator, typename _Sequence>
675  inline typename _Safe_iterator<_Iterator, _Sequence>::difference_type
676  operator-(const _Safe_iterator<_Iterator, _Sequence>& __lhs,
677  const _Safe_iterator<_Iterator, _Sequence>& __rhs)
678  {
679  _GLIBCXX_DEBUG_VERIFY(! __lhs._M_singular() && ! __rhs._M_singular(),
680  _M_message(__msg_distance_bad)
681  ._M_iterator(__lhs, "lhs")
682  ._M_iterator(__rhs, "rhs"));
683  _GLIBCXX_DEBUG_VERIFY(__lhs._M_can_compare(__rhs),
684  _M_message(__msg_distance_different)
685  ._M_iterator(__lhs, "lhs")
686  ._M_iterator(__rhs, "rhs"));
687  return __lhs.base() - __rhs.base();
688  }
689 
690  template<typename _Iterator, typename _Sequence>
691  inline _Safe_iterator<_Iterator, _Sequence>
692  operator+(typename _Safe_iterator<_Iterator,_Sequence>::difference_type __n,
693  const _Safe_iterator<_Iterator, _Sequence>& __i)
694  { return __i + __n; }
695 
696  // Helper struct to detect random access safe iterators.
697  template<typename _Iterator>
698  struct __is_safe_random_iterator
699  {
700  enum { __value = 0 };
701  typedef std::__false_type __type;
702  };
703 
704  template<typename _Iterator, typename _Sequence>
705  struct __is_safe_random_iterator<_Safe_iterator<_Iterator, _Sequence> >
706  : std::__are_same<std::random_access_iterator_tag,
707  typename std::iterator_traits<_Iterator>::
708  iterator_category>
709  { };
710 
711  template<typename _Iterator>
712  struct _Siter_base
713  : std::_Iter_base<_Iterator, __is_safe_random_iterator<_Iterator>::__value>
714  { };
715 
716  /** Helper function to extract base iterator of random access safe iterator
717  in order to reduce performance impact of debug mode. Limited to random
718  access iterator because it is the only category for which it is possible
719  to check for correct iterators order in the __valid_range function
720  thanks to the < operator.
721  */
722  template<typename _Iterator>
723  inline typename _Siter_base<_Iterator>::iterator_type
724  __base(_Iterator __it)
725  { return _Siter_base<_Iterator>::_S_base(__it); }
726 } // namespace __gnu_debug
727 
728 #include <debug/safe_iterator.tcc>
729 
730 #endif