2014-09-29 François Dumont <fdumont@gcc.gnu.org>
[official-gcc.git] / libstdc++-v3 / include / debug / safe_iterator.h
blob8083ed317194822b036f9d2442ee76192e6f54a5
1 // Safe iterator implementation -*- C++ -*-
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.
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.
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.
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/>.
25 /** @file debug/safe_iterator.h
26 * This file is a GNU debug extension to the Standard C++ Library.
29 #ifndef _GLIBCXX_DEBUG_SAFE_ITERATOR_H
30 #define _GLIBCXX_DEBUG_SAFE_ITERATOR_H 1
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>
39 namespace __gnu_debug
41 /** Helper struct to deal with sequence offering a before_begin
42 * iterator.
43 **/
44 template <typename _Sequence>
45 struct _BeforeBeginHelper
47 template<typename _Iterator>
48 static bool
49 _S_Is(const _Safe_iterator<_Iterator, _Sequence>&)
50 { return false; }
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(); }
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(); }
65 /** The precision to which we can calculate the distance between
66 * two iterators.
68 enum _Distance_precision
70 __dp_equality, //< Can compare iterator equality, only
71 __dp_sign, //< Can determine equality and ordering
72 __dp_exact //< Can determine distance precisely
75 /** Determine the distance between two iterators with some known
76 * precision.
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); }
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); }
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)
97 typedef typename std::iterator_traits<_Iterator>::iterator_category
98 _Category;
99 return __get_distance(__lhs, __rhs, _Category());
102 /** \brief Safe iterator wrapper.
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.
113 * Note that _Iterator must be the first base class so that it gets
114 * initialized before the iterator is being attached to the container's list
115 * of iterators and it is being detached before _Iterator get
116 * destroyed. Otherwise it would result in a data race.
118 template<typename _Iterator, typename _Sequence>
119 class _Safe_iterator
120 : private _Iterator,
121 public _Safe_iterator_base
123 typedef _Iterator _Iter_base;
124 typedef _Safe_iterator_base _Safe_base;
125 typedef typename _Sequence::const_iterator _Const_iterator;
127 /// Determine if this is a constant iterator.
128 bool
129 _M_constant() const
130 { return std::__are_same<_Const_iterator, _Safe_iterator>::__value; }
132 typedef std::iterator_traits<_Iterator> _Traits;
134 struct _Attach_single
135 { };
137 _Safe_iterator(const _Iterator& __i, _Safe_sequence_base* __seq,
138 _Attach_single)
139 _GLIBCXX_NOEXCEPT
140 : _Iter_base(__i)
141 { _M_attach_single(__seq); }
143 public:
144 typedef _Iterator iterator_type;
145 typedef typename _Traits::iterator_category iterator_category;
146 typedef typename _Traits::value_type value_type;
147 typedef typename _Traits::difference_type difference_type;
148 typedef typename _Traits::reference reference;
149 typedef typename _Traits::pointer pointer;
151 /// @post the iterator is singular and unattached
152 _Safe_iterator() _GLIBCXX_NOEXCEPT : _Iter_base() { }
155 * @brief Safe iterator construction from an unsafe iterator and
156 * its sequence.
158 * @pre @p seq is not NULL
159 * @post this is not singular
161 _Safe_iterator(const _Iterator& __i, const _Safe_sequence_base* __seq)
162 _GLIBCXX_NOEXCEPT
163 : _Iter_base(__i), _Safe_base(__seq, _M_constant())
165 _GLIBCXX_DEBUG_VERIFY(!this->_M_singular(),
166 _M_message(__msg_init_singular)
167 ._M_iterator(*this, "this"));
171 * @brief Copy construction.
173 _Safe_iterator(const _Safe_iterator& __x) _GLIBCXX_NOEXCEPT
174 : _Iter_base(__x.base())
176 // _GLIBCXX_RESOLVE_LIB_DEFECTS
177 // DR 408. Is vector<reverse_iterator<char*> > forbidden?
178 _GLIBCXX_DEBUG_VERIFY(!__x._M_singular()
179 || __x.base() == _Iterator(),
180 _M_message(__msg_init_copy_singular)
181 ._M_iterator(*this, "this")
182 ._M_iterator(__x, "other"));
183 _M_attach(__x._M_sequence);
186 #if __cplusplus >= 201103L
188 * @brief Move construction.
189 * @post __x is singular and unattached
191 _Safe_iterator(_Safe_iterator&& __x) noexcept
192 : _Iter_base()
194 _GLIBCXX_DEBUG_VERIFY(!__x._M_singular()
195 || __x.base() == _Iterator(),
196 _M_message(__msg_init_copy_singular)
197 ._M_iterator(*this, "this")
198 ._M_iterator(__x, "other"));
199 _Safe_sequence_base* __seq = __x._M_sequence;
200 __x._M_detach();
201 std::swap(base(), __x.base());
202 _M_attach(__seq);
204 #endif
207 * @brief Converting constructor from a mutable iterator to a
208 * constant iterator.
210 template<typename _MutableIterator>
211 _Safe_iterator(
212 const _Safe_iterator<_MutableIterator,
213 typename __gnu_cxx::__enable_if<(std::__are_same<_MutableIterator,
214 typename _Sequence::iterator::iterator_type>::__value),
215 _Sequence>::__type>& __x) _GLIBCXX_NOEXCEPT
216 : _Iter_base(__x.base())
218 // _GLIBCXX_RESOLVE_LIB_DEFECTS
219 // DR 408. Is vector<reverse_iterator<char*> > forbidden?
220 _GLIBCXX_DEBUG_VERIFY(!__x._M_singular()
221 || __x.base() == _Iterator(),
222 _M_message(__msg_init_const_singular)
223 ._M_iterator(*this, "this")
224 ._M_iterator(__x, "other"));
225 _M_attach(__x._M_sequence);
229 * @brief Copy assignment.
231 _Safe_iterator&
232 operator=(const _Safe_iterator& __x) _GLIBCXX_NOEXCEPT
234 // _GLIBCXX_RESOLVE_LIB_DEFECTS
235 // DR 408. Is vector<reverse_iterator<char*> > forbidden?
236 _GLIBCXX_DEBUG_VERIFY(!__x._M_singular()
237 || __x.base() == _Iterator(),
238 _M_message(__msg_copy_singular)
239 ._M_iterator(*this, "this")
240 ._M_iterator(__x, "other"));
242 if (this->_M_sequence && this->_M_sequence == __x._M_sequence)
244 __gnu_cxx::__scoped_lock __l(this->_M_get_mutex());
245 base() = __x.base();
246 _M_version = __x._M_sequence->_M_version;
248 else
250 _M_detach();
251 base() = __x.base();
252 _M_attach(__x._M_sequence);
255 return *this;
258 #if __cplusplus >= 201103L
260 * @brief Move assignment.
261 * @post __x is singular and unattached
263 _Safe_iterator&
264 operator=(_Safe_iterator&& __x) noexcept
266 _GLIBCXX_DEBUG_VERIFY(this != &__x,
267 _M_message(__msg_self_move_assign)
268 ._M_iterator(*this, "this"));
269 _GLIBCXX_DEBUG_VERIFY(!__x._M_singular()
270 || __x.base() == _Iterator(),
271 _M_message(__msg_copy_singular)
272 ._M_iterator(*this, "this")
273 ._M_iterator(__x, "other"));
275 if (this->_M_sequence && this->_M_sequence == __x._M_sequence)
277 __gnu_cxx::__scoped_lock __l(this->_M_get_mutex());
278 base() = __x.base();
279 _M_version = __x._M_sequence->_M_version;
281 else
283 _M_detach();
284 base() = __x.base();
285 _M_attach(__x._M_sequence);
288 __x._M_detach();
289 __x.base() = _Iterator();
290 return *this;
292 #endif
295 * @brief Iterator dereference.
296 * @pre iterator is dereferenceable
298 reference
299 operator*() const _GLIBCXX_NOEXCEPT
301 _GLIBCXX_DEBUG_VERIFY(this->_M_dereferenceable(),
302 _M_message(__msg_bad_deref)
303 ._M_iterator(*this, "this"));
304 return *base();
308 * @brief Iterator dereference.
309 * @pre iterator is dereferenceable
310 * @todo Make this correct w.r.t. iterators that return proxies
312 pointer
313 operator->() const _GLIBCXX_NOEXCEPT
315 _GLIBCXX_DEBUG_VERIFY(this->_M_dereferenceable(),
316 _M_message(__msg_bad_deref)
317 ._M_iterator(*this, "this"));
318 return std::__addressof(*base());
321 // ------ Input iterator requirements ------
323 * @brief Iterator preincrement
324 * @pre iterator is incrementable
326 _Safe_iterator&
327 operator++() _GLIBCXX_NOEXCEPT
329 _GLIBCXX_DEBUG_VERIFY(this->_M_incrementable(),
330 _M_message(__msg_bad_inc)
331 ._M_iterator(*this, "this"));
332 __gnu_cxx::__scoped_lock(this->_M_get_mutex());
333 ++base();
334 return *this;
338 * @brief Iterator postincrement
339 * @pre iterator is incrementable
341 _Safe_iterator
342 operator++(int) _GLIBCXX_NOEXCEPT
344 _GLIBCXX_DEBUG_VERIFY(this->_M_incrementable(),
345 _M_message(__msg_bad_inc)
346 ._M_iterator(*this, "this"));
347 __gnu_cxx::__scoped_lock __l(this->_M_get_mutex());
348 return _Safe_iterator(base()++, this->_M_sequence, _Attach_single());
351 // ------ Bidirectional iterator requirements ------
353 * @brief Iterator predecrement
354 * @pre iterator is decrementable
356 _Safe_iterator&
357 operator--() _GLIBCXX_NOEXCEPT
359 _GLIBCXX_DEBUG_VERIFY(this->_M_decrementable(),
360 _M_message(__msg_bad_dec)
361 ._M_iterator(*this, "this"));
362 __gnu_cxx::__scoped_lock __l(this->_M_get_mutex());
363 --base();
364 return *this;
368 * @brief Iterator postdecrement
369 * @pre iterator is decrementable
371 _Safe_iterator
372 operator--(int) _GLIBCXX_NOEXCEPT
374 _GLIBCXX_DEBUG_VERIFY(this->_M_decrementable(),
375 _M_message(__msg_bad_dec)
376 ._M_iterator(*this, "this"));
377 __gnu_cxx::__scoped_lock __l(this->_M_get_mutex());
378 return _Safe_iterator(base()--, this->_M_sequence, _Attach_single());
381 // ------ Random access iterator requirements ------
382 reference
383 operator[](const difference_type& __n) const _GLIBCXX_NOEXCEPT
385 _GLIBCXX_DEBUG_VERIFY(this->_M_can_advance(__n)
386 && this->_M_can_advance(__n+1),
387 _M_message(__msg_iter_subscript_oob)
388 ._M_iterator(*this)._M_integer(__n));
389 return base()[__n];
392 _Safe_iterator&
393 operator+=(const difference_type& __n) _GLIBCXX_NOEXCEPT
395 _GLIBCXX_DEBUG_VERIFY(this->_M_can_advance(__n),
396 _M_message(__msg_advance_oob)
397 ._M_iterator(*this)._M_integer(__n));
398 __gnu_cxx::__scoped_lock __l(this->_M_get_mutex());
399 base() += __n;
400 return *this;
403 _Safe_iterator
404 operator+(const difference_type& __n) const _GLIBCXX_NOEXCEPT
406 _GLIBCXX_DEBUG_VERIFY(this->_M_can_advance(__n),
407 _M_message(__msg_advance_oob)
408 ._M_iterator(*this)._M_integer(__n));
409 return _Safe_iterator(base() + __n, this->_M_sequence);
412 _Safe_iterator&
413 operator-=(const difference_type& __n) _GLIBCXX_NOEXCEPT
415 _GLIBCXX_DEBUG_VERIFY(this->_M_can_advance(-__n),
416 _M_message(__msg_retreat_oob)
417 ._M_iterator(*this)._M_integer(__n));
418 __gnu_cxx::__scoped_lock __l(this->_M_get_mutex());
419 base() -= __n;
420 return *this;
423 _Safe_iterator
424 operator-(const difference_type& __n) const _GLIBCXX_NOEXCEPT
426 _GLIBCXX_DEBUG_VERIFY(this->_M_can_advance(-__n),
427 _M_message(__msg_retreat_oob)
428 ._M_iterator(*this)._M_integer(__n));
429 return _Safe_iterator(base() - __n, this->_M_sequence);
432 // ------ Utilities ------
434 * @brief Return the underlying iterator
436 _Iterator&
437 base() _GLIBCXX_NOEXCEPT { return *this; }
439 const _Iterator&
440 base() const _GLIBCXX_NOEXCEPT { return *this; }
443 * @brief Conversion to underlying non-debug iterator to allow
444 * better interaction with non-debug containers.
446 operator _Iterator() const _GLIBCXX_NOEXCEPT { return *this; }
448 /** Attach iterator to the given sequence. */
449 void
450 _M_attach(_Safe_sequence_base* __seq)
451 { _Safe_base::_M_attach(__seq, _M_constant()); }
453 /** Likewise, but not thread-safe. */
454 void
455 _M_attach_single(_Safe_sequence_base* __seq)
456 { _Safe_base::_M_attach_single(__seq, _M_constant()); }
458 /// Is the iterator dereferenceable?
459 bool
460 _M_dereferenceable() const
461 { return !this->_M_singular() && !_M_is_end() && !_M_is_before_begin(); }
463 /// Is the iterator before a dereferenceable one?
464 bool
465 _M_before_dereferenceable() const
467 if (this->_M_incrementable())
469 _Iterator __base = base();
470 return ++__base != _M_get_sequence()->_M_base().end();
472 return false;
475 /// Is the iterator incrementable?
476 bool
477 _M_incrementable() const
478 { return !this->_M_singular() && !_M_is_end(); }
480 // Is the iterator decrementable?
481 bool
482 _M_decrementable() const { return !_M_singular() && !_M_is_begin(); }
484 // Can we advance the iterator @p __n steps (@p __n may be negative)
485 bool
486 _M_can_advance(const difference_type& __n) const;
488 // Is the iterator range [*this, __rhs) valid?
489 bool
490 _M_valid_range(const _Safe_iterator& __rhs) const;
492 // The sequence this iterator references.
493 typename
494 __gnu_cxx::__conditional_type<std::__are_same<_Const_iterator,
495 _Safe_iterator>::__value,
496 const _Sequence*,
497 _Sequence*>::__type
498 _M_get_sequence() const
499 { return static_cast<_Sequence*>(_M_sequence); }
501 /// Is this iterator equal to the sequence's begin() iterator?
502 bool
503 _M_is_begin() const
504 { return base() == _M_get_sequence()->_M_base().begin(); }
506 /// Is this iterator equal to the sequence's end() iterator?
507 bool
508 _M_is_end() const
509 { return base() == _M_get_sequence()->_M_base().end(); }
511 /// Is this iterator equal to the sequence's before_begin() iterator if
512 /// any?
513 bool
514 _M_is_before_begin() const
515 { return _BeforeBeginHelper<_Sequence>::_S_Is(*this); }
517 /// Is this iterator equal to the sequence's before_begin() iterator if
518 /// any or begin() otherwise?
519 bool
520 _M_is_beginnest() const
521 { return _BeforeBeginHelper<_Sequence>::_S_Is_Beginnest(*this); }
524 template<typename _IteratorL, typename _IteratorR, typename _Sequence>
525 inline bool
526 operator==(const _Safe_iterator<_IteratorL, _Sequence>& __lhs,
527 const _Safe_iterator<_IteratorR, _Sequence>& __rhs)
528 _GLIBCXX_NOEXCEPT
530 _GLIBCXX_DEBUG_VERIFY(! __lhs._M_singular() && ! __rhs._M_singular(),
531 _M_message(__msg_iter_compare_bad)
532 ._M_iterator(__lhs, "lhs")
533 ._M_iterator(__rhs, "rhs"));
534 _GLIBCXX_DEBUG_VERIFY(__lhs._M_can_compare(__rhs),
535 _M_message(__msg_compare_different)
536 ._M_iterator(__lhs, "lhs")
537 ._M_iterator(__rhs, "rhs"));
538 return __lhs.base() == __rhs.base();
541 template<typename _Iterator, typename _Sequence>
542 inline bool
543 operator==(const _Safe_iterator<_Iterator, _Sequence>& __lhs,
544 const _Safe_iterator<_Iterator, _Sequence>& __rhs)
545 _GLIBCXX_NOEXCEPT
547 _GLIBCXX_DEBUG_VERIFY(! __lhs._M_singular() && ! __rhs._M_singular(),
548 _M_message(__msg_iter_compare_bad)
549 ._M_iterator(__lhs, "lhs")
550 ._M_iterator(__rhs, "rhs"));
551 _GLIBCXX_DEBUG_VERIFY(__lhs._M_can_compare(__rhs),
552 _M_message(__msg_compare_different)
553 ._M_iterator(__lhs, "lhs")
554 ._M_iterator(__rhs, "rhs"));
555 return __lhs.base() == __rhs.base();
558 template<typename _IteratorL, typename _IteratorR, typename _Sequence>
559 inline bool
560 operator!=(const _Safe_iterator<_IteratorL, _Sequence>& __lhs,
561 const _Safe_iterator<_IteratorR, _Sequence>& __rhs)
562 _GLIBCXX_NOEXCEPT
564 _GLIBCXX_DEBUG_VERIFY(! __lhs._M_singular() && ! __rhs._M_singular(),
565 _M_message(__msg_iter_compare_bad)
566 ._M_iterator(__lhs, "lhs")
567 ._M_iterator(__rhs, "rhs"));
568 _GLIBCXX_DEBUG_VERIFY(__lhs._M_can_compare(__rhs),
569 _M_message(__msg_compare_different)
570 ._M_iterator(__lhs, "lhs")
571 ._M_iterator(__rhs, "rhs"));
572 return __lhs.base() != __rhs.base();
575 template<typename _Iterator, typename _Sequence>
576 inline bool
577 operator!=(const _Safe_iterator<_Iterator, _Sequence>& __lhs,
578 const _Safe_iterator<_Iterator, _Sequence>& __rhs)
579 _GLIBCXX_NOEXCEPT
581 _GLIBCXX_DEBUG_VERIFY(! __lhs._M_singular() && ! __rhs._M_singular(),
582 _M_message(__msg_iter_compare_bad)
583 ._M_iterator(__lhs, "lhs")
584 ._M_iterator(__rhs, "rhs"));
585 _GLIBCXX_DEBUG_VERIFY(__lhs._M_can_compare(__rhs),
586 _M_message(__msg_compare_different)
587 ._M_iterator(__lhs, "lhs")
588 ._M_iterator(__rhs, "rhs"));
589 return __lhs.base() != __rhs.base();
592 template<typename _IteratorL, typename _IteratorR, typename _Sequence>
593 inline bool
594 operator<(const _Safe_iterator<_IteratorL, _Sequence>& __lhs,
595 const _Safe_iterator<_IteratorR, _Sequence>& __rhs)
596 _GLIBCXX_NOEXCEPT
598 _GLIBCXX_DEBUG_VERIFY(! __lhs._M_singular() && ! __rhs._M_singular(),
599 _M_message(__msg_iter_order_bad)
600 ._M_iterator(__lhs, "lhs")
601 ._M_iterator(__rhs, "rhs"));
602 _GLIBCXX_DEBUG_VERIFY(__lhs._M_can_compare(__rhs),
603 _M_message(__msg_order_different)
604 ._M_iterator(__lhs, "lhs")
605 ._M_iterator(__rhs, "rhs"));
606 return __lhs.base() < __rhs.base();
609 template<typename _Iterator, typename _Sequence>
610 inline bool
611 operator<(const _Safe_iterator<_Iterator, _Sequence>& __lhs,
612 const _Safe_iterator<_Iterator, _Sequence>& __rhs)
613 _GLIBCXX_NOEXCEPT
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();
626 template<typename _IteratorL, typename _IteratorR, typename _Sequence>
627 inline bool
628 operator<=(const _Safe_iterator<_IteratorL, _Sequence>& __lhs,
629 const _Safe_iterator<_IteratorR, _Sequence>& __rhs)
630 _GLIBCXX_NOEXCEPT
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();
643 template<typename _Iterator, typename _Sequence>
644 inline bool
645 operator<=(const _Safe_iterator<_Iterator, _Sequence>& __lhs,
646 const _Safe_iterator<_Iterator, _Sequence>& __rhs)
647 _GLIBCXX_NOEXCEPT
649 _GLIBCXX_DEBUG_VERIFY(! __lhs._M_singular() && ! __rhs._M_singular(),
650 _M_message(__msg_iter_order_bad)
651 ._M_iterator(__lhs, "lhs")
652 ._M_iterator(__rhs, "rhs"));
653 _GLIBCXX_DEBUG_VERIFY(__lhs._M_can_compare(__rhs),
654 _M_message(__msg_order_different)
655 ._M_iterator(__lhs, "lhs")
656 ._M_iterator(__rhs, "rhs"));
657 return __lhs.base() <= __rhs.base();
660 template<typename _IteratorL, typename _IteratorR, typename _Sequence>
661 inline bool
662 operator>(const _Safe_iterator<_IteratorL, _Sequence>& __lhs,
663 const _Safe_iterator<_IteratorR, _Sequence>& __rhs)
664 _GLIBCXX_NOEXCEPT
666 _GLIBCXX_DEBUG_VERIFY(! __lhs._M_singular() && ! __rhs._M_singular(),
667 _M_message(__msg_iter_order_bad)
668 ._M_iterator(__lhs, "lhs")
669 ._M_iterator(__rhs, "rhs"));
670 _GLIBCXX_DEBUG_VERIFY(__lhs._M_can_compare(__rhs),
671 _M_message(__msg_order_different)
672 ._M_iterator(__lhs, "lhs")
673 ._M_iterator(__rhs, "rhs"));
674 return __lhs.base() > __rhs.base();
677 template<typename _Iterator, typename _Sequence>
678 inline bool
679 operator>(const _Safe_iterator<_Iterator, _Sequence>& __lhs,
680 const _Safe_iterator<_Iterator, _Sequence>& __rhs)
681 _GLIBCXX_NOEXCEPT
683 _GLIBCXX_DEBUG_VERIFY(! __lhs._M_singular() && ! __rhs._M_singular(),
684 _M_message(__msg_iter_order_bad)
685 ._M_iterator(__lhs, "lhs")
686 ._M_iterator(__rhs, "rhs"));
687 _GLIBCXX_DEBUG_VERIFY(__lhs._M_can_compare(__rhs),
688 _M_message(__msg_order_different)
689 ._M_iterator(__lhs, "lhs")
690 ._M_iterator(__rhs, "rhs"));
691 return __lhs.base() > __rhs.base();
694 template<typename _IteratorL, typename _IteratorR, typename _Sequence>
695 inline bool
696 operator>=(const _Safe_iterator<_IteratorL, _Sequence>& __lhs,
697 const _Safe_iterator<_IteratorR, _Sequence>& __rhs)
698 _GLIBCXX_NOEXCEPT
700 _GLIBCXX_DEBUG_VERIFY(! __lhs._M_singular() && ! __rhs._M_singular(),
701 _M_message(__msg_iter_order_bad)
702 ._M_iterator(__lhs, "lhs")
703 ._M_iterator(__rhs, "rhs"));
704 _GLIBCXX_DEBUG_VERIFY(__lhs._M_can_compare(__rhs),
705 _M_message(__msg_order_different)
706 ._M_iterator(__lhs, "lhs")
707 ._M_iterator(__rhs, "rhs"));
708 return __lhs.base() >= __rhs.base();
711 template<typename _Iterator, typename _Sequence>
712 inline bool
713 operator>=(const _Safe_iterator<_Iterator, _Sequence>& __lhs,
714 const _Safe_iterator<_Iterator, _Sequence>& __rhs)
715 _GLIBCXX_NOEXCEPT
717 _GLIBCXX_DEBUG_VERIFY(! __lhs._M_singular() && ! __rhs._M_singular(),
718 _M_message(__msg_iter_order_bad)
719 ._M_iterator(__lhs, "lhs")
720 ._M_iterator(__rhs, "rhs"));
721 _GLIBCXX_DEBUG_VERIFY(__lhs._M_can_compare(__rhs),
722 _M_message(__msg_order_different)
723 ._M_iterator(__lhs, "lhs")
724 ._M_iterator(__rhs, "rhs"));
725 return __lhs.base() >= __rhs.base();
728 // _GLIBCXX_RESOLVE_LIB_DEFECTS
729 // According to the resolution of DR179 not only the various comparison
730 // operators but also operator- must accept mixed iterator/const_iterator
731 // parameters.
732 template<typename _IteratorL, typename _IteratorR, typename _Sequence>
733 inline typename _Safe_iterator<_IteratorL, _Sequence>::difference_type
734 operator-(const _Safe_iterator<_IteratorL, _Sequence>& __lhs,
735 const _Safe_iterator<_IteratorR, _Sequence>& __rhs)
736 _GLIBCXX_NOEXCEPT
738 _GLIBCXX_DEBUG_VERIFY(! __lhs._M_singular() && ! __rhs._M_singular(),
739 _M_message(__msg_distance_bad)
740 ._M_iterator(__lhs, "lhs")
741 ._M_iterator(__rhs, "rhs"));
742 _GLIBCXX_DEBUG_VERIFY(__lhs._M_can_compare(__rhs),
743 _M_message(__msg_distance_different)
744 ._M_iterator(__lhs, "lhs")
745 ._M_iterator(__rhs, "rhs"));
746 return __lhs.base() - __rhs.base();
749 template<typename _Iterator, typename _Sequence>
750 inline typename _Safe_iterator<_Iterator, _Sequence>::difference_type
751 operator-(const _Safe_iterator<_Iterator, _Sequence>& __lhs,
752 const _Safe_iterator<_Iterator, _Sequence>& __rhs)
753 _GLIBCXX_NOEXCEPT
755 _GLIBCXX_DEBUG_VERIFY(! __lhs._M_singular() && ! __rhs._M_singular(),
756 _M_message(__msg_distance_bad)
757 ._M_iterator(__lhs, "lhs")
758 ._M_iterator(__rhs, "rhs"));
759 _GLIBCXX_DEBUG_VERIFY(__lhs._M_can_compare(__rhs),
760 _M_message(__msg_distance_different)
761 ._M_iterator(__lhs, "lhs")
762 ._M_iterator(__rhs, "rhs"));
763 return __lhs.base() - __rhs.base();
766 template<typename _Iterator, typename _Sequence>
767 inline _Safe_iterator<_Iterator, _Sequence>
768 operator+(typename _Safe_iterator<_Iterator,_Sequence>::difference_type __n,
769 const _Safe_iterator<_Iterator, _Sequence>& __i) _GLIBCXX_NOEXCEPT
770 { return __i + __n; }
771 } // namespace __gnu_debug
773 #include <debug/safe_iterator.tcc>
775 #endif