Dead
[official-gcc.git] / gomp-20050608-branch / libstdc++-v3 / include / debug / safe_iterator.h
blobbcd7324cf816827028f2d7d5f0a9e12d477f2ded
1 // Safe iterator implementation -*- C++ -*-
3 // Copyright (C) 2003, 2004, 2005
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 2, or (at your option)
10 // any later version.
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,
20 // USA.
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>
42 namespace std
44 namespace __gnu_debug
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.
50 inline bool
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
71 * two iterators.
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
81 _Iterator _M_current;
83 /// Determine if this is a constant iterator.
84 bool
85 _M_constant() const
87 typedef typename _Sequence::const_iterator const_iterator;
88 return __is_same<const_iterator, _Safe_iterator>::value;
91 typedef iterator_traits<_Iterator> _Traits;
93 public:
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
106 * its sequence.
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
134 * constant iterator.
136 * @pre @p x is not singular
138 template<typename _MutableIterator>
139 _Safe_iterator(
140 const _Safe_iterator<_MutableIterator,
141 typename std::__enable_if<
142 _Sequence,
143 (std::__are_same<_MutableIterator,
144 typename _Sequence::iterator::_Base_iterator>::__value)
145 >::__type>& __x)
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
158 _Safe_iterator&
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));
167 return *this;
171 * @brief Iterator dereference.
172 * @pre iterator is dereferenceable
174 reference
175 operator*() const
178 _GLIBCXX_DEBUG_VERIFY(this->_M_dereferenceable(),
179 _M_message(__msg_bad_deref)
180 ._M_iterator(*this, "this"));
181 return *_M_current;
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
190 pointer
191 operator->() const
193 _GLIBCXX_DEBUG_VERIFY(this->_M_dereferenceable(),
194 _M_message(__msg_bad_deref)
195 ._M_iterator(*this, "this"));
196 return &*_M_current;
199 // ------ Input iterator requirements ------
201 * @brief Iterator preincrement
202 * @pre iterator is incrementable
204 _Safe_iterator&
205 operator++()
207 _GLIBCXX_DEBUG_VERIFY(this->_M_incrementable(),
208 _M_message(__msg_bad_inc)
209 ._M_iterator(*this, "this"));
210 ++_M_current;
211 return *this;
215 * @brief Iterator postincrement
216 * @pre iterator is incrementable
218 _Safe_iterator
219 operator++(int)
221 _GLIBCXX_DEBUG_VERIFY(this->_M_incrementable(),
222 _M_message(__msg_bad_inc)
223 ._M_iterator(*this, "this"));
224 _Safe_iterator __tmp(*this);
225 ++_M_current;
226 return __tmp;
229 // ------ Bidirectional iterator requirements ------
231 * @brief Iterator predecrement
232 * @pre iterator is decrementable
234 _Safe_iterator&
235 operator--()
237 _GLIBCXX_DEBUG_VERIFY(this->_M_decrementable(),
238 _M_message(__msg_bad_dec)
239 ._M_iterator(*this, "this"));
240 --_M_current;
241 return *this;
245 * @brief Iterator postdecrement
246 * @pre iterator is decrementable
248 _Safe_iterator
249 operator--(int)
251 _GLIBCXX_DEBUG_VERIFY(this->_M_decrementable(),
252 _M_message(__msg_bad_dec)
253 ._M_iterator(*this, "this"));
254 _Safe_iterator __tmp(*this);
255 --_M_current;
256 return __tmp;
259 // ------ Random access iterator requirements ------
260 reference
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];
271 _Safe_iterator&
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));
277 _M_current += __n;
278 return *this;
281 _Safe_iterator
282 operator+(const difference_type& __n) const
284 _Safe_iterator __tmp(*this);
285 __tmp += __n;
286 return __tmp;
289 _Safe_iterator&
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));
295 _M_current += -__n;
296 return *this;
299 _Safe_iterator
300 operator-(const difference_type& __n) const
302 _Safe_iterator __tmp(*this);
303 __tmp -= __n;
304 return __tmp;
307 // ------ Utilities ------
309 * @brief Return the underlying iterator
311 _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. */
321 void
322 _M_attach(const _Sequence* __seq)
324 _Safe_iterator_base::_M_attach(const_cast<_Sequence*>(__seq),
325 _M_constant());
328 /** Invalidate the iterator, making it singular. */
329 void
330 _M_invalidate();
332 /// Is the iterator dereferenceable?
333 bool
334 _M_dereferenceable() const
335 { return !this->_M_singular() && !_M_is_end(); }
337 /// Is the iterator incrementable?
338 bool
339 _M_incrementable() const { return this->_M_dereferenceable(); }
341 // Is the iterator decrementable?
342 bool
343 _M_decrementable() const { return !_M_singular() && !_M_is_begin(); }
345 // Can we advance the iterator @p __n steps (@p __n may be negative)
346 bool
347 _M_can_advance(const difference_type& __n) const;
349 // Is the iterator range [*this, __rhs) valid?
350 template<typename _Other>
351 bool
352 _M_valid_range(const _Safe_iterator<_Other, _Sequence>& __rhs) const;
354 // The sequence this iterator references.
355 const _Sequence*
356 _M_get_sequence() const
357 { return static_cast<const _Sequence*>(_M_sequence); }
359 /** Determine the distance between two iterators with some known
360 * precision.
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
367 _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,
385 __dp_equality);
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>
398 inline bool
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>
414 inline bool
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>
430 inline bool
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>
446 inline bool
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>
462 inline bool
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>
478 inline bool
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>
494 inline bool
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>
510 inline bool
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>
526 inline bool
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>
542 inline bool
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>
558 inline bool
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>
574 inline bool
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
592 // parameters.
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
631 } // namespace std
633 #ifndef _GLIBCXX_EXPORT_TEMPLATE
634 # include <debug/safe_iterator.tcc>
635 #endif
637 #endif