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