1 // Safe iterator implementation -*- C++ -*-
3 // Copyright (C) 2003, 2004, 2005, 2006, 2009
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 3, 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 // 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.
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/>.
26 /** @file debug/safe_iterator.h
27 * This file is a GNU debug extension to the Standard C++ Library.
30 #ifndef _GLIBCXX_DEBUG_SAFE_ITERATOR_H
31 #define _GLIBCXX_DEBUG_SAFE_ITERATOR_H 1
33 #include <debug/debug.h>
34 #include <debug/macros.h>
35 #include <debug/functions.h>
36 #include <debug/formatter.h>
37 #include <debug/safe_base.h>
38 #include <bits/stl_pair.h>
39 #include <ext/type_traits.h>
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.
48 __check_singular_aux(const _Safe_iterator_base* __x)
49 { return __x->_M_singular(); }
51 /** \brief Safe iterator wrapper.
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.
62 template<typename _Iterator, typename _Sequence>
63 class _Safe_iterator : public _Safe_iterator_base
65 typedef _Safe_iterator _Self;
67 /** The precision to which we can calculate the distance between
70 enum _Distance_precision
72 __dp_equality, //< Can compare iterator equality, only
73 __dp_sign, //< Can determine equality and ordering
74 __dp_exact //< Can determine distance precisely
77 /// The underlying iterator
80 /// Determine if this is a constant iterator.
84 typedef typename _Sequence::const_iterator const_iterator;
85 return __is_same<const_iterator, _Safe_iterator>::value;
88 typedef std::iterator_traits<_Iterator> _Traits;
91 typedef _Iterator _Base_iterator;
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;
98 /// @post the iterator is singular and unattached
99 _Safe_iterator() : _M_current() { }
102 * @brief Safe iterator construction from an unsafe iterator and
105 * @pre @p seq is not NULL
106 * @post this is not singular
108 _Safe_iterator(const _Iterator& __i, const _Sequence* __seq)
109 : _Safe_iterator_base(__seq, _M_constant()), _M_current(__i)
111 _GLIBCXX_DEBUG_VERIFY(! this->_M_singular(),
112 _M_message(__msg_init_singular)
113 ._M_iterator(*this, "this"));
117 * @brief Copy construction.
118 * @pre @p x is not singular
120 _Safe_iterator(const _Safe_iterator& __x)
121 : _Safe_iterator_base(__x, _M_constant()), _M_current(__x._M_current)
123 _GLIBCXX_DEBUG_VERIFY(!__x._M_singular(),
124 _M_message(__msg_init_copy_singular)
125 ._M_iterator(*this, "this")
126 ._M_iterator(__x, "other"));
130 * @brief Converting constructor from a mutable iterator to a
133 * @pre @p x is not singular
135 template<typename _MutableIterator>
137 const _Safe_iterator<_MutableIterator,
138 typename __gnu_cxx::__enable_if<(std::__are_same<_MutableIterator,
139 typename _Sequence::iterator::_Base_iterator>::__value),
140 _Sequence>::__type>& __x)
141 : _Safe_iterator_base(__x, _M_constant()), _M_current(__x.base())
143 _GLIBCXX_DEBUG_VERIFY(!__x._M_singular(),
144 _M_message(__msg_init_const_singular)
145 ._M_iterator(*this, "this")
146 ._M_iterator(__x, "other"));
150 * @brief Copy assignment.
151 * @pre @p x is not singular
154 operator=(const _Safe_iterator& __x)
156 _GLIBCXX_DEBUG_VERIFY(!__x._M_singular(),
157 _M_message(__msg_copy_singular)
158 ._M_iterator(*this, "this")
159 ._M_iterator(__x, "other"));
160 _M_current = __x._M_current;
161 this->_M_attach(static_cast<_Sequence*>(__x._M_sequence));
166 * @brief Iterator dereference.
167 * @pre iterator is dereferenceable
173 _GLIBCXX_DEBUG_VERIFY(this->_M_dereferenceable(),
174 _M_message(__msg_bad_deref)
175 ._M_iterator(*this, "this"));
180 * @brief Iterator dereference.
181 * @pre iterator is dereferenceable
182 * @todo Make this correct w.r.t. iterators that return proxies
183 * @todo Use addressof() instead of & operator
188 _GLIBCXX_DEBUG_VERIFY(this->_M_dereferenceable(),
189 _M_message(__msg_bad_deref)
190 ._M_iterator(*this, "this"));
194 // ------ Input iterator requirements ------
196 * @brief Iterator preincrement
197 * @pre iterator is incrementable
202 _GLIBCXX_DEBUG_VERIFY(this->_M_incrementable(),
203 _M_message(__msg_bad_inc)
204 ._M_iterator(*this, "this"));
210 * @brief Iterator postincrement
211 * @pre iterator is incrementable
216 _GLIBCXX_DEBUG_VERIFY(this->_M_incrementable(),
217 _M_message(__msg_bad_inc)
218 ._M_iterator(*this, "this"));
219 _Safe_iterator __tmp(*this);
224 // ------ Bidirectional iterator requirements ------
226 * @brief Iterator predecrement
227 * @pre iterator is decrementable
232 _GLIBCXX_DEBUG_VERIFY(this->_M_decrementable(),
233 _M_message(__msg_bad_dec)
234 ._M_iterator(*this, "this"));
240 * @brief Iterator postdecrement
241 * @pre iterator is decrementable
246 _GLIBCXX_DEBUG_VERIFY(this->_M_decrementable(),
247 _M_message(__msg_bad_dec)
248 ._M_iterator(*this, "this"));
249 _Safe_iterator __tmp(*this);
254 // ------ Random access iterator requirements ------
256 operator[](const difference_type& __n) const
258 _GLIBCXX_DEBUG_VERIFY(this->_M_can_advance(__n)
259 && this->_M_can_advance(__n+1),
260 _M_message(__msg_iter_subscript_oob)
261 ._M_iterator(*this)._M_integer(__n));
263 return _M_current[__n];
267 operator+=(const difference_type& __n)
269 _GLIBCXX_DEBUG_VERIFY(this->_M_can_advance(__n),
270 _M_message(__msg_advance_oob)
271 ._M_iterator(*this)._M_integer(__n));
277 operator+(const difference_type& __n) const
279 _Safe_iterator __tmp(*this);
285 operator-=(const difference_type& __n)
287 _GLIBCXX_DEBUG_VERIFY(this->_M_can_advance(-__n),
288 _M_message(__msg_retreat_oob)
289 ._M_iterator(*this)._M_integer(__n));
295 operator-(const difference_type& __n) const
297 _Safe_iterator __tmp(*this);
302 // ------ Utilities ------
304 * @brief Return the underlying iterator
307 base() const { return _M_current; }
310 * @brief Conversion to underlying non-debug iterator to allow
311 * better interaction with non-debug containers.
313 operator _Iterator() const { return _M_current; }
315 /** Attach iterator to the given sequence. */
317 _M_attach(const _Sequence* __seq)
319 _Safe_iterator_base::_M_attach(const_cast<_Sequence*>(__seq),
323 /** Likewise, but not thread-safe. */
325 _M_attach_single(const _Sequence* __seq)
327 _Safe_iterator_base::_M_attach_single(const_cast<_Sequence*>(__seq),
331 /** Invalidate the iterator, making it singular. */
335 /** Likewise, but not thread-safe. */
337 _M_invalidate_single();
339 /// Is the iterator dereferenceable?
341 _M_dereferenceable() const
342 { return !this->_M_singular() && !_M_is_end(); }
344 /// Is the iterator incrementable?
346 _M_incrementable() const { return this->_M_dereferenceable(); }
348 // Is the iterator decrementable?
350 _M_decrementable() const { return !_M_singular() && !_M_is_begin(); }
352 // Can we advance the iterator @p __n steps (@p __n may be negative)
354 _M_can_advance(const difference_type& __n) const;
356 // Is the iterator range [*this, __rhs) valid?
357 template<typename _Other>
359 _M_valid_range(const _Safe_iterator<_Other, _Sequence>& __rhs) const;
361 // The sequence this iterator references.
363 _M_get_sequence() const
364 { return static_cast<const _Sequence*>(_M_sequence); }
366 /** Determine the distance between two iterators with some known
369 template<typename _Iterator1, typename _Iterator2>
370 static std::pair<difference_type, _Distance_precision>
371 _M_get_distance(const _Iterator1& __lhs, const _Iterator2& __rhs)
373 typedef typename std::iterator_traits<_Iterator1>::iterator_category
375 return _M_get_distance(__lhs, __rhs, _Category());
378 template<typename _Iterator1, typename _Iterator2>
379 static std::pair<difference_type, _Distance_precision>
380 _M_get_distance(const _Iterator1& __lhs, const _Iterator2& __rhs,
381 std::random_access_iterator_tag)
383 return std::make_pair(__rhs.base() - __lhs.base(), __dp_exact);
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 std::forward_iterator_tag)
391 return std::make_pair(__lhs.base() == __rhs.base()? 0 : 1,
395 /// Is this iterator equal to the sequence's begin() iterator?
396 bool _M_is_begin() const
397 { return *this == static_cast<const _Sequence*>(_M_sequence)->begin(); }
399 /// Is this iterator equal to the sequence's end() iterator?
400 bool _M_is_end() const
401 { return *this == static_cast<const _Sequence*>(_M_sequence)->end(); }
404 template<typename _IteratorL, typename _IteratorR, typename _Sequence>
406 operator==(const _Safe_iterator<_IteratorL, _Sequence>& __lhs,
407 const _Safe_iterator<_IteratorR, _Sequence>& __rhs)
409 _GLIBCXX_DEBUG_VERIFY(! __lhs._M_singular() && ! __rhs._M_singular(),
410 _M_message(__msg_iter_compare_bad)
411 ._M_iterator(__lhs, "lhs")
412 ._M_iterator(__rhs, "rhs"));
413 _GLIBCXX_DEBUG_VERIFY(__lhs._M_can_compare(__rhs),
414 _M_message(__msg_compare_different)
415 ._M_iterator(__lhs, "lhs")
416 ._M_iterator(__rhs, "rhs"));
417 return __lhs.base() == __rhs.base();
420 template<typename _Iterator, typename _Sequence>
422 operator==(const _Safe_iterator<_Iterator, _Sequence>& __lhs,
423 const _Safe_iterator<_Iterator, _Sequence>& __rhs)
425 _GLIBCXX_DEBUG_VERIFY(! __lhs._M_singular() && ! __rhs._M_singular(),
426 _M_message(__msg_iter_compare_bad)
427 ._M_iterator(__lhs, "lhs")
428 ._M_iterator(__rhs, "rhs"));
429 _GLIBCXX_DEBUG_VERIFY(__lhs._M_can_compare(__rhs),
430 _M_message(__msg_compare_different)
431 ._M_iterator(__lhs, "lhs")
432 ._M_iterator(__rhs, "rhs"));
433 return __lhs.base() == __rhs.base();
436 template<typename _IteratorL, typename _IteratorR, typename _Sequence>
438 operator!=(const _Safe_iterator<_IteratorL, _Sequence>& __lhs,
439 const _Safe_iterator<_IteratorR, _Sequence>& __rhs)
441 _GLIBCXX_DEBUG_VERIFY(! __lhs._M_singular() && ! __rhs._M_singular(),
442 _M_message(__msg_iter_compare_bad)
443 ._M_iterator(__lhs, "lhs")
444 ._M_iterator(__rhs, "rhs"));
445 _GLIBCXX_DEBUG_VERIFY(__lhs._M_can_compare(__rhs),
446 _M_message(__msg_compare_different)
447 ._M_iterator(__lhs, "lhs")
448 ._M_iterator(__rhs, "rhs"));
449 return __lhs.base() != __rhs.base();
452 template<typename _Iterator, typename _Sequence>
454 operator!=(const _Safe_iterator<_Iterator, _Sequence>& __lhs,
455 const _Safe_iterator<_Iterator, _Sequence>& __rhs)
457 _GLIBCXX_DEBUG_VERIFY(! __lhs._M_singular() && ! __rhs._M_singular(),
458 _M_message(__msg_iter_compare_bad)
459 ._M_iterator(__lhs, "lhs")
460 ._M_iterator(__rhs, "rhs"));
461 _GLIBCXX_DEBUG_VERIFY(__lhs._M_can_compare(__rhs),
462 _M_message(__msg_compare_different)
463 ._M_iterator(__lhs, "lhs")
464 ._M_iterator(__rhs, "rhs"));
465 return __lhs.base() != __rhs.base();
468 template<typename _IteratorL, typename _IteratorR, typename _Sequence>
470 operator<(const _Safe_iterator<_IteratorL, _Sequence>& __lhs,
471 const _Safe_iterator<_IteratorR, _Sequence>& __rhs)
473 _GLIBCXX_DEBUG_VERIFY(! __lhs._M_singular() && ! __rhs._M_singular(),
474 _M_message(__msg_iter_order_bad)
475 ._M_iterator(__lhs, "lhs")
476 ._M_iterator(__rhs, "rhs"));
477 _GLIBCXX_DEBUG_VERIFY(__lhs._M_can_compare(__rhs),
478 _M_message(__msg_order_different)
479 ._M_iterator(__lhs, "lhs")
480 ._M_iterator(__rhs, "rhs"));
481 return __lhs.base() < __rhs.base();
484 template<typename _Iterator, typename _Sequence>
486 operator<(const _Safe_iterator<_Iterator, _Sequence>& __lhs,
487 const _Safe_iterator<_Iterator, _Sequence>& __rhs)
489 _GLIBCXX_DEBUG_VERIFY(! __lhs._M_singular() && ! __rhs._M_singular(),
490 _M_message(__msg_iter_order_bad)
491 ._M_iterator(__lhs, "lhs")
492 ._M_iterator(__rhs, "rhs"));
493 _GLIBCXX_DEBUG_VERIFY(__lhs._M_can_compare(__rhs),
494 _M_message(__msg_order_different)
495 ._M_iterator(__lhs, "lhs")
496 ._M_iterator(__rhs, "rhs"));
497 return __lhs.base() < __rhs.base();
500 template<typename _IteratorL, typename _IteratorR, typename _Sequence>
502 operator<=(const _Safe_iterator<_IteratorL, _Sequence>& __lhs,
503 const _Safe_iterator<_IteratorR, _Sequence>& __rhs)
505 _GLIBCXX_DEBUG_VERIFY(! __lhs._M_singular() && ! __rhs._M_singular(),
506 _M_message(__msg_iter_order_bad)
507 ._M_iterator(__lhs, "lhs")
508 ._M_iterator(__rhs, "rhs"));
509 _GLIBCXX_DEBUG_VERIFY(__lhs._M_can_compare(__rhs),
510 _M_message(__msg_order_different)
511 ._M_iterator(__lhs, "lhs")
512 ._M_iterator(__rhs, "rhs"));
513 return __lhs.base() <= __rhs.base();
516 template<typename _Iterator, typename _Sequence>
518 operator<=(const _Safe_iterator<_Iterator, _Sequence>& __lhs,
519 const _Safe_iterator<_Iterator, _Sequence>& __rhs)
521 _GLIBCXX_DEBUG_VERIFY(! __lhs._M_singular() && ! __rhs._M_singular(),
522 _M_message(__msg_iter_order_bad)
523 ._M_iterator(__lhs, "lhs")
524 ._M_iterator(__rhs, "rhs"));
525 _GLIBCXX_DEBUG_VERIFY(__lhs._M_can_compare(__rhs),
526 _M_message(__msg_order_different)
527 ._M_iterator(__lhs, "lhs")
528 ._M_iterator(__rhs, "rhs"));
529 return __lhs.base() <= __rhs.base();
532 template<typename _IteratorL, typename _IteratorR, typename _Sequence>
534 operator>(const _Safe_iterator<_IteratorL, _Sequence>& __lhs,
535 const _Safe_iterator<_IteratorR, _Sequence>& __rhs)
537 _GLIBCXX_DEBUG_VERIFY(! __lhs._M_singular() && ! __rhs._M_singular(),
538 _M_message(__msg_iter_order_bad)
539 ._M_iterator(__lhs, "lhs")
540 ._M_iterator(__rhs, "rhs"));
541 _GLIBCXX_DEBUG_VERIFY(__lhs._M_can_compare(__rhs),
542 _M_message(__msg_order_different)
543 ._M_iterator(__lhs, "lhs")
544 ._M_iterator(__rhs, "rhs"));
545 return __lhs.base() > __rhs.base();
548 template<typename _Iterator, typename _Sequence>
550 operator>(const _Safe_iterator<_Iterator, _Sequence>& __lhs,
551 const _Safe_iterator<_Iterator, _Sequence>& __rhs)
553 _GLIBCXX_DEBUG_VERIFY(! __lhs._M_singular() && ! __rhs._M_singular(),
554 _M_message(__msg_iter_order_bad)
555 ._M_iterator(__lhs, "lhs")
556 ._M_iterator(__rhs, "rhs"));
557 _GLIBCXX_DEBUG_VERIFY(__lhs._M_can_compare(__rhs),
558 _M_message(__msg_order_different)
559 ._M_iterator(__lhs, "lhs")
560 ._M_iterator(__rhs, "rhs"));
561 return __lhs.base() > __rhs.base();
564 template<typename _IteratorL, typename _IteratorR, typename _Sequence>
566 operator>=(const _Safe_iterator<_IteratorL, _Sequence>& __lhs,
567 const _Safe_iterator<_IteratorR, _Sequence>& __rhs)
569 _GLIBCXX_DEBUG_VERIFY(! __lhs._M_singular() && ! __rhs._M_singular(),
570 _M_message(__msg_iter_order_bad)
571 ._M_iterator(__lhs, "lhs")
572 ._M_iterator(__rhs, "rhs"));
573 _GLIBCXX_DEBUG_VERIFY(__lhs._M_can_compare(__rhs),
574 _M_message(__msg_order_different)
575 ._M_iterator(__lhs, "lhs")
576 ._M_iterator(__rhs, "rhs"));
577 return __lhs.base() >= __rhs.base();
580 template<typename _Iterator, typename _Sequence>
582 operator>=(const _Safe_iterator<_Iterator, _Sequence>& __lhs,
583 const _Safe_iterator<_Iterator, _Sequence>& __rhs)
585 _GLIBCXX_DEBUG_VERIFY(! __lhs._M_singular() && ! __rhs._M_singular(),
586 _M_message(__msg_iter_order_bad)
587 ._M_iterator(__lhs, "lhs")
588 ._M_iterator(__rhs, "rhs"));
589 _GLIBCXX_DEBUG_VERIFY(__lhs._M_can_compare(__rhs),
590 _M_message(__msg_order_different)
591 ._M_iterator(__lhs, "lhs")
592 ._M_iterator(__rhs, "rhs"));
593 return __lhs.base() >= __rhs.base();
596 // _GLIBCXX_RESOLVE_LIB_DEFECTS
597 // According to the resolution of DR179 not only the various comparison
598 // operators but also operator- must accept mixed iterator/const_iterator
600 template<typename _IteratorL, typename _IteratorR, typename _Sequence>
601 inline typename _Safe_iterator<_IteratorL, _Sequence>::difference_type
602 operator-(const _Safe_iterator<_IteratorL, _Sequence>& __lhs,
603 const _Safe_iterator<_IteratorR, _Sequence>& __rhs)
605 _GLIBCXX_DEBUG_VERIFY(! __lhs._M_singular() && ! __rhs._M_singular(),
606 _M_message(__msg_distance_bad)
607 ._M_iterator(__lhs, "lhs")
608 ._M_iterator(__rhs, "rhs"));
609 _GLIBCXX_DEBUG_VERIFY(__lhs._M_can_compare(__rhs),
610 _M_message(__msg_distance_different)
611 ._M_iterator(__lhs, "lhs")
612 ._M_iterator(__rhs, "rhs"));
613 return __lhs.base() - __rhs.base();
616 template<typename _Iterator, typename _Sequence>
617 inline typename _Safe_iterator<_Iterator, _Sequence>::difference_type
618 operator-(const _Safe_iterator<_Iterator, _Sequence>& __lhs,
619 const _Safe_iterator<_Iterator, _Sequence>& __rhs)
621 _GLIBCXX_DEBUG_VERIFY(! __lhs._M_singular() && ! __rhs._M_singular(),
622 _M_message(__msg_distance_bad)
623 ._M_iterator(__lhs, "lhs")
624 ._M_iterator(__rhs, "rhs"));
625 _GLIBCXX_DEBUG_VERIFY(__lhs._M_can_compare(__rhs),
626 _M_message(__msg_distance_different)
627 ._M_iterator(__lhs, "lhs")
628 ._M_iterator(__rhs, "rhs"));
629 return __lhs.base() - __rhs.base();
632 template<typename _Iterator, typename _Sequence>
633 inline _Safe_iterator<_Iterator, _Sequence>
634 operator+(typename _Safe_iterator<_Iterator,_Sequence>::difference_type __n,
635 const _Safe_iterator<_Iterator, _Sequence>& __i)
636 { return __i + __n; }
637 } // namespace __gnu_debug
639 #ifndef _GLIBCXX_EXPORT_TEMPLATE
640 # include <debug/safe_iterator.tcc>