1 // Safe iterator implementation -*- C++ -*-
3 // Copyright (C) 2003, 2004, 2005
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, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
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 <debug/debug.h>
35 #include <debug/macros.h>
36 #include <debug/functions.h>
37 #include <debug/formatter.h>
38 #include <debug/safe_base.h>
39 #include <bits/stl_pair.h>
40 #include <bits/cpp_type_traits.h>
46 /** Iterators that derive from _Safe_iterator_base but that aren't
47 * _Safe_iterators can be determined singular or non-singular via
48 * _Safe_iterator_base.
51 __check_singular_aux(const _Safe_iterator_base
* __x
)
52 { return __x
->_M_singular(); }
54 /** \brief Safe iterator wrapper.
56 * The class template %_Safe_iterator is a wrapper around an
57 * iterator that tracks the iterator's movement among sequences and
58 * checks that operations performed on the "safe" iterator are
59 * legal. In additional to the basic iterator operations (which are
60 * validated, and then passed to the underlying iterator),
61 * %_Safe_iterator has member functions for iterator invalidation,
62 * attaching/detaching the iterator from sequences, and querying
63 * the iterator's state.
65 template<typename _Iterator
, typename _Sequence
>
66 class _Safe_iterator
: public _Safe_iterator_base
68 typedef _Safe_iterator _Self
;
70 /** The precision to which we can calculate the distance between
73 enum _Distance_precision
75 __dp_equality
, //< Can compare iterator equality, only
76 __dp_sign
, //< Can determine equality and ordering
77 __dp_exact
//< Can determine distance precisely
80 /// The underlying iterator
83 /// Determine if this is a constant iterator.
87 typedef typename
_Sequence::const_iterator const_iterator
;
88 return __is_same
<const_iterator
, _Safe_iterator
>::value
;
91 typedef iterator_traits
<_Iterator
> _Traits
;
94 typedef _Iterator _Base_iterator
;
95 typedef typename
_Traits::iterator_category iterator_category
;
96 typedef typename
_Traits::value_type value_type
;
97 typedef typename
_Traits::difference_type difference_type
;
98 typedef typename
_Traits::reference reference
;
99 typedef typename
_Traits::pointer pointer
;
101 /// @post the iterator is singular and unattached
102 _Safe_iterator() : _M_current() { }
105 * @brief Safe iterator construction from an unsafe iterator and
108 * @pre @p seq is not NULL
109 * @post this is not singular
111 _Safe_iterator(const _Iterator
& __i
, const _Sequence
* __seq
)
112 : _Safe_iterator_base(__seq
, _M_constant()), _M_current(__i
)
114 _GLIBCXX_DEBUG_VERIFY(! this->_M_singular(),
115 _M_message(__msg_init_singular
)
116 ._M_iterator(*this, "this"));
120 * @brief Copy construction.
121 * @pre @p x is not singular
123 _Safe_iterator(const _Safe_iterator
& __x
)
124 : _Safe_iterator_base(__x
, _M_constant()), _M_current(__x
._M_current
)
126 _GLIBCXX_DEBUG_VERIFY(!__x
._M_singular(),
127 _M_message(__msg_init_copy_singular
)
128 ._M_iterator(*this, "this")
129 ._M_iterator(__x
, "other"));
133 * @brief Converting constructor from a mutable iterator to a
136 * @pre @p x is not singular
138 template<typename _MutableIterator
>
140 const _Safe_iterator
<_MutableIterator
,
141 typename
std::__enable_if
<
143 (std::__are_same
<_MutableIterator
,
144 typename
_Sequence::iterator::_Base_iterator
>::__value
)
146 : _Safe_iterator_base(__x
, _M_constant()), _M_current(__x
.base())
148 _GLIBCXX_DEBUG_VERIFY(!__x
._M_singular(),
149 _M_message(__msg_init_const_singular
)
150 ._M_iterator(*this, "this")
151 ._M_iterator(__x
, "other"));
155 * @brief Copy assignment.
156 * @pre @p x is not singular
159 operator=(const _Safe_iterator
& __x
)
161 _GLIBCXX_DEBUG_VERIFY(!__x
._M_singular(),
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
));
171 * @brief Iterator dereference.
172 * @pre iterator is dereferenceable
178 _GLIBCXX_DEBUG_VERIFY(this->_M_dereferenceable(),
179 _M_message(__msg_bad_deref
)
180 ._M_iterator(*this, "this"));
185 * @brief Iterator dereference.
186 * @pre iterator is dereferenceable
187 * @todo Make this correct w.r.t. iterators that return proxies
188 * @todo Use addressof() instead of & operator
193 _GLIBCXX_DEBUG_VERIFY(this->_M_dereferenceable(),
194 _M_message(__msg_bad_deref
)
195 ._M_iterator(*this, "this"));
199 // ------ Input iterator requirements ------
201 * @brief Iterator preincrement
202 * @pre iterator is incrementable
207 _GLIBCXX_DEBUG_VERIFY(this->_M_incrementable(),
208 _M_message(__msg_bad_inc
)
209 ._M_iterator(*this, "this"));
215 * @brief Iterator postincrement
216 * @pre iterator is incrementable
221 _GLIBCXX_DEBUG_VERIFY(this->_M_incrementable(),
222 _M_message(__msg_bad_inc
)
223 ._M_iterator(*this, "this"));
224 _Safe_iterator
__tmp(*this);
229 // ------ Bidirectional iterator requirements ------
231 * @brief Iterator predecrement
232 * @pre iterator is decrementable
237 _GLIBCXX_DEBUG_VERIFY(this->_M_decrementable(),
238 _M_message(__msg_bad_dec
)
239 ._M_iterator(*this, "this"));
245 * @brief Iterator postdecrement
246 * @pre iterator is decrementable
251 _GLIBCXX_DEBUG_VERIFY(this->_M_decrementable(),
252 _M_message(__msg_bad_dec
)
253 ._M_iterator(*this, "this"));
254 _Safe_iterator
__tmp(*this);
259 // ------ Random access iterator requirements ------
261 operator[](const difference_type
& __n
) const
263 _GLIBCXX_DEBUG_VERIFY(this->_M_can_advance(__n
)
264 && this->_M_can_advance(__n
+1),
265 _M_message(__msg_iter_subscript_oob
)
266 ._M_iterator(*this)._M_integer(__n
));
268 return _M_current
[__n
];
272 operator+=(const difference_type
& __n
)
274 _GLIBCXX_DEBUG_VERIFY(this->_M_can_advance(__n
),
275 _M_message(__msg_advance_oob
)
276 ._M_iterator(*this)._M_integer(__n
));
282 operator+(const difference_type
& __n
) const
284 _Safe_iterator
__tmp(*this);
290 operator-=(const difference_type
& __n
)
292 _GLIBCXX_DEBUG_VERIFY(this->_M_can_advance(-__n
),
293 _M_message(__msg_retreat_oob
)
294 ._M_iterator(*this)._M_integer(__n
));
300 operator-(const difference_type
& __n
) const
302 _Safe_iterator
__tmp(*this);
307 // ------ Utilities ------
309 * @brief Return the underlying iterator
312 base() const { return _M_current
; }
315 * @brief Conversion to underlying non-debug iterator to allow
316 * better interaction with non-debug containers.
318 operator _Iterator() const { return _M_current
; }
320 /** Attach iterator to the given sequence. */
322 _M_attach(const _Sequence
* __seq
)
324 _Safe_iterator_base::_M_attach(const_cast<_Sequence
*>(__seq
),
328 /** Invalidate the iterator, making it singular. */
332 /// Is the iterator dereferenceable?
334 _M_dereferenceable() const
335 { return !this->_M_singular() && !_M_is_end(); }
337 /// Is the iterator incrementable?
339 _M_incrementable() const { return this->_M_dereferenceable(); }
341 // Is the iterator decrementable?
343 _M_decrementable() const { return !_M_singular() && !_M_is_begin(); }
345 // Can we advance the iterator @p __n steps (@p __n may be negative)
347 _M_can_advance(const difference_type
& __n
) const;
349 // Is the iterator range [*this, __rhs) valid?
350 template<typename _Other
>
352 _M_valid_range(const _Safe_iterator
<_Other
, _Sequence
>& __rhs
) const;
354 // The sequence this iterator references.
356 _M_get_sequence() const
357 { return static_cast<const _Sequence
*>(_M_sequence
); }
359 /** Determine the distance between two iterators with some known
362 template<typename _Iterator1
, typename _Iterator2
>
363 static pair
<difference_type
, _Distance_precision
>
364 _M_get_distance(const _Iterator1
& __lhs
, const _Iterator2
& __rhs
)
366 typedef typename iterator_traits
<_Iterator1
>::iterator_category
368 return _M_get_distance(__lhs
, __rhs
, _Category());
371 template<typename _Iterator1
, typename _Iterator2
>
372 static pair
<difference_type
, _Distance_precision
>
373 _M_get_distance(const _Iterator1
& __lhs
, const _Iterator2
& __rhs
,
374 std::random_access_iterator_tag
)
376 return std::make_pair(__rhs
.base() - __lhs
.base(), __dp_exact
);
379 template<typename _Iterator1
, typename _Iterator2
>
380 static pair
<difference_type
, _Distance_precision
>
381 _M_get_distance(const _Iterator1
& __lhs
, const _Iterator2
& __rhs
,
382 std::forward_iterator_tag
)
384 return std::make_pair(__lhs
.base() == __rhs
.base()? 0 : 1,
388 /// Is this iterator equal to the sequence's begin() iterator?
389 bool _M_is_begin() const
390 { return *this == static_cast<const _Sequence
*>(_M_sequence
)->begin(); }
392 /// Is this iterator equal to the sequence's end() iterator?
393 bool _M_is_end() const
394 { return *this == static_cast<const _Sequence
*>(_M_sequence
)->end(); }
397 template<typename _IteratorL
, typename _IteratorR
, typename _Sequence
>
399 operator==(const _Safe_iterator
<_IteratorL
, _Sequence
>& __lhs
,
400 const _Safe_iterator
<_IteratorR
, _Sequence
>& __rhs
)
402 _GLIBCXX_DEBUG_VERIFY(! __lhs
._M_singular() && ! __rhs
._M_singular(),
403 _M_message(__msg_iter_compare_bad
)
404 ._M_iterator(__lhs
, "lhs")
405 ._M_iterator(__rhs
, "rhs"));
406 _GLIBCXX_DEBUG_VERIFY(__lhs
._M_can_compare(__rhs
),
407 _M_message(__msg_compare_different
)
408 ._M_iterator(__lhs
, "lhs")
409 ._M_iterator(__rhs
, "rhs"));
410 return __lhs
.base() == __rhs
.base();
413 template<typename _Iterator
, typename _Sequence
>
415 operator==(const _Safe_iterator
<_Iterator
, _Sequence
>& __lhs
,
416 const _Safe_iterator
<_Iterator
, _Sequence
>& __rhs
)
418 _GLIBCXX_DEBUG_VERIFY(! __lhs
._M_singular() && ! __rhs
._M_singular(),
419 _M_message(__msg_iter_compare_bad
)
420 ._M_iterator(__lhs
, "lhs")
421 ._M_iterator(__rhs
, "rhs"));
422 _GLIBCXX_DEBUG_VERIFY(__lhs
._M_can_compare(__rhs
),
423 _M_message(__msg_compare_different
)
424 ._M_iterator(__lhs
, "lhs")
425 ._M_iterator(__rhs
, "rhs"));
426 return __lhs
.base() == __rhs
.base();
429 template<typename _IteratorL
, typename _IteratorR
, typename _Sequence
>
431 operator!=(const _Safe_iterator
<_IteratorL
, _Sequence
>& __lhs
,
432 const _Safe_iterator
<_IteratorR
, _Sequence
>& __rhs
)
434 _GLIBCXX_DEBUG_VERIFY(! __lhs
._M_singular() && ! __rhs
._M_singular(),
435 _M_message(__msg_iter_compare_bad
)
436 ._M_iterator(__lhs
, "lhs")
437 ._M_iterator(__rhs
, "rhs"));
438 _GLIBCXX_DEBUG_VERIFY(__lhs
._M_can_compare(__rhs
),
439 _M_message(__msg_compare_different
)
440 ._M_iterator(__lhs
, "lhs")
441 ._M_iterator(__rhs
, "rhs"));
442 return __lhs
.base() != __rhs
.base();
445 template<typename _Iterator
, typename _Sequence
>
447 operator!=(const _Safe_iterator
<_Iterator
, _Sequence
>& __lhs
,
448 const _Safe_iterator
<_Iterator
, _Sequence
>& __rhs
)
450 _GLIBCXX_DEBUG_VERIFY(! __lhs
._M_singular() && ! __rhs
._M_singular(),
451 _M_message(__msg_iter_compare_bad
)
452 ._M_iterator(__lhs
, "lhs")
453 ._M_iterator(__rhs
, "rhs"));
454 _GLIBCXX_DEBUG_VERIFY(__lhs
._M_can_compare(__rhs
),
455 _M_message(__msg_compare_different
)
456 ._M_iterator(__lhs
, "lhs")
457 ._M_iterator(__rhs
, "rhs"));
458 return __lhs
.base() != __rhs
.base();
461 template<typename _IteratorL
, typename _IteratorR
, typename _Sequence
>
463 operator<(const _Safe_iterator
<_IteratorL
, _Sequence
>& __lhs
,
464 const _Safe_iterator
<_IteratorR
, _Sequence
>& __rhs
)
466 _GLIBCXX_DEBUG_VERIFY(! __lhs
._M_singular() && ! __rhs
._M_singular(),
467 _M_message(__msg_iter_order_bad
)
468 ._M_iterator(__lhs
, "lhs")
469 ._M_iterator(__rhs
, "rhs"));
470 _GLIBCXX_DEBUG_VERIFY(__lhs
._M_can_compare(__rhs
),
471 _M_message(__msg_order_different
)
472 ._M_iterator(__lhs
, "lhs")
473 ._M_iterator(__rhs
, "rhs"));
474 return __lhs
.base() < __rhs
.base();
477 template<typename _Iterator
, typename _Sequence
>
479 operator<(const _Safe_iterator
<_Iterator
, _Sequence
>& __lhs
,
480 const _Safe_iterator
<_Iterator
, _Sequence
>& __rhs
)
482 _GLIBCXX_DEBUG_VERIFY(! __lhs
._M_singular() && ! __rhs
._M_singular(),
483 _M_message(__msg_iter_order_bad
)
484 ._M_iterator(__lhs
, "lhs")
485 ._M_iterator(__rhs
, "rhs"));
486 _GLIBCXX_DEBUG_VERIFY(__lhs
._M_can_compare(__rhs
),
487 _M_message(__msg_order_different
)
488 ._M_iterator(__lhs
, "lhs")
489 ._M_iterator(__rhs
, "rhs"));
490 return __lhs
.base() < __rhs
.base();
493 template<typename _IteratorL
, typename _IteratorR
, typename _Sequence
>
495 operator<=(const _Safe_iterator
<_IteratorL
, _Sequence
>& __lhs
,
496 const _Safe_iterator
<_IteratorR
, _Sequence
>& __rhs
)
498 _GLIBCXX_DEBUG_VERIFY(! __lhs
._M_singular() && ! __rhs
._M_singular(),
499 _M_message(__msg_iter_order_bad
)
500 ._M_iterator(__lhs
, "lhs")
501 ._M_iterator(__rhs
, "rhs"));
502 _GLIBCXX_DEBUG_VERIFY(__lhs
._M_can_compare(__rhs
),
503 _M_message(__msg_order_different
)
504 ._M_iterator(__lhs
, "lhs")
505 ._M_iterator(__rhs
, "rhs"));
506 return __lhs
.base() <= __rhs
.base();
509 template<typename _Iterator
, typename _Sequence
>
511 operator<=(const _Safe_iterator
<_Iterator
, _Sequence
>& __lhs
,
512 const _Safe_iterator
<_Iterator
, _Sequence
>& __rhs
)
514 _GLIBCXX_DEBUG_VERIFY(! __lhs
._M_singular() && ! __rhs
._M_singular(),
515 _M_message(__msg_iter_order_bad
)
516 ._M_iterator(__lhs
, "lhs")
517 ._M_iterator(__rhs
, "rhs"));
518 _GLIBCXX_DEBUG_VERIFY(__lhs
._M_can_compare(__rhs
),
519 _M_message(__msg_order_different
)
520 ._M_iterator(__lhs
, "lhs")
521 ._M_iterator(__rhs
, "rhs"));
522 return __lhs
.base() <= __rhs
.base();
525 template<typename _IteratorL
, typename _IteratorR
, typename _Sequence
>
527 operator>(const _Safe_iterator
<_IteratorL
, _Sequence
>& __lhs
,
528 const _Safe_iterator
<_IteratorR
, _Sequence
>& __rhs
)
530 _GLIBCXX_DEBUG_VERIFY(! __lhs
._M_singular() && ! __rhs
._M_singular(),
531 _M_message(__msg_iter_order_bad
)
532 ._M_iterator(__lhs
, "lhs")
533 ._M_iterator(__rhs
, "rhs"));
534 _GLIBCXX_DEBUG_VERIFY(__lhs
._M_can_compare(__rhs
),
535 _M_message(__msg_order_different
)
536 ._M_iterator(__lhs
, "lhs")
537 ._M_iterator(__rhs
, "rhs"));
538 return __lhs
.base() > __rhs
.base();
541 template<typename _Iterator
, typename _Sequence
>
543 operator>(const _Safe_iterator
<_Iterator
, _Sequence
>& __lhs
,
544 const _Safe_iterator
<_Iterator
, _Sequence
>& __rhs
)
546 _GLIBCXX_DEBUG_VERIFY(! __lhs
._M_singular() && ! __rhs
._M_singular(),
547 _M_message(__msg_iter_order_bad
)
548 ._M_iterator(__lhs
, "lhs")
549 ._M_iterator(__rhs
, "rhs"));
550 _GLIBCXX_DEBUG_VERIFY(__lhs
._M_can_compare(__rhs
),
551 _M_message(__msg_order_different
)
552 ._M_iterator(__lhs
, "lhs")
553 ._M_iterator(__rhs
, "rhs"));
554 return __lhs
.base() > __rhs
.base();
557 template<typename _IteratorL
, typename _IteratorR
, typename _Sequence
>
559 operator>=(const _Safe_iterator
<_IteratorL
, _Sequence
>& __lhs
,
560 const _Safe_iterator
<_IteratorR
, _Sequence
>& __rhs
)
562 _GLIBCXX_DEBUG_VERIFY(! __lhs
._M_singular() && ! __rhs
._M_singular(),
563 _M_message(__msg_iter_order_bad
)
564 ._M_iterator(__lhs
, "lhs")
565 ._M_iterator(__rhs
, "rhs"));
566 _GLIBCXX_DEBUG_VERIFY(__lhs
._M_can_compare(__rhs
),
567 _M_message(__msg_order_different
)
568 ._M_iterator(__lhs
, "lhs")
569 ._M_iterator(__rhs
, "rhs"));
570 return __lhs
.base() >= __rhs
.base();
573 template<typename _Iterator
, typename _Sequence
>
575 operator>=(const _Safe_iterator
<_Iterator
, _Sequence
>& __lhs
,
576 const _Safe_iterator
<_Iterator
, _Sequence
>& __rhs
)
578 _GLIBCXX_DEBUG_VERIFY(! __lhs
._M_singular() && ! __rhs
._M_singular(),
579 _M_message(__msg_iter_order_bad
)
580 ._M_iterator(__lhs
, "lhs")
581 ._M_iterator(__rhs
, "rhs"));
582 _GLIBCXX_DEBUG_VERIFY(__lhs
._M_can_compare(__rhs
),
583 _M_message(__msg_order_different
)
584 ._M_iterator(__lhs
, "lhs")
585 ._M_iterator(__rhs
, "rhs"));
586 return __lhs
.base() >= __rhs
.base();
589 // _GLIBCXX_RESOLVE_LIB_DEFECTS
590 // According to the resolution of DR179 not only the various comparison
591 // operators but also operator- must accept mixed iterator/const_iterator
593 template<typename _IteratorL
, typename _IteratorR
, typename _Sequence
>
594 inline typename _Safe_iterator
<_IteratorL
, _Sequence
>::difference_type
595 operator-(const _Safe_iterator
<_IteratorL
, _Sequence
>& __lhs
,
596 const _Safe_iterator
<_IteratorR
, _Sequence
>& __rhs
)
598 _GLIBCXX_DEBUG_VERIFY(! __lhs
._M_singular() && ! __rhs
._M_singular(),
599 _M_message(__msg_distance_bad
)
600 ._M_iterator(__lhs
, "lhs")
601 ._M_iterator(__rhs
, "rhs"));
602 _GLIBCXX_DEBUG_VERIFY(__lhs
._M_can_compare(__rhs
),
603 _M_message(__msg_distance_different
)
604 ._M_iterator(__lhs
, "lhs")
605 ._M_iterator(__rhs
, "rhs"));
606 return __lhs
.base() - __rhs
.base();
609 template<typename _Iterator
, typename _Sequence
>
610 inline typename _Safe_iterator
<_Iterator
, _Sequence
>::difference_type
611 operator-(const _Safe_iterator
<_Iterator
, _Sequence
>& __lhs
,
612 const _Safe_iterator
<_Iterator
, _Sequence
>& __rhs
)
614 _GLIBCXX_DEBUG_VERIFY(! __lhs
._M_singular() && ! __rhs
._M_singular(),
615 _M_message(__msg_distance_bad
)
616 ._M_iterator(__lhs
, "lhs")
617 ._M_iterator(__rhs
, "rhs"));
618 _GLIBCXX_DEBUG_VERIFY(__lhs
._M_can_compare(__rhs
),
619 _M_message(__msg_distance_different
)
620 ._M_iterator(__lhs
, "lhs")
621 ._M_iterator(__rhs
, "rhs"));
622 return __lhs
.base() - __rhs
.base();
625 template<typename _Iterator
, typename _Sequence
>
626 inline _Safe_iterator
<_Iterator
, _Sequence
>
627 operator+(typename _Safe_iterator
<_Iterator
,_Sequence
>::difference_type __n
,
628 const _Safe_iterator
<_Iterator
, _Sequence
>& __i
)
629 { return __i
+ __n
; }
630 } // namespace __gnu_debug
633 #ifndef _GLIBCXX_EXPORT_TEMPLATE
634 # include <debug/safe_iterator.tcc>