]> git.ipfire.org Git - thirdparty/gcc.git/blob - libstdc++-v3/include/debug/safe_iterator.h
re PR libstdc++/58338 (Add noexcept to functions with a narrow contract)
[thirdparty/gcc.git] / libstdc++-v3 / include / debug / safe_iterator.h
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() _GLIBCXX_NOEXCEPT : _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 _GLIBCXX_NOEXCEPT
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) _GLIBCXX_NOEXCEPT
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 #if __cplusplus >= 201103L
176 /**
177 * @brief Move construction.
178 * @post __x is singular and unattached
179 */
180 _Safe_iterator(_Safe_iterator&& __x) noexcept : _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) _GLIBCXX_NOEXCEPT
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) _GLIBCXX_NOEXCEPT
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 #if __cplusplus >= 201103L
233 /**
234 * @brief Move assignment.
235 * @post __x is singular and unattached
236 */
237 _Safe_iterator&
238 operator=(_Safe_iterator&& __x) noexcept
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 _GLIBCXX_NOEXCEPT
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 */
274 pointer
275 operator->() const _GLIBCXX_NOEXCEPT
276 {
277 _GLIBCXX_DEBUG_VERIFY(this->_M_dereferenceable(),
278 _M_message(__msg_bad_deref)
279 ._M_iterator(*this, "this"));
280 return std::__addressof(*_M_current);
281 }
282
283 // ------ Input iterator requirements ------
284 /**
285 * @brief Iterator preincrement
286 * @pre iterator is incrementable
287 */
288 _Safe_iterator&
289 operator++() _GLIBCXX_NOEXCEPT
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) _GLIBCXX_NOEXCEPT
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--() _GLIBCXX_NOEXCEPT
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) _GLIBCXX_NOEXCEPT
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 _GLIBCXX_NOEXCEPT
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) _GLIBCXX_NOEXCEPT
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 _GLIBCXX_NOEXCEPT
367 {
368 _Safe_iterator __tmp(*this);
369 __tmp += __n;
370 return __tmp;
371 }
372
373 _Safe_iterator&
374 operator-=(const difference_type& __n) _GLIBCXX_NOEXCEPT
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 _GLIBCXX_NOEXCEPT
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 _GLIBCXX_NOEXCEPT { 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 _GLIBCXX_NOEXCEPT { 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 _GLIBCXX_NOEXCEPT
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 _GLIBCXX_NOEXCEPT
504 {
505 _GLIBCXX_DEBUG_VERIFY(! __lhs._M_singular() && ! __rhs._M_singular(),
506 _M_message(__msg_iter_compare_bad)
507 ._M_iterator(__lhs, "lhs")
508 ._M_iterator(__rhs, "rhs"));
509 _GLIBCXX_DEBUG_VERIFY(__lhs._M_can_compare(__rhs),
510 _M_message(__msg_compare_different)
511 ._M_iterator(__lhs, "lhs")
512 ._M_iterator(__rhs, "rhs"));
513 return __lhs.base() == __rhs.base();
514 }
515
516 template<typename _IteratorL, typename _IteratorR, typename _Sequence>
517 inline bool
518 operator!=(const _Safe_iterator<_IteratorL, _Sequence>& __lhs,
519 const _Safe_iterator<_IteratorR, _Sequence>& __rhs)
520 _GLIBCXX_NOEXCEPT
521 {
522 _GLIBCXX_DEBUG_VERIFY(! __lhs._M_singular() && ! __rhs._M_singular(),
523 _M_message(__msg_iter_compare_bad)
524 ._M_iterator(__lhs, "lhs")
525 ._M_iterator(__rhs, "rhs"));
526 _GLIBCXX_DEBUG_VERIFY(__lhs._M_can_compare(__rhs),
527 _M_message(__msg_compare_different)
528 ._M_iterator(__lhs, "lhs")
529 ._M_iterator(__rhs, "rhs"));
530 return __lhs.base() != __rhs.base();
531 }
532
533 template<typename _Iterator, typename _Sequence>
534 inline bool
535 operator!=(const _Safe_iterator<_Iterator, _Sequence>& __lhs,
536 const _Safe_iterator<_Iterator, _Sequence>& __rhs)
537 _GLIBCXX_NOEXCEPT
538 {
539 _GLIBCXX_DEBUG_VERIFY(! __lhs._M_singular() && ! __rhs._M_singular(),
540 _M_message(__msg_iter_compare_bad)
541 ._M_iterator(__lhs, "lhs")
542 ._M_iterator(__rhs, "rhs"));
543 _GLIBCXX_DEBUG_VERIFY(__lhs._M_can_compare(__rhs),
544 _M_message(__msg_compare_different)
545 ._M_iterator(__lhs, "lhs")
546 ._M_iterator(__rhs, "rhs"));
547 return __lhs.base() != __rhs.base();
548 }
549
550 template<typename _IteratorL, typename _IteratorR, typename _Sequence>
551 inline bool
552 operator<(const _Safe_iterator<_IteratorL, _Sequence>& __lhs,
553 const _Safe_iterator<_IteratorR, _Sequence>& __rhs)
554 _GLIBCXX_NOEXCEPT
555 {
556 _GLIBCXX_DEBUG_VERIFY(! __lhs._M_singular() && ! __rhs._M_singular(),
557 _M_message(__msg_iter_order_bad)
558 ._M_iterator(__lhs, "lhs")
559 ._M_iterator(__rhs, "rhs"));
560 _GLIBCXX_DEBUG_VERIFY(__lhs._M_can_compare(__rhs),
561 _M_message(__msg_order_different)
562 ._M_iterator(__lhs, "lhs")
563 ._M_iterator(__rhs, "rhs"));
564 return __lhs.base() < __rhs.base();
565 }
566
567 template<typename _Iterator, typename _Sequence>
568 inline bool
569 operator<(const _Safe_iterator<_Iterator, _Sequence>& __lhs,
570 const _Safe_iterator<_Iterator, _Sequence>& __rhs)
571 _GLIBCXX_NOEXCEPT
572 {
573 _GLIBCXX_DEBUG_VERIFY(! __lhs._M_singular() && ! __rhs._M_singular(),
574 _M_message(__msg_iter_order_bad)
575 ._M_iterator(__lhs, "lhs")
576 ._M_iterator(__rhs, "rhs"));
577 _GLIBCXX_DEBUG_VERIFY(__lhs._M_can_compare(__rhs),
578 _M_message(__msg_order_different)
579 ._M_iterator(__lhs, "lhs")
580 ._M_iterator(__rhs, "rhs"));
581 return __lhs.base() < __rhs.base();
582 }
583
584 template<typename _IteratorL, typename _IteratorR, typename _Sequence>
585 inline bool
586 operator<=(const _Safe_iterator<_IteratorL, _Sequence>& __lhs,
587 const _Safe_iterator<_IteratorR, _Sequence>& __rhs)
588 _GLIBCXX_NOEXCEPT
589 {
590 _GLIBCXX_DEBUG_VERIFY(! __lhs._M_singular() && ! __rhs._M_singular(),
591 _M_message(__msg_iter_order_bad)
592 ._M_iterator(__lhs, "lhs")
593 ._M_iterator(__rhs, "rhs"));
594 _GLIBCXX_DEBUG_VERIFY(__lhs._M_can_compare(__rhs),
595 _M_message(__msg_order_different)
596 ._M_iterator(__lhs, "lhs")
597 ._M_iterator(__rhs, "rhs"));
598 return __lhs.base() <= __rhs.base();
599 }
600
601 template<typename _Iterator, typename _Sequence>
602 inline bool
603 operator<=(const _Safe_iterator<_Iterator, _Sequence>& __lhs,
604 const _Safe_iterator<_Iterator, _Sequence>& __rhs)
605 _GLIBCXX_NOEXCEPT
606 {
607 _GLIBCXX_DEBUG_VERIFY(! __lhs._M_singular() && ! __rhs._M_singular(),
608 _M_message(__msg_iter_order_bad)
609 ._M_iterator(__lhs, "lhs")
610 ._M_iterator(__rhs, "rhs"));
611 _GLIBCXX_DEBUG_VERIFY(__lhs._M_can_compare(__rhs),
612 _M_message(__msg_order_different)
613 ._M_iterator(__lhs, "lhs")
614 ._M_iterator(__rhs, "rhs"));
615 return __lhs.base() <= __rhs.base();
616 }
617
618 template<typename _IteratorL, typename _IteratorR, typename _Sequence>
619 inline bool
620 operator>(const _Safe_iterator<_IteratorL, _Sequence>& __lhs,
621 const _Safe_iterator<_IteratorR, _Sequence>& __rhs)
622 _GLIBCXX_NOEXCEPT
623 {
624 _GLIBCXX_DEBUG_VERIFY(! __lhs._M_singular() && ! __rhs._M_singular(),
625 _M_message(__msg_iter_order_bad)
626 ._M_iterator(__lhs, "lhs")
627 ._M_iterator(__rhs, "rhs"));
628 _GLIBCXX_DEBUG_VERIFY(__lhs._M_can_compare(__rhs),
629 _M_message(__msg_order_different)
630 ._M_iterator(__lhs, "lhs")
631 ._M_iterator(__rhs, "rhs"));
632 return __lhs.base() > __rhs.base();
633 }
634
635 template<typename _Iterator, typename _Sequence>
636 inline bool
637 operator>(const _Safe_iterator<_Iterator, _Sequence>& __lhs,
638 const _Safe_iterator<_Iterator, _Sequence>& __rhs)
639 _GLIBCXX_NOEXCEPT
640 {
641 _GLIBCXX_DEBUG_VERIFY(! __lhs._M_singular() && ! __rhs._M_singular(),
642 _M_message(__msg_iter_order_bad)
643 ._M_iterator(__lhs, "lhs")
644 ._M_iterator(__rhs, "rhs"));
645 _GLIBCXX_DEBUG_VERIFY(__lhs._M_can_compare(__rhs),
646 _M_message(__msg_order_different)
647 ._M_iterator(__lhs, "lhs")
648 ._M_iterator(__rhs, "rhs"));
649 return __lhs.base() > __rhs.base();
650 }
651
652 template<typename _IteratorL, typename _IteratorR, typename _Sequence>
653 inline bool
654 operator>=(const _Safe_iterator<_IteratorL, _Sequence>& __lhs,
655 const _Safe_iterator<_IteratorR, _Sequence>& __rhs)
656 _GLIBCXX_NOEXCEPT
657 {
658 _GLIBCXX_DEBUG_VERIFY(! __lhs._M_singular() && ! __rhs._M_singular(),
659 _M_message(__msg_iter_order_bad)
660 ._M_iterator(__lhs, "lhs")
661 ._M_iterator(__rhs, "rhs"));
662 _GLIBCXX_DEBUG_VERIFY(__lhs._M_can_compare(__rhs),
663 _M_message(__msg_order_different)
664 ._M_iterator(__lhs, "lhs")
665 ._M_iterator(__rhs, "rhs"));
666 return __lhs.base() >= __rhs.base();
667 }
668
669 template<typename _Iterator, typename _Sequence>
670 inline bool
671 operator>=(const _Safe_iterator<_Iterator, _Sequence>& __lhs,
672 const _Safe_iterator<_Iterator, _Sequence>& __rhs)
673 _GLIBCXX_NOEXCEPT
674 {
675 _GLIBCXX_DEBUG_VERIFY(! __lhs._M_singular() && ! __rhs._M_singular(),
676 _M_message(__msg_iter_order_bad)
677 ._M_iterator(__lhs, "lhs")
678 ._M_iterator(__rhs, "rhs"));
679 _GLIBCXX_DEBUG_VERIFY(__lhs._M_can_compare(__rhs),
680 _M_message(__msg_order_different)
681 ._M_iterator(__lhs, "lhs")
682 ._M_iterator(__rhs, "rhs"));
683 return __lhs.base() >= __rhs.base();
684 }
685
686 // _GLIBCXX_RESOLVE_LIB_DEFECTS
687 // According to the resolution of DR179 not only the various comparison
688 // operators but also operator- must accept mixed iterator/const_iterator
689 // parameters.
690 template<typename _IteratorL, typename _IteratorR, typename _Sequence>
691 inline typename _Safe_iterator<_IteratorL, _Sequence>::difference_type
692 operator-(const _Safe_iterator<_IteratorL, _Sequence>& __lhs,
693 const _Safe_iterator<_IteratorR, _Sequence>& __rhs)
694 _GLIBCXX_NOEXCEPT
695 {
696 _GLIBCXX_DEBUG_VERIFY(! __lhs._M_singular() && ! __rhs._M_singular(),
697 _M_message(__msg_distance_bad)
698 ._M_iterator(__lhs, "lhs")
699 ._M_iterator(__rhs, "rhs"));
700 _GLIBCXX_DEBUG_VERIFY(__lhs._M_can_compare(__rhs),
701 _M_message(__msg_distance_different)
702 ._M_iterator(__lhs, "lhs")
703 ._M_iterator(__rhs, "rhs"));
704 return __lhs.base() - __rhs.base();
705 }
706
707 template<typename _Iterator, typename _Sequence>
708 inline typename _Safe_iterator<_Iterator, _Sequence>::difference_type
709 operator-(const _Safe_iterator<_Iterator, _Sequence>& __lhs,
710 const _Safe_iterator<_Iterator, _Sequence>& __rhs)
711 _GLIBCXX_NOEXCEPT
712 {
713 _GLIBCXX_DEBUG_VERIFY(! __lhs._M_singular() && ! __rhs._M_singular(),
714 _M_message(__msg_distance_bad)
715 ._M_iterator(__lhs, "lhs")
716 ._M_iterator(__rhs, "rhs"));
717 _GLIBCXX_DEBUG_VERIFY(__lhs._M_can_compare(__rhs),
718 _M_message(__msg_distance_different)
719 ._M_iterator(__lhs, "lhs")
720 ._M_iterator(__rhs, "rhs"));
721 return __lhs.base() - __rhs.base();
722 }
723
724 template<typename _Iterator, typename _Sequence>
725 inline _Safe_iterator<_Iterator, _Sequence>
726 operator+(typename _Safe_iterator<_Iterator,_Sequence>::difference_type __n,
727 const _Safe_iterator<_Iterator, _Sequence>& __i) _GLIBCXX_NOEXCEPT
728 { return __i + __n; }
729 } // namespace __gnu_debug
730
731 #include <debug/safe_iterator.tcc>
732
733 #endif