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