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