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