1 // Safe iterator implementation -*- C++ -*-
4 // Free Software Foundation, Inc.
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 2, or (at your option)
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.
17 // You should have received a copy of the GNU General Public License along
18 // with this library; see the file COPYING. If not, write to the Free
19 // Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307,
22 // As a special exception, you may use this file as part of a free software
23 // library without restriction. Specifically, if other files instantiate
24 // templates or use macros or inline functions from this file, or you compile
25 // this file and link it with other files to produce an executable, this
26 // file does not by itself cause the resulting executable to be covered by
27 // the GNU General Public License. This exception does not however
28 // invalidate any other reasons why the executable file might be covered by
29 // the GNU General Public License.
31 #ifndef _GLIBCXX_DEBUG_SAFE_ITERATOR_H
32 #define _GLIBCXX_DEBUG_SAFE_ITERATOR_H 1
34 #include <bits/stl_pair.h>
35 #include <debug/debug.h>
36 #include <debug/formatter.h>
37 #include <debug/safe_base.h>
41 /** Iterators that derive from _Safe_iterator_base but that aren't
42 * _Safe_iterators can be determined singular or non-singular via
43 * _Safe_iterator_base.
45 inline bool __check_singular_aux(const _Safe_iterator_base
* __x
)
46 { return __x
->_M_singular(); }
48 /** \brief Safe iterator wrapper.
50 * The class template %_Safe_iterator is a wrapper around an
51 * iterator that tracks the iterator's movement among sequences and
52 * checks that operations performed on the "safe" iterator are
53 * legal. In additional to the basic iterator operations (which are
54 * validated, and then passed to the underlying iterator),
55 * %_Safe_iterator has member functions for iterator invalidation,
56 * attaching/detaching the iterator from sequences, and querying
57 * the iterator's state.
59 template<typename _Iterator
, typename _Sequence
>
60 class _Safe_iterator
: public _Safe_iterator_base
62 typedef _Safe_iterator _Self
;
64 /** The precision to which we can calculate the distance between
67 enum _Distance_precision
69 __dp_equality
, //< Can compare iterator equality, only
70 __dp_sign
, //< Can determine equality and ordering
71 __dp_exact
//< Can determine distance precisely
74 /// The underlying iterator
77 /// Determine if this is a constant iterator.
81 typedef typename
_Sequence::const_iterator const_iterator
;
82 return __is_same
<const_iterator
, _Safe_iterator
>::value
;
85 typedef iterator_traits
<_Iterator
> _Traits
;
88 typedef typename
_Traits::iterator_category iterator_category
;
89 typedef typename
_Traits::value_type value_type
;
90 typedef typename
_Traits::difference_type difference_type
;
91 typedef typename
_Traits::reference reference
;
92 typedef typename
_Traits::pointer pointer
;
94 /// @post the iterator is singular and unattached
95 _Safe_iterator() : _M_current() { }
98 * @brief Safe iterator construction from an unsafe iterator and
101 * @pre @p seq is not NULL
102 * @post this is not singular
104 _Safe_iterator(const _Iterator
& __i
, const _Sequence
* __seq
)
105 : _Safe_iterator_base(__seq
, _M_constant()), _M_current(__i
)
107 _GLIBCXX_DEBUG_VERIFY(! this->_M_singular(),
108 _M_message(__msg_init_singular
)
109 ._M_iterator(*this, "this"));
113 * @brief Copy construction.
114 * @pre @p x is not singular
116 _Safe_iterator(const _Safe_iterator
& __x
)
117 : _Safe_iterator_base(__x
, _M_constant()), _M_current(__x
._M_current
)
119 _GLIBCXX_DEBUG_VERIFY(!__x
._M_singular(),
120 _M_message(__msg_init_copy_singular
)
121 ._M_iterator(*this, "this")
122 ._M_iterator(__x
, "other"));
126 * @brief Converting constructor from a mutable iterator to a
129 * @pre @p x is not singular
131 template<typename _MutableIterator
>
132 _Safe_iterator(const _Safe_iterator
<_MutableIterator
, _Sequence
>& __x
)
133 : _Safe_iterator_base(__x
, _M_constant()), _M_current(__x
.base())
135 _GLIBCXX_DEBUG_VERIFY(!__x
._M_singular(),
136 _M_message(__msg_init_const_singular
)
137 ._M_iterator(*this, "this")
138 ._M_iterator(__x
, "other"));
142 * @brief Copy assignment.
143 * @pre @p x is not singular
146 operator=(const _Safe_iterator
& __x
)
148 _GLIBCXX_DEBUG_VERIFY(!__x
._M_singular(),
149 _M_message(__msg_copy_singular
)
150 ._M_iterator(*this, "this")
151 ._M_iterator(__x
, "other"));
152 _M_current
= __x
._M_current
;
153 this->_M_attach(static_cast<_Sequence
*>(__x
._M_sequence
));
158 * @brief Iterator dereference.
159 * @pre iterator is dereferenceable
165 _GLIBCXX_DEBUG_VERIFY(this->_M_dereferenceable(),
166 _M_message(__msg_bad_deref
)
167 ._M_iterator(*this, "this"));
172 * @brief Iterator dereference.
173 * @pre iterator is dereferenceable
174 * @todo Make this correct w.r.t. iterators that return proxies
175 * @todo Use addressof() instead of & operator
180 _GLIBCXX_DEBUG_VERIFY(this->_M_dereferenceable(),
181 _M_message(__msg_bad_deref
)
182 ._M_iterator(*this, "this"));
186 // ------ Input iterator requirements ------
188 * @brief Iterator preincrement
189 * @pre iterator is incrementable
194 _GLIBCXX_DEBUG_VERIFY(this->_M_incrementable(),
195 _M_message(__msg_bad_inc
)
196 ._M_iterator(*this, "this"));
202 * @brief Iterator postincrement
203 * @pre iterator is incrementable
208 _GLIBCXX_DEBUG_VERIFY(this->_M_incrementable(),
209 _M_message(__msg_bad_inc
)
210 ._M_iterator(*this, "this"));
211 _Safe_iterator
__tmp(*this);
216 // ------ Bidirectional iterator requirements ------
218 * @brief Iterator predecrement
219 * @pre iterator is decrementable
224 _GLIBCXX_DEBUG_VERIFY(this->_M_decrementable(),
225 _M_message(__msg_bad_dec
)
226 ._M_iterator(*this, "this"));
232 * @brief Iterator postdecrement
233 * @pre iterator is decrementable
238 _GLIBCXX_DEBUG_VERIFY(this->_M_decrementable(),
239 _M_message(__msg_bad_dec
)
240 ._M_iterator(*this, "this"));
241 _Safe_iterator
__tmp(*this);
246 // ------ Random access iterator requirements ------
248 operator[](const difference_type
& __n
) const
250 _GLIBCXX_DEBUG_VERIFY(this->_M_can_advance(__n
)
251 && this->_M_can_advance(__n
+1),
252 _M_message(__msg_iter_subscript_oob
)
253 ._M_iterator(*this)._M_integer(__n
));
255 return _M_current
[__n
];
259 operator+=(const difference_type
& __n
)
261 _GLIBCXX_DEBUG_VERIFY(this->_M_can_advance(__n
),
262 _M_message(__msg_advance_oob
)
263 ._M_iterator(*this)._M_integer(__n
));
269 operator+(const difference_type
& __n
) const
271 _Safe_iterator
__tmp(*this);
277 operator-=(const difference_type
& __n
)
279 _GLIBCXX_DEBUG_VERIFY(this->_M_can_advance(-__n
),
280 _M_message(__msg_retreat_oob
)
281 ._M_iterator(*this)._M_integer(__n
));
287 operator-(const difference_type
& __n
) const
289 _Safe_iterator
__tmp(*this);
294 // ------ Utilities ------
296 * @brief Return the underlying iterator
299 base() const { return _M_current
; }
302 * @brief Conversion to underlying non-debug iterator to allow
303 * better interaction with non-debug containers.
305 operator _Iterator() const { return _M_current
; }
307 /** Attach iterator to the given sequence. */
309 _M_attach(const _Sequence
* __seq
)
311 _Safe_iterator_base::_M_attach(const_cast<_Sequence
*>(__seq
),
315 /** Invalidate the iterator, making it singular. */
319 /// Is the iterator dereferenceable?
321 _M_dereferenceable() const
322 { return !this->_M_singular() && !_M_is_end(); }
324 /// Is the iterator incrementable?
326 _M_incrementable() const { return this->_M_dereferenceable(); }
328 // Is the iterator decrementable?
330 _M_decrementable() const { return !_M_singular() && !_M_is_begin(); }
332 // Can we advance the iterator @p __n steps (@p __n may be negative)
334 _M_can_advance(const difference_type
& __n
) const;
336 // Is the iterator range [*this, __rhs) valid?
337 template<typename _Other
>
339 _M_valid_range(const _Safe_iterator
<_Other
, _Sequence
>& __rhs
) const;
341 // The sequence this iterator references.
343 _M_get_sequence() const
344 { return static_cast<const _Sequence
*>(_M_sequence
); }
346 /** Determine the distance between two iterators with some known
349 template<typename _Iterator1
, typename _Iterator2
>
350 static pair
<difference_type
, _Distance_precision
>
351 _M_get_distance(const _Iterator1
& __lhs
, const _Iterator2
& __rhs
)
353 typedef typename iterator_traits
<_Iterator1
>::iterator_category
355 return _M_get_distance(__lhs
, __rhs
, _Category());
358 template<typename _Iterator1
, typename _Iterator2
>
359 static pair
<difference_type
, _Distance_precision
>
360 _M_get_distance(const _Iterator1
& __lhs
, const _Iterator2
& __rhs
,
361 std::random_access_iterator_tag
)
363 return std::make_pair(__rhs
.base() - __lhs
.base(), __dp_exact
);
366 template<typename _Iterator1
, typename _Iterator2
>
367 static pair
<difference_type
, _Distance_precision
>
368 _M_get_distance(const _Iterator1
& __lhs
, const _Iterator2
& __rhs
,
369 std::forward_iterator_tag
)
371 return std::make_pair(__lhs
.base() == __rhs
.base()? 0 : 1,
375 /// Is this iterator equal to the sequence's begin() iterator?
376 bool _M_is_begin() const
377 { return *this == static_cast<const _Sequence
*>(_M_sequence
)->begin(); }
379 /// Is this iterator equal to the sequence's end() iterator?
380 bool _M_is_end() const
381 { return *this == static_cast<const _Sequence
*>(_M_sequence
)->end(); }
384 template<typename _IteratorL
, typename _IteratorR
, typename _Sequence
>
386 operator==(const _Safe_iterator
<_IteratorL
, _Sequence
>& __lhs
,
387 const _Safe_iterator
<_IteratorR
, _Sequence
>& __rhs
)
389 _GLIBCXX_DEBUG_VERIFY(! __lhs
._M_singular() && ! __rhs
._M_singular(),
390 _M_message(__msg_iter_compare_bad
)
391 ._M_iterator(__lhs
, "lhs")
392 ._M_iterator(__rhs
, "rhs"));
393 _GLIBCXX_DEBUG_VERIFY(__lhs
._M_can_compare(__rhs
),
394 _M_message(__msg_compare_different
)
395 ._M_iterator(__lhs
, "lhs")
396 ._M_iterator(__rhs
, "rhs"));
397 return __lhs
.base() == __rhs
.base();
400 template<typename _Iterator
, typename _Sequence
>
402 operator==(const _Safe_iterator
<_Iterator
, _Sequence
>& __lhs
,
403 const _Safe_iterator
<_Iterator
, _Sequence
>& __rhs
)
405 _GLIBCXX_DEBUG_VERIFY(! __lhs
._M_singular() && ! __rhs
._M_singular(),
406 _M_message(__msg_iter_compare_bad
)
407 ._M_iterator(__lhs
, "lhs")
408 ._M_iterator(__rhs
, "rhs"));
409 _GLIBCXX_DEBUG_VERIFY(__lhs
._M_can_compare(__rhs
),
410 _M_message(__msg_compare_different
)
411 ._M_iterator(__lhs
, "lhs")
412 ._M_iterator(__rhs
, "rhs"));
413 return __lhs
.base() == __rhs
.base();
416 template<typename _IteratorL
, typename _IteratorR
, typename _Sequence
>
418 operator!=(const _Safe_iterator
<_IteratorL
, _Sequence
>& __lhs
,
419 const _Safe_iterator
<_IteratorR
, _Sequence
>& __rhs
)
421 _GLIBCXX_DEBUG_VERIFY(! __lhs
._M_singular() && ! __rhs
._M_singular(),
422 _M_message(__msg_iter_compare_bad
)
423 ._M_iterator(__lhs
, "lhs")
424 ._M_iterator(__rhs
, "rhs"));
425 _GLIBCXX_DEBUG_VERIFY(__lhs
._M_can_compare(__rhs
),
426 _M_message(__msg_compare_different
)
427 ._M_iterator(__lhs
, "lhs")
428 ._M_iterator(__rhs
, "rhs"));
429 return __lhs
.base() != __rhs
.base();
432 template<typename _Iterator
, typename _Sequence
>
434 operator!=(const _Safe_iterator
<_Iterator
, _Sequence
>& __lhs
,
435 const _Safe_iterator
<_Iterator
, _Sequence
>& __rhs
)
437 _GLIBCXX_DEBUG_VERIFY(! __lhs
._M_singular() && ! __rhs
._M_singular(),
438 _M_message(__msg_iter_compare_bad
)
439 ._M_iterator(__lhs
, "lhs")
440 ._M_iterator(__rhs
, "rhs"));
441 _GLIBCXX_DEBUG_VERIFY(__lhs
._M_can_compare(__rhs
),
442 _M_message(__msg_compare_different
)
443 ._M_iterator(__lhs
, "lhs")
444 ._M_iterator(__rhs
, "rhs"));
445 return __lhs
.base() != __rhs
.base();
448 template<typename _IteratorL
, typename _IteratorR
, typename _Sequence
>
450 operator<(const _Safe_iterator
<_IteratorL
, _Sequence
>& __lhs
,
451 const _Safe_iterator
<_IteratorR
, _Sequence
>& __rhs
)
453 _GLIBCXX_DEBUG_VERIFY(! __lhs
._M_singular() && ! __rhs
._M_singular(),
454 _M_message(__msg_iter_order_bad
)
455 ._M_iterator(__lhs
, "lhs")
456 ._M_iterator(__rhs
, "rhs"));
457 _GLIBCXX_DEBUG_VERIFY(__lhs
._M_can_compare(__rhs
),
458 _M_message(__msg_order_different
)
459 ._M_iterator(__lhs
, "lhs")
460 ._M_iterator(__rhs
, "rhs"));
461 return __lhs
.base() < __rhs
.base();
464 template<typename _Iterator
, typename _Sequence
>
466 operator<(const _Safe_iterator
<_Iterator
, _Sequence
>& __lhs
,
467 const _Safe_iterator
<_Iterator
, _Sequence
>& __rhs
)
469 _GLIBCXX_DEBUG_VERIFY(! __lhs
._M_singular() && ! __rhs
._M_singular(),
470 _M_message(__msg_iter_order_bad
)
471 ._M_iterator(__lhs
, "lhs")
472 ._M_iterator(__rhs
, "rhs"));
473 _GLIBCXX_DEBUG_VERIFY(__lhs
._M_can_compare(__rhs
),
474 _M_message(__msg_order_different
)
475 ._M_iterator(__lhs
, "lhs")
476 ._M_iterator(__rhs
, "rhs"));
477 return __lhs
.base() < __rhs
.base();
480 template<typename _IteratorL
, typename _IteratorR
, typename _Sequence
>
482 operator<=(const _Safe_iterator
<_IteratorL
, _Sequence
>& __lhs
,
483 const _Safe_iterator
<_IteratorR
, _Sequence
>& __rhs
)
485 _GLIBCXX_DEBUG_VERIFY(! __lhs
._M_singular() && ! __rhs
._M_singular(),
486 _M_message(__msg_iter_order_bad
)
487 ._M_iterator(__lhs
, "lhs")
488 ._M_iterator(__rhs
, "rhs"));
489 _GLIBCXX_DEBUG_VERIFY(__lhs
._M_can_compare(__rhs
),
490 _M_message(__msg_order_different
)
491 ._M_iterator(__lhs
, "lhs")
492 ._M_iterator(__rhs
, "rhs"));
493 return __lhs
.base() <= __rhs
.base();
496 template<typename _Iterator
, typename _Sequence
>
498 operator<=(const _Safe_iterator
<_Iterator
, _Sequence
>& __lhs
,
499 const _Safe_iterator
<_Iterator
, _Sequence
>& __rhs
)
501 _GLIBCXX_DEBUG_VERIFY(! __lhs
._M_singular() && ! __rhs
._M_singular(),
502 _M_message(__msg_iter_order_bad
)
503 ._M_iterator(__lhs
, "lhs")
504 ._M_iterator(__rhs
, "rhs"));
505 _GLIBCXX_DEBUG_VERIFY(__lhs
._M_can_compare(__rhs
),
506 _M_message(__msg_order_different
)
507 ._M_iterator(__lhs
, "lhs")
508 ._M_iterator(__rhs
, "rhs"));
509 return __lhs
.base() <= __rhs
.base();
512 template<typename _IteratorL
, typename _IteratorR
, typename _Sequence
>
514 operator>(const _Safe_iterator
<_IteratorL
, _Sequence
>& __lhs
,
515 const _Safe_iterator
<_IteratorR
, _Sequence
>& __rhs
)
517 _GLIBCXX_DEBUG_VERIFY(! __lhs
._M_singular() && ! __rhs
._M_singular(),
518 _M_message(__msg_iter_order_bad
)
519 ._M_iterator(__lhs
, "lhs")
520 ._M_iterator(__rhs
, "rhs"));
521 _GLIBCXX_DEBUG_VERIFY(__lhs
._M_can_compare(__rhs
),
522 _M_message(__msg_order_different
)
523 ._M_iterator(__lhs
, "lhs")
524 ._M_iterator(__rhs
, "rhs"));
525 return __lhs
.base() > __rhs
.base();
528 template<typename _Iterator
, typename _Sequence
>
530 operator>(const _Safe_iterator
<_Iterator
, _Sequence
>& __lhs
,
531 const _Safe_iterator
<_Iterator
, _Sequence
>& __rhs
)
533 _GLIBCXX_DEBUG_VERIFY(! __lhs
._M_singular() && ! __rhs
._M_singular(),
534 _M_message(__msg_iter_order_bad
)
535 ._M_iterator(__lhs
, "lhs")
536 ._M_iterator(__rhs
, "rhs"));
537 _GLIBCXX_DEBUG_VERIFY(__lhs
._M_can_compare(__rhs
),
538 _M_message(__msg_order_different
)
539 ._M_iterator(__lhs
, "lhs")
540 ._M_iterator(__rhs
, "rhs"));
541 return __lhs
.base() > __rhs
.base();
544 template<typename _IteratorL
, typename _IteratorR
, typename _Sequence
>
546 operator>=(const _Safe_iterator
<_IteratorL
, _Sequence
>& __lhs
,
547 const _Safe_iterator
<_IteratorR
, _Sequence
>& __rhs
)
549 _GLIBCXX_DEBUG_VERIFY(! __lhs
._M_singular() && ! __rhs
._M_singular(),
550 _M_message(__msg_iter_order_bad
)
551 ._M_iterator(__lhs
, "lhs")
552 ._M_iterator(__rhs
, "rhs"));
553 _GLIBCXX_DEBUG_VERIFY(__lhs
._M_can_compare(__rhs
),
554 _M_message(__msg_order_different
)
555 ._M_iterator(__lhs
, "lhs")
556 ._M_iterator(__rhs
, "rhs"));
557 return __lhs
.base() >= __rhs
.base();
560 template<typename _Iterator
, typename _Sequence
>
562 operator>=(const _Safe_iterator
<_Iterator
, _Sequence
>& __lhs
,
563 const _Safe_iterator
<_Iterator
, _Sequence
>& __rhs
)
565 _GLIBCXX_DEBUG_VERIFY(! __lhs
._M_singular() && ! __rhs
._M_singular(),
566 _M_message(__msg_iter_order_bad
)
567 ._M_iterator(__lhs
, "lhs")
568 ._M_iterator(__rhs
, "rhs"));
569 _GLIBCXX_DEBUG_VERIFY(__lhs
._M_can_compare(__rhs
),
570 _M_message(__msg_order_different
)
571 ._M_iterator(__lhs
, "lhs")
572 ._M_iterator(__rhs
, "rhs"));
573 return __lhs
.base() >= __rhs
.base();
576 // _GLIBCXX_RESOLVE_LIB_DEFECTS
577 // According to the resolution of DR179 not only the various comparison
578 // operators but also operator- must accept mixed iterator/const_iterator
580 template<typename _IteratorL
, typename _IteratorR
, typename _Sequence
>
581 inline typename _Safe_iterator
<_IteratorL
, _Sequence
>::difference_type
582 operator-(const _Safe_iterator
<_IteratorL
, _Sequence
>& __lhs
,
583 const _Safe_iterator
<_IteratorR
, _Sequence
>& __rhs
)
585 _GLIBCXX_DEBUG_VERIFY(! __lhs
._M_singular() && ! __rhs
._M_singular(),
586 _M_message(__msg_distance_bad
)
587 ._M_iterator(__lhs
, "lhs")
588 ._M_iterator(__rhs
, "rhs"));
589 _GLIBCXX_DEBUG_VERIFY(__lhs
._M_can_compare(__rhs
),
590 _M_message(__msg_distance_different
)
591 ._M_iterator(__lhs
, "lhs")
592 ._M_iterator(__rhs
, "rhs"));
593 return __lhs
.base() - __rhs
.base();
596 template<typename _Iterator
, typename _Sequence
>
597 inline _Safe_iterator
<_Iterator
, _Sequence
>
598 operator+(typename _Safe_iterator
<_Iterator
,_Sequence
>::difference_type __n
,
599 const _Safe_iterator
<_Iterator
, _Sequence
>& __i
)
600 { return __i
+ __n
; }
601 } // namespace __gnu_debug
603 #ifndef _GLIBCXX_EXPORT_TEMPLATE
604 # include <debug/safe_iterator.tcc>