re PR libstdc++/60333 (type_traits make_signed, make_unsigned missing support for...
[gcc.git] / libstdc++-v3 / include / debug / safe_iterator.h
1 // Safe iterator implementation -*- C++ -*-
2
3 // Copyright (C) 2003-2015 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 * 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.
117 */
118 template<typename _Iterator, typename _Sequence>
119 class _Safe_iterator
120 : private _Iterator,
121 public _Safe_iterator_base
122 {
123 typedef _Iterator _Iter_base;
124 typedef _Safe_iterator_base _Safe_base;
125 typedef typename _Sequence::const_iterator _Const_iterator;
126
127 /// Determine if this is a constant iterator.
128 bool
129 _M_constant() const
130 { return std::__are_same<_Const_iterator, _Safe_iterator>::__value; }
131
132 typedef std::iterator_traits<_Iterator> _Traits;
133
134 struct _Attach_single
135 { };
136
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); }
142
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;
150
151 /// @post the iterator is singular and unattached
152 _Safe_iterator() _GLIBCXX_NOEXCEPT : _Iter_base() { }
153
154 /**
155 * @brief Safe iterator construction from an unsafe iterator and
156 * its sequence.
157 *
158 * @pre @p seq is not NULL
159 * @post this is not singular
160 */
161 _Safe_iterator(const _Iterator& __i, const _Safe_sequence_base* __seq)
162 _GLIBCXX_NOEXCEPT
163 : _Iter_base(__i), _Safe_base(__seq, _M_constant())
164 {
165 _GLIBCXX_DEBUG_VERIFY(!this->_M_singular(),
166 _M_message(__msg_init_singular)
167 ._M_iterator(*this, "this"));
168 }
169
170 /**
171 * @brief Copy construction.
172 */
173 _Safe_iterator(const _Safe_iterator& __x) _GLIBCXX_NOEXCEPT
174 : _Iter_base(__x.base())
175 {
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);
184 }
185
186 #if __cplusplus >= 201103L
187 /**
188 * @brief Move construction.
189 * @post __x is singular and unattached
190 */
191 _Safe_iterator(_Safe_iterator&& __x) noexcept
192 : _Iter_base()
193 {
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);
203 }
204 #endif
205
206 /**
207 * @brief Converting constructor from a mutable iterator to a
208 * constant iterator.
209 */
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())
217 {
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);
226 }
227
228 /**
229 * @brief Copy assignment.
230 */
231 _Safe_iterator&
232 operator=(const _Safe_iterator& __x) _GLIBCXX_NOEXCEPT
233 {
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"));
241
242 if (this->_M_sequence && this->_M_sequence == __x._M_sequence)
243 {
244 __gnu_cxx::__scoped_lock __l(this->_M_get_mutex());
245 base() = __x.base();
246 _M_version = __x._M_sequence->_M_version;
247 }
248 else
249 {
250 _M_detach();
251 base() = __x.base();
252 _M_attach(__x._M_sequence);
253 }
254
255 return *this;
256 }
257
258 #if __cplusplus >= 201103L
259 /**
260 * @brief Move assignment.
261 * @post __x is singular and unattached
262 */
263 _Safe_iterator&
264 operator=(_Safe_iterator&& __x) noexcept
265 {
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"));
274
275 if (this->_M_sequence && this->_M_sequence == __x._M_sequence)
276 {
277 __gnu_cxx::__scoped_lock __l(this->_M_get_mutex());
278 base() = __x.base();
279 _M_version = __x._M_sequence->_M_version;
280 }
281 else
282 {
283 _M_detach();
284 base() = __x.base();
285 _M_attach(__x._M_sequence);
286 }
287
288 __x._M_detach();
289 __x.base() = _Iterator();
290 return *this;
291 }
292 #endif
293
294 /**
295 * @brief Iterator dereference.
296 * @pre iterator is dereferenceable
297 */
298 reference
299 operator*() const _GLIBCXX_NOEXCEPT
300 {
301 _GLIBCXX_DEBUG_VERIFY(this->_M_dereferenceable(),
302 _M_message(__msg_bad_deref)
303 ._M_iterator(*this, "this"));
304 return *base();
305 }
306
307 /**
308 * @brief Iterator dereference.
309 * @pre iterator is dereferenceable
310 * @todo Make this correct w.r.t. iterators that return proxies
311 */
312 pointer
313 operator->() const _GLIBCXX_NOEXCEPT
314 {
315 _GLIBCXX_DEBUG_VERIFY(this->_M_dereferenceable(),
316 _M_message(__msg_bad_deref)
317 ._M_iterator(*this, "this"));
318 return std::__addressof(*base());
319 }
320
321 // ------ Input iterator requirements ------
322 /**
323 * @brief Iterator preincrement
324 * @pre iterator is incrementable
325 */
326 _Safe_iterator&
327 operator++() _GLIBCXX_NOEXCEPT
328 {
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;
335 }
336
337 /**
338 * @brief Iterator postincrement
339 * @pre iterator is incrementable
340 */
341 _Safe_iterator
342 operator++(int) _GLIBCXX_NOEXCEPT
343 {
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());
349 }
350
351 // ------ Bidirectional iterator requirements ------
352 /**
353 * @brief Iterator predecrement
354 * @pre iterator is decrementable
355 */
356 _Safe_iterator&
357 operator--() _GLIBCXX_NOEXCEPT
358 {
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;
365 }
366
367 /**
368 * @brief Iterator postdecrement
369 * @pre iterator is decrementable
370 */
371 _Safe_iterator
372 operator--(int) _GLIBCXX_NOEXCEPT
373 {
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());
379 }
380
381 // ------ Random access iterator requirements ------
382 reference
383 operator[](const difference_type& __n) const _GLIBCXX_NOEXCEPT
384 {
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];
390 }
391
392 _Safe_iterator&
393 operator+=(const difference_type& __n) _GLIBCXX_NOEXCEPT
394 {
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;
401 }
402
403 _Safe_iterator
404 operator+(const difference_type& __n) const _GLIBCXX_NOEXCEPT
405 {
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);
410 }
411
412 _Safe_iterator&
413 operator-=(const difference_type& __n) _GLIBCXX_NOEXCEPT
414 {
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;
421 }
422
423 _Safe_iterator
424 operator-(const difference_type& __n) const _GLIBCXX_NOEXCEPT
425 {
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);
430 }
431
432 // ------ Utilities ------
433 /**
434 * @brief Return the underlying iterator
435 */
436 _Iterator&
437 base() _GLIBCXX_NOEXCEPT { return *this; }
438
439 const _Iterator&
440 base() const _GLIBCXX_NOEXCEPT { return *this; }
441
442 /**
443 * @brief Conversion to underlying non-debug iterator to allow
444 * better interaction with non-debug containers.
445 */
446 operator _Iterator() const _GLIBCXX_NOEXCEPT { return *this; }
447
448 /** Attach iterator to the given sequence. */
449 void
450 _M_attach(_Safe_sequence_base* __seq)
451 { _Safe_base::_M_attach(__seq, _M_constant()); }
452
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()); }
457
458 /// Is the iterator dereferenceable?
459 bool
460 _M_dereferenceable() const
461 { return !this->_M_singular() && !_M_is_end() && !_M_is_before_begin(); }
462
463 /// Is the iterator before a dereferenceable one?
464 bool
465 _M_before_dereferenceable() const
466 {
467 if (this->_M_incrementable())
468 {
469 _Iterator __base = base();
470 return ++__base != _M_get_sequence()->_M_base().end();
471 }
472 return false;
473 }
474
475 /// Is the iterator incrementable?
476 bool
477 _M_incrementable() const
478 { return !this->_M_singular() && !_M_is_end(); }
479
480 // Is the iterator decrementable?
481 bool
482 _M_decrementable() const { return !_M_singular() && !_M_is_begin(); }
483
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;
487
488 // Is the iterator range [*this, __rhs) valid?
489 bool
490 _M_valid_range(const _Safe_iterator& __rhs) const;
491
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); }
500
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(); }
505
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(); }
510
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); }
516
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); }
522 };
523
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
529 {
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();
539 }
540
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
546 {
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();
556 }
557
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
563 {
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();
573 }
574
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
580 {
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();
590 }
591
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
597 {
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();
607 }
608
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
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 _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
631 {
632 _GLIBCXX_DEBUG_VERIFY(! __lhs._M_singular() && ! __rhs._M_singular(),
633 _M_message(__msg_iter_order_bad)
634 ._M_iterator(__lhs, "lhs")
635 ._M_iterator(__rhs, "rhs"));
636 _GLIBCXX_DEBUG_VERIFY(__lhs._M_can_compare(__rhs),
637 _M_message(__msg_order_different)
638 ._M_iterator(__lhs, "lhs")
639 ._M_iterator(__rhs, "rhs"));
640 return __lhs.base() <= __rhs.base();
641 }
642
643 template<typename _Iterator, typename _Sequence>
644 inline bool
645 operator<=(const _Safe_iterator<_Iterator, _Sequence>& __lhs,
646 const _Safe_iterator<_Iterator, _Sequence>& __rhs)
647 _GLIBCXX_NOEXCEPT
648 {
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();
658 }
659
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
665 {
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();
675 }
676
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
682 {
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();
692 }
693
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
699 {
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();
709 }
710
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
716 {
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();
726 }
727
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
737 {
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();
747 }
748
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
754 {
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();
764 }
765
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
772
773 #include <debug/safe_iterator.tcc>
774
775 #endif