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