libstdc++

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