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