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