source: Daodan/MSYS2/mingw32/include/c++/11.2.0/debug/safe_iterator.h@ 1186

Last change on this file since 1186 was 1166, checked in by rossy, 3 years ago

Daodan: Replace MinGW build env with an up-to-date MSYS2 env

File size: 29.9 KB
Line 
1// Safe iterator implementation -*- C++ -*-
2
3// Copyright (C) 2003-2021 Free Software Foundation, Inc.
4//
5// This file is part of the GNU ISO C++ Library. This library is free
6// software; you can redistribute it and/or modify it under the
7// terms of the GNU General Public License as published by the
8// Free Software Foundation; either version 3, or (at your option)
9// any later version.
10
11// This library is distributed in the hope that it will be useful,
12// but WITHOUT ANY WARRANTY; without even the implied warranty of
13// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14// GNU General Public License for more details.
15
16// Under Section 7 of GPL version 3, you are granted additional
17// permissions described in the GCC Runtime Library Exception, version
18// 3.1, as published by the Free Software Foundation.
19
20// You should have received a copy of the GNU General Public License and
21// a copy of the GCC Runtime Library Exception along with this program;
22// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
23// <http://www.gnu.org/licenses/>.
24
25/** @file debug/safe_iterator.h
26 * This file is a GNU debug extension to the Standard C++ Library.
27 */
28
29#ifndef _GLIBCXX_DEBUG_SAFE_ITERATOR_H
30#define _GLIBCXX_DEBUG_SAFE_ITERATOR_H 1
31
32#include <debug/assertions.h>
33#include <debug/macros.h>
34#include <debug/functions.h>
35#include <debug/safe_base.h>
36#include <bits/stl_pair.h>
37#include <ext/type_traits.h>
38#if __cplusplus > 201703L
39# include <compare>
40#endif
41
42#define _GLIBCXX_DEBUG_VERIFY_OPERANDS(_Lhs, _Rhs, _BadMsgId, _DiffMsgId) \
43 _GLIBCXX_DEBUG_VERIFY(!_Lhs._M_singular() && !_Rhs._M_singular() \
44 || (_Lhs.base() == _Iterator() \
45 && _Rhs.base() == _Iterator()), \
46 _M_message(_BadMsgId) \
47 ._M_iterator(_Lhs, #_Lhs) \
48 ._M_iterator(_Rhs, #_Rhs)); \
49 _GLIBCXX_DEBUG_VERIFY(_Lhs._M_can_compare(_Rhs), \
50 _M_message(_DiffMsgId) \
51 ._M_iterator(_Lhs, #_Lhs) \
52 ._M_iterator(_Rhs, #_Rhs))
53
54#define _GLIBCXX_DEBUG_VERIFY_EQ_OPERANDS(_Lhs, _Rhs) \
55 _GLIBCXX_DEBUG_VERIFY_OPERANDS(_Lhs, _Rhs, __msg_iter_compare_bad, \
56 __msg_compare_different)
57
58#define _GLIBCXX_DEBUG_VERIFY_REL_OPERANDS(_Lhs, _Rhs) \
59 _GLIBCXX_DEBUG_VERIFY_OPERANDS(_Lhs, _Rhs, __msg_iter_order_bad, \
60 __msg_order_different)
61
62#define _GLIBCXX_DEBUG_VERIFY_DIST_OPERANDS(_Lhs, _Rhs) \
63 _GLIBCXX_DEBUG_VERIFY_OPERANDS(_Lhs, _Rhs, __msg_distance_bad, \
64 __msg_distance_different)
65
66namespace __gnu_debug
67{
68 /** Helper struct to deal with sequence offering a before_begin
69 * iterator.
70 **/
71 template<typename _Sequence>
72 struct _BeforeBeginHelper
73 {
74 template<typename _Iterator, typename _Category>
75 static bool
76 _S_Is(const _Safe_iterator<_Iterator, _Sequence, _Category>&)
77 { return false; }
78
79 template<typename _Iterator, typename _Category>
80 static bool
81 _S_Is_Beginnest(const _Safe_iterator<_Iterator, _Sequence, _Category>& __it)
82 { return __it.base() == __it._M_get_sequence()->_M_base().begin(); }
83 };
84
85 /** Sequence traits giving the size of a container if possible. */
86 template<typename _Sequence>
87 struct _Sequence_traits
88 {
89 typedef _Distance_traits<typename _Sequence::iterator> _DistTraits;
90
91 static typename _DistTraits::__type
92 _S_size(const _Sequence& __seq)
93 { return std::make_pair(__seq.size(), __dp_exact); }
94 };
95
96 /** \brief Safe iterator wrapper.
97 *
98 * The class template %_Safe_iterator is a wrapper around an
99 * iterator that tracks the iterator's movement among sequences and
100 * checks that operations performed on the "safe" iterator are
101 * legal. In additional to the basic iterator operations (which are
102 * validated, and then passed to the underlying iterator),
103 * %_Safe_iterator has member functions for iterator invalidation,
104 * attaching/detaching the iterator from sequences, and querying
105 * the iterator's state.
106 *
107 * Note that _Iterator must be the first base class so that it gets
108 * initialized before the iterator is being attached to the container's list
109 * of iterators and it is being detached before _Iterator get
110 * destroyed. Otherwise it would result in a data race.
111 */
112 template<typename _Iterator, typename _Sequence, typename _Category
113 = typename std::iterator_traits<_Iterator>::iterator_category>
114 class _Safe_iterator
115 : private _Iterator,
116 public _Safe_iterator_base
117 {
118 typedef _Iterator _Iter_base;
119 typedef _Safe_iterator_base _Safe_base;
120
121 typedef std::iterator_traits<_Iterator> _Traits;
122
123 protected:
124 typedef std::__are_same<typename _Sequence::_Base::const_iterator,
125 _Iterator> _IsConstant;
126
127 typedef typename __gnu_cxx::__conditional_type<
128 _IsConstant::__value,
129 typename _Sequence::_Base::iterator,
130 typename _Sequence::_Base::const_iterator>::__type _OtherIterator;
131
132 struct _Attach_single
133 { };
134
135 _Safe_iterator(_Iterator __i, _Safe_sequence_base* __seq, _Attach_single)
136 _GLIBCXX_NOEXCEPT
137 : _Iter_base(__i)
138 { _M_attach_single(__seq); }
139
140 public:
141 typedef _Iterator iterator_type;
142 typedef typename _Traits::iterator_category iterator_category;
143 typedef typename _Traits::value_type value_type;
144 typedef typename _Traits::difference_type difference_type;
145 typedef typename _Traits::reference reference;
146 typedef typename _Traits::pointer pointer;
147
148#if __cplusplus > 201703L && __cpp_lib_concepts
149 using iterator_concept = std::__detail::__iter_concept<_Iterator>;
150#endif
151
152 /// @post the iterator is singular and unattached
153 _Safe_iterator() _GLIBCXX_NOEXCEPT : _Iter_base() { }
154
155 /**
156 * @brief Safe iterator construction from an unsafe iterator and
157 * its sequence.
158 *
159 * @pre @p seq is not NULL
160 * @post this is not singular
161 */
162 _Safe_iterator(_Iterator __i, const _Safe_sequence_base* __seq)
163 _GLIBCXX_NOEXCEPT
164 : _Iter_base(__i), _Safe_base(__seq, _S_constant())
165 {
166 _GLIBCXX_DEBUG_VERIFY(!this->_M_singular(),
167 _M_message(__msg_init_singular)
168 ._M_iterator(*this, "this"));
169 }
170
171 /**
172 * @brief Copy construction.
173 */
174 _Safe_iterator(const _Safe_iterator& __x) _GLIBCXX_NOEXCEPT
175 : _Iter_base(__x.base()), _Safe_base()
176 {
177 // _GLIBCXX_RESOLVE_LIB_DEFECTS
178 // DR 408. Is vector<reverse_iterator<char*> > forbidden?
179 _GLIBCXX_DEBUG_VERIFY(!__x._M_singular()
180 || __x.base() == _Iterator(),
181 _M_message(__msg_init_copy_singular)
182 ._M_iterator(*this, "this")
183 ._M_iterator(__x, "other"));
184 _M_attach(__x._M_sequence);
185 }
186
187#if __cplusplus >= 201103L
188 /**
189 * @brief Move construction.
190 * @post __x is singular and unattached
191 */
192 _Safe_iterator(_Safe_iterator&& __x) noexcept
193 : _Iter_base()
194 {
195 _GLIBCXX_DEBUG_VERIFY(!__x._M_singular()
196 || __x.base() == _Iterator(),
197 _M_message(__msg_init_copy_singular)
198 ._M_iterator(*this, "this")
199 ._M_iterator(__x, "other"));
200 _Safe_sequence_base* __seq = __x._M_sequence;
201 __x._M_detach();
202 std::swap(base(), __x.base());
203 _M_attach(__seq);
204 }
205#endif
206
207 /**
208 * @brief Converting constructor from a mutable iterator to a
209 * constant iterator.
210 */
211 template<typename _MutableIterator>
212 _Safe_iterator(
213 const _Safe_iterator<_MutableIterator, _Sequence,
214 typename __gnu_cxx::__enable_if<_IsConstant::__value &&
215 std::__are_same<_MutableIterator, _OtherIterator>::__value,
216 _Category>::__type>& __x)
217 _GLIBCXX_NOEXCEPT
218 : _Iter_base(__x.base())
219 {
220 // _GLIBCXX_RESOLVE_LIB_DEFECTS
221 // DR 408. Is vector<reverse_iterator<char*> > forbidden?
222 _GLIBCXX_DEBUG_VERIFY(!__x._M_singular()
223 || __x.base() == _MutableIterator(),
224 _M_message(__msg_init_const_singular)
225 ._M_iterator(*this, "this")
226 ._M_iterator(__x, "other"));
227 _M_attach(__x._M_sequence);
228 }
229
230 /**
231 * @brief Copy assignment.
232 */
233 _Safe_iterator&
234 operator=(const _Safe_iterator& __x) _GLIBCXX_NOEXCEPT
235 {
236 // _GLIBCXX_RESOLVE_LIB_DEFECTS
237 // DR 408. Is vector<reverse_iterator<char*> > forbidden?
238 _GLIBCXX_DEBUG_VERIFY(!__x._M_singular()
239 || __x.base() == _Iterator(),
240 _M_message(__msg_copy_singular)
241 ._M_iterator(*this, "this")
242 ._M_iterator(__x, "other"));
243
244 if (this->_M_sequence && this->_M_sequence == __x._M_sequence)
245 {
246 __gnu_cxx::__scoped_lock __l(this->_M_get_mutex());
247 base() = __x.base();
248 _M_version = __x._M_sequence->_M_version;
249 }
250 else
251 {
252 _M_detach();
253 base() = __x.base();
254 _M_attach(__x._M_sequence);
255 }
256
257 return *this;
258 }
259
260#if __cplusplus >= 201103L
261 /**
262 * @brief Move assignment.
263 * @post __x is singular and unattached
264 */
265 _Safe_iterator&
266 operator=(_Safe_iterator&& __x) noexcept
267 {
268 _GLIBCXX_DEBUG_VERIFY(!__x._M_singular()
269 || __x.base() == _Iterator(),
270 _M_message(__msg_copy_singular)
271 ._M_iterator(*this, "this")
272 ._M_iterator(__x, "other"));
273
274 if (std::__addressof(__x) == this)
275 return *this;
276
277 if (this->_M_sequence && this->_M_sequence == __x._M_sequence)
278 {
279 __gnu_cxx::__scoped_lock __l(this->_M_get_mutex());
280 base() = __x.base();
281 _M_version = __x._M_sequence->_M_version;
282 }
283 else
284 {
285 _M_detach();
286 base() = __x.base();
287 _M_attach(__x._M_sequence);
288 }
289
290 __x._M_detach();
291 __x.base() = _Iterator();
292 return *this;
293 }
294#endif
295
296 /**
297 * @brief Iterator dereference.
298 * @pre iterator is dereferenceable
299 */
300 reference
301 operator*() const _GLIBCXX_NOEXCEPT
302 {
303 _GLIBCXX_DEBUG_VERIFY(this->_M_dereferenceable(),
304 _M_message(__msg_bad_deref)
305 ._M_iterator(*this, "this"));
306 return *base();
307 }
308
309 /**
310 * @brief Iterator dereference.
311 * @pre iterator is dereferenceable
312 */
313 pointer
314 operator->() const _GLIBCXX_NOEXCEPT
315 {
316 _GLIBCXX_DEBUG_VERIFY(this->_M_dereferenceable(),
317 _M_message(__msg_bad_deref)
318 ._M_iterator(*this, "this"));
319 return base().operator->();
320 }
321
322 // ------ Input iterator requirements ------
323 /**
324 * @brief Iterator preincrement
325 * @pre iterator is incrementable
326 */
327 _Safe_iterator&
328 operator++() _GLIBCXX_NOEXCEPT
329 {
330 _GLIBCXX_DEBUG_VERIFY(this->_M_incrementable(),
331 _M_message(__msg_bad_inc)
332 ._M_iterator(*this, "this"));
333 __gnu_cxx::__scoped_lock __l(this->_M_get_mutex());
334 ++base();
335 return *this;
336 }
337
338 /**
339 * @brief Iterator postincrement
340 * @pre iterator is incrementable
341 */
342 _Safe_iterator
343 operator++(int) _GLIBCXX_NOEXCEPT
344 {
345 _GLIBCXX_DEBUG_VERIFY(this->_M_incrementable(),
346 _M_message(__msg_bad_inc)
347 ._M_iterator(*this, "this"));
348 __gnu_cxx::__scoped_lock __l(this->_M_get_mutex());
349 return _Safe_iterator(base()++, this->_M_sequence, _Attach_single());
350 }
351
352 // ------ Utilities ------
353
354 /// Determine if this is a constant iterator.
355 static _GLIBCXX_CONSTEXPR bool
356 _S_constant()
357 { return _IsConstant::__value; }
358
359 /**
360 * @brief Return the underlying iterator
361 */
362 _Iterator&
363 base() _GLIBCXX_NOEXCEPT { return *this; }
364
365 const _Iterator&
366 base() const _GLIBCXX_NOEXCEPT { return *this; }
367
368 /**
369 * @brief Conversion to underlying non-debug iterator to allow
370 * better interaction with non-debug containers.
371 */
372 operator _Iterator() const _GLIBCXX_NOEXCEPT { return *this; }
373
374 /** Attach iterator to the given sequence. */
375 void
376 _M_attach(_Safe_sequence_base* __seq)
377 { _Safe_base::_M_attach(__seq, _S_constant()); }
378
379 /** Likewise, but not thread-safe. */
380 void
381 _M_attach_single(_Safe_sequence_base* __seq)
382 { _Safe_base::_M_attach_single(__seq, _S_constant()); }
383
384 /// Is the iterator dereferenceable?
385 bool
386 _M_dereferenceable() const
387 { return !this->_M_singular() && !_M_is_end() && !_M_is_before_begin(); }
388
389 /// Is the iterator before a dereferenceable one?
390 bool
391 _M_before_dereferenceable() const
392 {
393 if (this->_M_incrementable())
394 {
395 _Iterator __base = base();
396 return ++__base != _M_get_sequence()->_M_base().end();
397 }
398 return false;
399 }
400
401 /// Is the iterator incrementable?
402 bool
403 _M_incrementable() const
404 { return !this->_M_singular() && !_M_is_end(); }
405
406 // Can we advance the iterator @p __n steps (@p __n may be negative)
407 bool
408 _M_can_advance(difference_type __n, bool __strict = false) const;
409
410 // Can we advance the iterator using @p __dist in @p __way direction.
411 template<typename _Diff>
412 bool
413 _M_can_advance(const std::pair<_Diff, _Distance_precision>& __dist,
414 int __way) const;
415
416 // Is the iterator range [*this, __rhs) valid?
417 bool
418 _M_valid_range(const _Safe_iterator& __rhs,
419 std::pair<difference_type, _Distance_precision>& __dist,
420 bool __check_dereferenceable = true) const;
421
422 // The sequence this iterator references.
423 typename __gnu_cxx::__conditional_type<
424 _IsConstant::__value, const _Sequence*, _Sequence*>::__type
425 _M_get_sequence() const
426 { return static_cast<_Sequence*>(_M_sequence); }
427
428 // Get distance to __rhs.
429 typename _Distance_traits<_Iterator>::__type
430 _M_get_distance_to(const _Safe_iterator& __rhs) const;
431
432 // Get distance from sequence begin up to *this.
433 typename _Distance_traits<_Iterator>::__type
434 _M_get_distance_from_begin() const;
435
436 // Get distance from *this to sequence end.
437 typename _Distance_traits<_Iterator>::__type
438 _M_get_distance_to_end() const;
439
440 /// Is this iterator equal to the sequence's begin() iterator?
441 bool
442 _M_is_begin() const
443 { return base() == _M_get_sequence()->_M_base().begin(); }
444
445 /// Is this iterator equal to the sequence's end() iterator?
446 bool
447 _M_is_end() const
448 { return base() == _M_get_sequence()->_M_base().end(); }
449
450 /// Is this iterator equal to the sequence's before_begin() iterator if
451 /// any?
452 bool
453 _M_is_before_begin() const
454 { return _BeforeBeginHelper<_Sequence>::_S_Is(*this); }
455
456 /// Is this iterator equal to the sequence's before_begin() iterator if
457 /// any or begin() otherwise?
458 bool
459 _M_is_beginnest() const
460 { return _BeforeBeginHelper<_Sequence>::_S_Is_Beginnest(*this); }
461
462 // ------ Operators ------
463
464 typedef _Safe_iterator<_Iterator, _Sequence, iterator_category> _Self;
465
466 friend bool
467 operator==(const _Self& __lhs, const _Self& __rhs) _GLIBCXX_NOEXCEPT
468 {
469 _GLIBCXX_DEBUG_VERIFY_EQ_OPERANDS(__lhs, __rhs);
470 return __lhs.base() == __rhs.base();
471 }
472
473 template<typename _IteR>
474 friend bool
475 operator==(const _Self& __lhs,
476 const _Safe_iterator<_IteR, _Sequence, iterator_category>& __rhs)
477 _GLIBCXX_NOEXCEPT
478 {
479 _GLIBCXX_DEBUG_VERIFY_EQ_OPERANDS(__lhs, __rhs);
480 return __lhs.base() == __rhs.base();
481 }
482
483#if ! __cpp_lib_three_way_comparison
484 friend bool
485 operator!=(const _Self& __lhs, const _Self& __rhs) _GLIBCXX_NOEXCEPT
486 {
487 _GLIBCXX_DEBUG_VERIFY_EQ_OPERANDS(__lhs, __rhs);
488 return __lhs.base() != __rhs.base();
489 }
490
491 template<typename _IteR>
492 friend bool
493 operator!=(const _Self& __lhs,
494 const _Safe_iterator<_IteR, _Sequence, iterator_category>& __rhs)
495 _GLIBCXX_NOEXCEPT
496 {
497 _GLIBCXX_DEBUG_VERIFY_EQ_OPERANDS(__lhs, __rhs);
498 return __lhs.base() != __rhs.base();
499 }
500#endif // three-way comparison
501 };
502
503 template<typename _Iterator, typename _Sequence>
504 class _Safe_iterator<_Iterator, _Sequence, std::bidirectional_iterator_tag>
505 : public _Safe_iterator<_Iterator, _Sequence, std::forward_iterator_tag>
506 {
507 typedef _Safe_iterator<_Iterator, _Sequence,
508 std::forward_iterator_tag> _Safe_base;
509
510 protected:
511 typedef typename _Safe_base::_OtherIterator _OtherIterator;
512 typedef typename _Safe_base::_Attach_single _Attach_single;
513
514 _Safe_iterator(_Iterator __i, _Safe_sequence_base* __seq, _Attach_single)
515 _GLIBCXX_NOEXCEPT
516 : _Safe_base(__i, __seq, _Attach_single())
517 { }
518
519 public:
520 /// @post the iterator is singular and unattached
521 _Safe_iterator() _GLIBCXX_NOEXCEPT { }
522
523 /**
524 * @brief Safe iterator construction from an unsafe iterator and
525 * its sequence.
526 *
527 * @pre @p seq is not NULL
528 * @post this is not singular
529 */
530 _Safe_iterator(_Iterator __i, const _Safe_sequence_base* __seq)
531 _GLIBCXX_NOEXCEPT
532 : _Safe_base(__i, __seq)
533 { }
534
535 /**
536 * @brief Copy construction.
537 */
538 _Safe_iterator(const _Safe_iterator& __x) _GLIBCXX_NOEXCEPT
539 : _Safe_base(__x)
540 { }
541
542#if __cplusplus >= 201103L
543 /** @brief Move construction. */
544 _Safe_iterator(_Safe_iterator&&) = default;
545#endif
546
547 /**
548 * @brief Converting constructor from a mutable iterator to a
549 * constant iterator.
550 */
551 template<typename _MutableIterator>
552 _Safe_iterator(
553 const _Safe_iterator<_MutableIterator, _Sequence,
554 typename __gnu_cxx::__enable_if<_Safe_base::_IsConstant::__value &&
555 std::__are_same<_MutableIterator, _OtherIterator>::__value,
556 std::bidirectional_iterator_tag>::__type>& __x)
557 _GLIBCXX_NOEXCEPT
558 : _Safe_base(__x)
559 { }
560
561#if __cplusplus >= 201103L
562 /** @brief Copy assignment. */
563 _Safe_iterator&
564 operator=(const _Safe_iterator&) = default;
565
566 /** @brief Move assignment. */
567 _Safe_iterator&
568 operator=(_Safe_iterator&&) = default;
569#else
570 /** @brief Copy assignment. */
571 _Safe_iterator&
572 operator=(const _Safe_iterator& __x)
573 {
574 _Safe_base::operator=(__x);
575 return *this;
576 }
577#endif
578
579 // ------ Input iterator requirements ------
580 /**
581 * @brief Iterator preincrement
582 * @pre iterator is incrementable
583 */
584 _Safe_iterator&
585 operator++() _GLIBCXX_NOEXCEPT
586 {
587 _Safe_base::operator++();
588 return *this;
589 }
590
591 /**
592 * @brief Iterator postincrement
593 * @pre iterator is incrementable
594 */
595 _Safe_iterator
596 operator++(int) _GLIBCXX_NOEXCEPT
597 {
598 _GLIBCXX_DEBUG_VERIFY(this->_M_incrementable(),
599 _M_message(__msg_bad_inc)
600 ._M_iterator(*this, "this"));
601 __gnu_cxx::__scoped_lock __l(this->_M_get_mutex());
602 return _Safe_iterator(this->base()++, this->_M_sequence,
603 _Attach_single());
604 }
605
606 // ------ Bidirectional iterator requirements ------
607 /**
608 * @brief Iterator predecrement
609 * @pre iterator is decrementable
610 */
611 _Safe_iterator&
612 operator--() _GLIBCXX_NOEXCEPT
613 {
614 _GLIBCXX_DEBUG_VERIFY(this->_M_decrementable(),
615 _M_message(__msg_bad_dec)
616 ._M_iterator(*this, "this"));
617 __gnu_cxx::__scoped_lock __l(this->_M_get_mutex());
618 --this->base();
619 return *this;
620 }
621
622 /**
623 * @brief Iterator postdecrement
624 * @pre iterator is decrementable
625 */
626 _Safe_iterator
627 operator--(int) _GLIBCXX_NOEXCEPT
628 {
629 _GLIBCXX_DEBUG_VERIFY(this->_M_decrementable(),
630 _M_message(__msg_bad_dec)
631 ._M_iterator(*this, "this"));
632 __gnu_cxx::__scoped_lock __l(this->_M_get_mutex());
633 return _Safe_iterator(this->base()--, this->_M_sequence,
634 _Attach_single());
635 }
636
637 // ------ Utilities ------
638
639 // Is the iterator decrementable?
640 bool
641 _M_decrementable() const
642 { return !this->_M_singular() && !this->_M_is_begin(); }
643 };
644
645 template<typename _Iterator, typename _Sequence>
646 class _Safe_iterator<_Iterator, _Sequence, std::random_access_iterator_tag>
647 : public _Safe_iterator<_Iterator, _Sequence,
648 std::bidirectional_iterator_tag>
649 {
650 typedef _Safe_iterator<_Iterator, _Sequence,
651 std::bidirectional_iterator_tag> _Safe_base;
652 typedef typename _Safe_base::_OtherIterator _OtherIterator;
653
654 typedef typename _Safe_base::_Self _Self;
655 typedef _Safe_iterator<_OtherIterator, _Sequence,
656 std::random_access_iterator_tag> _OtherSelf;
657
658 typedef typename _Safe_base::_Attach_single _Attach_single;
659
660 _Safe_iterator(_Iterator __i, _Safe_sequence_base* __seq, _Attach_single)
661 _GLIBCXX_NOEXCEPT
662 : _Safe_base(__i, __seq, _Attach_single())
663 { }
664
665 public:
666 typedef typename _Safe_base::difference_type difference_type;
667 typedef typename _Safe_base::reference reference;
668
669 /// @post the iterator is singular and unattached
670 _Safe_iterator() _GLIBCXX_NOEXCEPT { }
671
672 /**
673 * @brief Safe iterator construction from an unsafe iterator and
674 * its sequence.
675 *
676 * @pre @p seq is not NULL
677 * @post this is not singular
678 */
679 _Safe_iterator(_Iterator __i, const _Safe_sequence_base* __seq)
680 _GLIBCXX_NOEXCEPT
681 : _Safe_base(__i, __seq)
682 { }
683
684 /**
685 * @brief Copy construction.
686 */
687 _Safe_iterator(const _Safe_iterator& __x) _GLIBCXX_NOEXCEPT
688 : _Safe_base(__x)
689 { }
690
691#if __cplusplus >= 201103L
692 /** @brief Move construction. */
693 _Safe_iterator(_Safe_iterator&&) = default;
694#endif
695
696 /**
697 * @brief Converting constructor from a mutable iterator to a
698 * constant iterator.
699 */
700 template<typename _MutableIterator>
701 _Safe_iterator(
702 const _Safe_iterator<_MutableIterator, _Sequence,
703 typename __gnu_cxx::__enable_if<_Safe_base::_IsConstant::__value &&
704 std::__are_same<_MutableIterator, _OtherIterator>::__value,
705 std::random_access_iterator_tag>::__type>& __x)
706 _GLIBCXX_NOEXCEPT
707 : _Safe_base(__x)
708 { }
709
710#if __cplusplus >= 201103L
711 /** @brief Copy assignment. */
712 _Safe_iterator&
713 operator=(const _Safe_iterator&) = default;
714
715 /** @brief Move assignment. */
716 _Safe_iterator&
717 operator=(_Safe_iterator&&) = default;
718#else
719 /** @brief Copy assignment. */
720 _Safe_iterator&
721 operator=(const _Safe_iterator& __x)
722 {
723 _Safe_base::operator=(__x);
724 return *this;
725 }
726#endif
727
728 // Is the iterator range [*this, __rhs) valid?
729 bool
730 _M_valid_range(const _Safe_iterator& __rhs,
731 std::pair<difference_type,
732 _Distance_precision>& __dist) const;
733
734 // ------ Input iterator requirements ------
735 /**
736 * @brief Iterator preincrement
737 * @pre iterator is incrementable
738 */
739 _Safe_iterator&
740 operator++() _GLIBCXX_NOEXCEPT
741 {
742 _Safe_base::operator++();
743 return *this;
744 }
745
746 /**
747 * @brief Iterator postincrement
748 * @pre iterator is incrementable
749 */
750 _Safe_iterator
751 operator++(int) _GLIBCXX_NOEXCEPT
752 {
753 _GLIBCXX_DEBUG_VERIFY(this->_M_incrementable(),
754 _M_message(__msg_bad_inc)
755 ._M_iterator(*this, "this"));
756 __gnu_cxx::__scoped_lock __l(this->_M_get_mutex());
757 return _Safe_iterator(this->base()++, this->_M_sequence,
758 _Attach_single());
759 }
760
761 // ------ Bidirectional iterator requirements ------
762 /**
763 * @brief Iterator predecrement
764 * @pre iterator is decrementable
765 */
766 _Safe_iterator&
767 operator--() _GLIBCXX_NOEXCEPT
768 {
769 _Safe_base::operator--();
770 return *this;
771 }
772
773 /**
774 * @brief Iterator postdecrement
775 * @pre iterator is decrementable
776 */
777 _Safe_iterator
778 operator--(int) _GLIBCXX_NOEXCEPT
779 {
780 _GLIBCXX_DEBUG_VERIFY(this->_M_decrementable(),
781 _M_message(__msg_bad_dec)
782 ._M_iterator(*this, "this"));
783 __gnu_cxx::__scoped_lock __l(this->_M_get_mutex());
784 return _Safe_iterator(this->base()--, this->_M_sequence,
785 _Attach_single());
786 }
787
788 // ------ Random access iterator requirements ------
789 reference
790 operator[](difference_type __n) const _GLIBCXX_NOEXCEPT
791 {
792 _GLIBCXX_DEBUG_VERIFY(this->_M_can_advance(__n)
793 && this->_M_can_advance(__n + 1),
794 _M_message(__msg_iter_subscript_oob)
795 ._M_iterator(*this)._M_integer(__n));
796 return this->base()[__n];
797 }
798
799 _Safe_iterator&
800 operator+=(difference_type __n) _GLIBCXX_NOEXCEPT
801 {
802 _GLIBCXX_DEBUG_VERIFY(this->_M_can_advance(__n),
803 _M_message(__msg_advance_oob)
804 ._M_iterator(*this)._M_integer(__n));
805 __gnu_cxx::__scoped_lock __l(this->_M_get_mutex());
806 this->base() += __n;
807 return *this;
808 }
809
810 _Safe_iterator&
811 operator-=(difference_type __n) _GLIBCXX_NOEXCEPT
812 {
813 _GLIBCXX_DEBUG_VERIFY(this->_M_can_advance(-__n),
814 _M_message(__msg_retreat_oob)
815 ._M_iterator(*this)._M_integer(__n));
816 __gnu_cxx::__scoped_lock __l(this->_M_get_mutex());
817 this->base() -= __n;
818 return *this;
819 }
820
821#if __cpp_lib_three_way_comparison
822 friend auto
823 operator<=>(const _Self& __lhs, const _Self& __rhs) noexcept
824 {
825 _GLIBCXX_DEBUG_VERIFY_REL_OPERANDS(__lhs, __rhs);
826 return __lhs.base() <=> __rhs.base();
827 }
828
829 friend auto
830 operator<=>(const _Self& __lhs, const _OtherSelf& __rhs) noexcept
831 {
832 _GLIBCXX_DEBUG_VERIFY_REL_OPERANDS(__lhs, __rhs);
833 return __lhs.base() <=> __rhs.base();
834 }
835#else
836 friend bool
837 operator<(const _Self& __lhs, const _Self& __rhs) _GLIBCXX_NOEXCEPT
838 {
839 _GLIBCXX_DEBUG_VERIFY_REL_OPERANDS(__lhs, __rhs);
840 return __lhs.base() < __rhs.base();
841 }
842
843 friend bool
844 operator<(const _Self& __lhs, const _OtherSelf& __rhs) _GLIBCXX_NOEXCEPT
845 {
846 _GLIBCXX_DEBUG_VERIFY_REL_OPERANDS(__lhs, __rhs);
847 return __lhs.base() < __rhs.base();
848 }
849
850 friend bool
851 operator<=(const _Self& __lhs, const _Self& __rhs) _GLIBCXX_NOEXCEPT
852 {
853 _GLIBCXX_DEBUG_VERIFY_REL_OPERANDS(__lhs, __rhs);
854 return __lhs.base() <= __rhs.base();
855 }
856
857 friend bool
858 operator<=(const _Self& __lhs, const _OtherSelf& __rhs) _GLIBCXX_NOEXCEPT
859 {
860 _GLIBCXX_DEBUG_VERIFY_REL_OPERANDS(__lhs, __rhs);
861 return __lhs.base() <= __rhs.base();
862 }
863
864 friend bool
865 operator>(const _Self& __lhs, const _Self& __rhs) _GLIBCXX_NOEXCEPT
866 {
867 _GLIBCXX_DEBUG_VERIFY_REL_OPERANDS(__lhs, __rhs);
868 return __lhs.base() > __rhs.base();
869 }
870
871 friend bool
872 operator>(const _Self& __lhs, const _OtherSelf& __rhs) _GLIBCXX_NOEXCEPT
873 {
874 _GLIBCXX_DEBUG_VERIFY_REL_OPERANDS(__lhs, __rhs);
875 return __lhs.base() > __rhs.base();
876 }
877
878 friend bool
879 operator>=(const _Self& __lhs, const _Self& __rhs) _GLIBCXX_NOEXCEPT
880 {
881 _GLIBCXX_DEBUG_VERIFY_REL_OPERANDS(__lhs, __rhs);
882 return __lhs.base() >= __rhs.base();
883 }
884
885 friend bool
886 operator>=(const _Self& __lhs, const _OtherSelf& __rhs) _GLIBCXX_NOEXCEPT
887 {
888 _GLIBCXX_DEBUG_VERIFY_REL_OPERANDS(__lhs, __rhs);
889 return __lhs.base() >= __rhs.base();
890 }
891#endif // three-way comparison
892
893 // _GLIBCXX_RESOLVE_LIB_DEFECTS
894 // According to the resolution of DR179 not only the various comparison
895 // operators but also operator- must accept mixed iterator/const_iterator
896 // parameters.
897 friend difference_type
898 operator-(const _Self& __lhs, const _OtherSelf& __rhs) _GLIBCXX_NOEXCEPT
899 {
900 _GLIBCXX_DEBUG_VERIFY_DIST_OPERANDS(__lhs, __rhs);
901 return __lhs.base() - __rhs.base();
902 }
903
904 friend difference_type
905 operator-(const _Self& __lhs, const _Self& __rhs) _GLIBCXX_NOEXCEPT
906 {
907 _GLIBCXX_DEBUG_VERIFY_DIST_OPERANDS(__lhs, __rhs);
908 return __lhs.base() - __rhs.base();
909 }
910
911 friend _Self
912 operator+(const _Self& __x, difference_type __n) _GLIBCXX_NOEXCEPT
913 {
914 _GLIBCXX_DEBUG_VERIFY(__x._M_can_advance(__n),
915 _M_message(__msg_advance_oob)
916 ._M_iterator(__x)._M_integer(__n));
917 return _Safe_iterator(__x.base() + __n, __x._M_sequence);
918 }
919
920 friend _Self
921 operator+(difference_type __n, const _Self& __x) _GLIBCXX_NOEXCEPT
922 {
923 _GLIBCXX_DEBUG_VERIFY(__x._M_can_advance(__n),
924 _M_message(__msg_advance_oob)
925 ._M_iterator(__x)._M_integer(__n));
926 return _Safe_iterator(__n + __x.base(), __x._M_sequence);
927 }
928
929 friend _Self
930 operator-(const _Self& __x, difference_type __n) _GLIBCXX_NOEXCEPT
931 {
932 _GLIBCXX_DEBUG_VERIFY(__x._M_can_advance(-__n),
933 _M_message(__msg_retreat_oob)
934 ._M_iterator(__x)._M_integer(__n));
935 return _Safe_iterator(__x.base() - __n, __x._M_sequence);
936 }
937 };
938
939 /** Safe iterators know how to check if they form a valid range. */
940 template<typename _Iterator, typename _Sequence, typename _Category>
941 inline bool
942 __valid_range(const _Safe_iterator<_Iterator, _Sequence,
943 _Category>& __first,
944 const _Safe_iterator<_Iterator, _Sequence,
945 _Category>& __last,
946 typename _Distance_traits<_Iterator>::__type& __dist)
947 { return __first._M_valid_range(__last, __dist); }
948
949 template<typename _Iterator, typename _Sequence, typename _Category>
950 inline bool
951 __valid_range(const _Safe_iterator<_Iterator, _Sequence,
952 _Category>& __first,
953 const _Safe_iterator<_Iterator, _Sequence,
954 _Category>& __last)
955 {
956 typename _Distance_traits<_Iterator>::__type __dist;
957 return __first._M_valid_range(__last, __dist);
958 }
959
960 template<typename _Iterator, typename _Sequence, typename _Category,
961 typename _Size>
962 inline bool
963 __can_advance(const _Safe_iterator<_Iterator, _Sequence, _Category>& __it,
964 _Size __n)
965 { return __it._M_can_advance(__n); }
966
967 template<typename _Iterator, typename _Sequence, typename _Category,
968 typename _Diff>
969 inline bool
970 __can_advance(const _Safe_iterator<_Iterator, _Sequence, _Category>& __it,
971 const std::pair<_Diff, _Distance_precision>& __dist,
972 int __way)
973 { return __it._M_can_advance(__dist, __way); }
974
975 template<typename _Iterator, typename _Sequence>
976 _Iterator
977 __base(const _Safe_iterator<_Iterator, _Sequence,
978 std::random_access_iterator_tag>& __it)
979 { return __it.base(); }
980
981#if __cplusplus < 201103L
982 template<typename _Iterator, typename _Sequence>
983 struct _Unsafe_type<_Safe_iterator<_Iterator, _Sequence> >
984 { typedef _Iterator _Type; };
985#endif
986
987 template<typename _Iterator, typename _Sequence>
988 inline _Iterator
989 __unsafe(const _Safe_iterator<_Iterator, _Sequence>& __it)
990 { return __it.base(); }
991
992} // namespace __gnu_debug
993
994#undef _GLIBCXX_DEBUG_VERIFY_DIST_OPERANDS
995#undef _GLIBCXX_DEBUG_VERIFY_REL_OPERANDS
996#undef _GLIBCXX_DEBUG_VERIFY_EQ_OPERANDS
997#undef _GLIBCXX_DEBUG_VERIFY_OPERANDS
998
999#include <debug/safe_iterator.tcc>
1000
1001#endif
Note: See TracBrowser for help on using the repository browser.