OSDN Git Service

Backported from mainline
[pf3gnuchains/gcc-fork.git] / libstdc++-v3 / include / debug / safe_iterator.h
1 // Safe iterator implementation  -*- C++ -*-
2
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.
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>
47     struct _BeforeBeginHelper
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   /** The precision to which we can calculate the distance between
66    *  two iterators.
67    */
68   enum _Distance_precision
69     {
70       __dp_equality, //< Can compare iterator equality, only
71       __dp_sign,     //< Can determine equality and ordering
72       __dp_exact     //< Can determine distance precisely
73     };
74
75   /** Determine the distance between two iterators with some known
76    *    precision.
77   */
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); }
84
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); }
91
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)
96     {
97       typedef typename std::iterator_traits<_Iterator1>::iterator_category
98           _Category;
99       return __get_distance(__lhs, __rhs, _Category());
100     }
101
102   /** \brief Safe iterator wrapper.
103    *
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.
112    */
113   template<typename _Iterator, typename _Sequence>
114     class _Safe_iterator : public _Safe_iterator_base
115     {
116       typedef _Safe_iterator _Self;
117
118       /// The underlying iterator
119       _Iterator _M_current;
120
121       /// Determine if this is a constant iterator.
122       bool
123       _M_constant() const
124       {
125         typedef typename _Sequence::const_iterator const_iterator;
126         return std::__are_same<const_iterator, _Safe_iterator>::__value;
127       }
128
129       typedef std::iterator_traits<_Iterator> _Traits;
130
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;
138
139       /// @post the iterator is singular and unattached
140       _Safe_iterator() : _M_current() { }
141
142       /**
143        * @brief Safe iterator construction from an unsafe iterator and
144        * its sequence.
145        *
146        * @pre @p seq is not NULL
147        * @post this is not singular
148        */
149       _Safe_iterator(const _Iterator& __i, const _Sequence* __seq)
150       : _Safe_iterator_base(__seq, _M_constant()), _M_current(__i)
151       {
152         _GLIBCXX_DEBUG_VERIFY(! this->_M_singular(),
153                               _M_message(__msg_init_singular)
154                               ._M_iterator(*this, "this"));
155       }
156
157       /**
158        * @brief Copy construction.
159        */
160       _Safe_iterator(const _Safe_iterator& __x)
161       : _Safe_iterator_base(__x, _M_constant()), _M_current(__x._M_current)
162       {
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"));
170       }
171
172       /**
173        *  @brief Converting constructor from a mutable iterator to a
174        *  constant iterator.
175       */
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())
183         {
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"));
191         }
192
193       /**
194        * @brief Copy assignment.
195        */
196       _Safe_iterator&
197       operator=(const _Safe_iterator& __x)
198       {
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;
209       }
210
211       /**
212        *  @brief Iterator dereference.
213        *  @pre iterator is dereferenceable
214        */
215       reference
216       operator*() const
217       {
218         _GLIBCXX_DEBUG_VERIFY(this->_M_dereferenceable(),
219                               _M_message(__msg_bad_deref)
220                               ._M_iterator(*this, "this"));
221         return *_M_current;
222       }
223
224       /**
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
229        */
230       pointer
231       operator->() const
232       {
233         _GLIBCXX_DEBUG_VERIFY(this->_M_dereferenceable(),
234                               _M_message(__msg_bad_deref)
235                               ._M_iterator(*this, "this"));
236         return &*_M_current;
237       }
238
239       // ------ Input iterator requirements ------
240       /**
241        *  @brief Iterator preincrement
242        *  @pre iterator is incrementable
243        */
244       _Safe_iterator&
245       operator++()
246       {
247         _GLIBCXX_DEBUG_VERIFY(this->_M_incrementable(),
248                               _M_message(__msg_bad_inc)
249                               ._M_iterator(*this, "this"));
250         ++_M_current;
251         return *this;
252       }
253
254       /**
255        *  @brief Iterator postincrement
256        *  @pre iterator is incrementable
257        */
258       _Safe_iterator
259       operator++(int)
260       {
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;
267       }
268
269       // ------ Bidirectional iterator requirements ------
270       /**
271        *  @brief Iterator predecrement
272        *  @pre iterator is decrementable
273        */
274       _Safe_iterator&
275       operator--()
276       {
277         _GLIBCXX_DEBUG_VERIFY(this->_M_decrementable(),
278                               _M_message(__msg_bad_dec)
279                               ._M_iterator(*this, "this"));
280         --_M_current;
281         return *this;
282       }
283
284       /**
285        *  @brief Iterator postdecrement
286        *  @pre iterator is decrementable
287        */
288       _Safe_iterator
289       operator--(int)
290       {
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;
297       }
298
299       // ------ Random access iterator requirements ------
300       reference
301       operator[](const difference_type& __n) const
302       {
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));
307
308         return _M_current[__n];
309       }
310
311       _Safe_iterator&
312       operator+=(const difference_type& __n)
313       {
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;
319       }
320
321       _Safe_iterator
322       operator+(const difference_type& __n) const
323       {
324         _Safe_iterator __tmp(*this);
325         __tmp += __n;
326         return __tmp;
327       }
328
329       _Safe_iterator&
330       operator-=(const difference_type& __n)
331       {
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;
337       }
338
339       _Safe_iterator
340       operator-(const difference_type& __n) const
341       {
342         _Safe_iterator __tmp(*this);
343         __tmp -= __n;
344         return __tmp;
345       }
346
347       // ------ Utilities ------
348       /**
349        * @brief Return the underlying iterator
350        */
351       _Iterator
352       base() const { return _M_current; }
353
354       /**
355        * @brief Conversion to underlying non-debug iterator to allow
356        * better interaction with non-debug containers.
357        */
358       operator _Iterator() const { return _M_current; }
359
360       /** Attach iterator to the given sequence. */
361       void
362       _M_attach(_Safe_sequence_base* __seq)
363       {
364         _Safe_iterator_base::_M_attach(__seq, _M_constant());
365       }
366
367       /** Likewise, but not thread-safe. */
368       void
369       _M_attach_single(_Safe_sequence_base* __seq)
370       {
371         _Safe_iterator_base::_M_attach_single(__seq, _M_constant());
372       }
373
374       /// Is the iterator dereferenceable?
375       bool
376       _M_dereferenceable() const
377       { return !this->_M_singular() && !_M_is_end() && !_M_is_before_begin(); }
378
379       /// Is the iterator before a dereferenceable one?
380       bool
381       _M_before_dereferenceable() const
382       {
383         if (this->_M_incrementable())
384         {
385           _Iterator __base = base();
386           return ++__base != _M_get_sequence()->_M_base().end();
387         }
388         return false;
389       }
390
391       /// Is the iterator incrementable?
392       bool
393       _M_incrementable() const
394       { return !this->_M_singular() && !_M_is_end(); }
395
396       // Is the iterator decrementable?
397       bool
398       _M_decrementable() const { return !_M_singular() && !_M_is_begin(); }
399
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;
403
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;
408
409       // The sequence this iterator references.
410       const _Sequence*
411       _M_get_sequence() const
412       { return static_cast<const _Sequence*>(_M_sequence); }
413
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(); }
417
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(); }
421
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()); }
426     };
427
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)
432     {
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();
442     }
443
444   template<typename _Iterator, typename _Sequence>
445     inline bool
446     operator==(const _Safe_iterator<_Iterator, _Sequence>& __lhs,
447                const _Safe_iterator<_Iterator, _Sequence>& __rhs)
448     {
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();
458     }
459
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)
464     {
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();
474     }
475
476   template<typename _Iterator, typename _Sequence>
477     inline bool
478     operator!=(const _Safe_iterator<_Iterator, _Sequence>& __lhs,
479                const _Safe_iterator<_Iterator, _Sequence>& __rhs)
480     {
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();
490     }
491
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)
496     {
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();
506     }
507
508   template<typename _Iterator, typename _Sequence>
509     inline bool
510     operator<(const _Safe_iterator<_Iterator, _Sequence>& __lhs,
511               const _Safe_iterator<_Iterator, _Sequence>& __rhs)
512     {
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();
522     }
523
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)
528     {
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();
538     }
539
540   template<typename _Iterator, typename _Sequence>
541     inline bool
542     operator<=(const _Safe_iterator<_Iterator, _Sequence>& __lhs,
543                const _Safe_iterator<_Iterator, _Sequence>& __rhs)
544     {
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();
554     }
555
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)
560     {
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();
570     }
571
572   template<typename _Iterator, typename _Sequence>
573     inline bool
574     operator>(const _Safe_iterator<_Iterator, _Sequence>& __lhs,
575               const _Safe_iterator<_Iterator, _Sequence>& __rhs)
576     {
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();
586     }
587
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)
592     {
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();
602     }
603
604   template<typename _Iterator, typename _Sequence>
605     inline bool
606     operator>=(const _Safe_iterator<_Iterator, _Sequence>& __lhs,
607                const _Safe_iterator<_Iterator, _Sequence>& __rhs)
608     {
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();
618     }
619
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)
628     {
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();
638     }
639
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)
644      {
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();
654      }
655
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; }
661
662   // Helper struct to detect random access safe iterators.
663   template<typename _Iterator>
664     struct __is_safe_random_iterator
665     {
666       enum { __value = 0 };
667       typedef std::__false_type __type;
668     };
669
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     { };
676
677   template<typename _Iterator>
678     struct _Siter_base
679     : std::_Iter_base<_Iterator, __is_safe_random_iterator<_Iterator>::__value>
680     { };
681
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.
687   */
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
693
694 #include <debug/safe_iterator.tcc>
695
696 #endif