1 // <forward_list> -*- C++ -*-
3 // Copyright (C) 2010-2015 Free Software Foundation, Inc.
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)
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.
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.
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/>.
25 /** @file debug/forward_list
26 * This file is a GNU debug extension to the Standard C++ Library.
29 #ifndef _GLIBCXX_DEBUG_FORWARD_LIST
30 #define _GLIBCXX_DEBUG_FORWARD_LIST 1
32 #pragma GCC system_header
34 #include <forward_list>
35 #include <debug/safe_sequence.h>
36 #include <debug/safe_container.h>
37 #include <debug/safe_iterator.h>
41 /// Special iterators swap and invalidation for forward_list because of the
42 /// before_begin iterator.
43 template<typename _SafeSequence>
44 class _Safe_forward_list
45 : public _Safe_sequence<_SafeSequence>
49 { return *static_cast<_SafeSequence*>(this); }
52 _M_swap_aux(_Safe_sequence_base& __lhs,
53 _Safe_iterator_base*& __lhs_iterators,
54 _Safe_sequence_base& __rhs,
55 _Safe_iterator_base*& __rhs_iterators);
57 void _M_swap_single(_Safe_sequence_base&) noexcept;
63 using _Base_const_iterator = __decltype(_M_this()._M_base().cend());
64 this->_M_invalidate_if([this](_Base_const_iterator __it)
66 return __it != _M_this()._M_base().cbefore_begin()
67 && __it != _M_this()._M_base().cend(); });
70 void _M_swap(_Safe_sequence_base&) noexcept;
73 template<typename _SafeSequence>
75 _Safe_forward_list<_SafeSequence>::
76 _M_swap_aux(_Safe_sequence_base& __lhs,
77 _Safe_iterator_base*& __lhs_iterators,
78 _Safe_sequence_base& __rhs,
79 _Safe_iterator_base*& __rhs_iterators)
81 using const_iterator = typename _SafeSequence::const_iterator;
82 _Safe_iterator_base* __bbegin_its = 0;
83 _Safe_iterator_base* __last_bbegin = 0;
84 _SafeSequence& __rseq = static_cast<_SafeSequence&>(__rhs);
86 for (_Safe_iterator_base* __iter = __lhs_iterators; __iter;)
88 // Even iterator is cast to const_iterator, not a problem.
89 _Safe_iterator_base* __victim_base = __iter;
90 const_iterator* __victim =
91 static_cast<const_iterator*>(__victim_base);
92 __iter = __iter->_M_next;
93 if (__victim->base() == __rseq._M_base().cbefore_begin())
95 __victim->_M_unlink();
96 if (__lhs_iterators == __victim_base)
97 __lhs_iterators = __victim_base->_M_next;
100 __victim_base->_M_next = __bbegin_its;
101 __bbegin_its->_M_prior = __victim_base;
104 __last_bbegin = __victim_base;
105 __bbegin_its = __victim_base;
108 __victim_base->_M_sequence = &__lhs;
115 __rhs_iterators->_M_prior = __last_bbegin;
116 __last_bbegin->_M_next = __rhs_iterators;
118 __rhs_iterators = __bbegin_its;
122 template<typename _SafeSequence>
124 _Safe_forward_list<_SafeSequence>::
125 _M_swap_single(_Safe_sequence_base& __other) noexcept
127 std::swap(_M_this()._M_iterators, __other._M_iterators);
128 std::swap(_M_this()._M_const_iterators, __other._M_const_iterators);
129 // Useless, always 1 on forward_list
130 //std::swap(_M_this()_M_version, __other._M_version);
131 _Safe_iterator_base* __this_its = _M_this()._M_iterators;
132 _M_swap_aux(__other, __other._M_iterators,
133 _M_this(), _M_this()._M_iterators);
134 _Safe_iterator_base* __this_const_its = _M_this()._M_const_iterators;
135 _M_swap_aux(__other, __other._M_const_iterators,
136 _M_this(), _M_this()._M_const_iterators);
137 _M_swap_aux(_M_this(), __this_its,
138 __other, __other._M_iterators);
139 _M_swap_aux(_M_this(), __this_const_its,
140 __other, __other._M_const_iterators);
143 /* Special forward_list _M_swap version that does not swap the
144 * before-begin ownership.*/
145 template<typename _SafeSequence>
147 _Safe_forward_list<_SafeSequence>::
148 _M_swap(_Safe_sequence_base& __other) noexcept
150 // We need to lock both sequences to swap
151 using namespace __gnu_cxx;
152 __mutex *__this_mutex = &_M_this()._M_get_mutex();
153 __mutex *__other_mutex =
154 &static_cast<_SafeSequence&>(__other)._M_get_mutex();
155 if (__this_mutex == __other_mutex)
157 __scoped_lock __lock(*__this_mutex);
158 _M_swap_single(__other);
162 __scoped_lock __l1(__this_mutex < __other_mutex
163 ? *__this_mutex : *__other_mutex);
164 __scoped_lock __l2(__this_mutex < __other_mutex
165 ? *__other_mutex : *__this_mutex);
166 _M_swap_single(__other);
171 namespace std _GLIBCXX_VISIBILITY(default)
175 /// Class std::forward_list with safety/checking/debug instrumentation.
176 template<typename _Tp, typename _Alloc = std::allocator<_Tp> >
178 : public __gnu_debug::_Safe_container<
179 forward_list<_Tp, _Alloc>, _Alloc, __gnu_debug::_Safe_forward_list>,
180 public _GLIBCXX_STD_C::forward_list<_Tp, _Alloc>
182 typedef _GLIBCXX_STD_C::forward_list<_Tp, _Alloc> _Base;
183 typedef __gnu_debug::_Safe_container<
184 forward_list, _Alloc, __gnu_debug::_Safe_forward_list> _Safe;
186 typedef typename _Base::iterator _Base_iterator;
187 typedef typename _Base::const_iterator _Base_const_iterator;
190 typedef typename _Base::reference reference;
191 typedef typename _Base::const_reference const_reference;
193 typedef __gnu_debug::_Safe_iterator<
194 _Base_iterator, forward_list> iterator;
195 typedef __gnu_debug::_Safe_iterator<
196 _Base_const_iterator, forward_list> const_iterator;
198 typedef typename _Base::size_type size_type;
199 typedef typename _Base::difference_type difference_type;
201 typedef _Tp value_type;
202 typedef typename _Base::allocator_type allocator_type;
203 typedef typename _Base::pointer pointer;
204 typedef typename _Base::const_pointer const_pointer;
206 // 23.2.3.1 construct/copy/destroy:
208 forward_list(const allocator_type& __al = allocator_type())
211 forward_list(const forward_list& __list, const allocator_type& __al)
212 : _Base(__list, __al)
215 forward_list(forward_list&& __list, const allocator_type& __al)
216 : _Safe(std::move(__list._M_safe()), __al),
217 _Base(std::move(__list._M_base()), __al)
221 forward_list(size_type __n, const allocator_type& __al = allocator_type())
225 forward_list(size_type __n, const _Tp& __value,
226 const allocator_type& __al = allocator_type())
227 : _Base(__n, __value, __al)
230 template<typename _InputIterator,
231 typename = std::_RequireInputIter<_InputIterator>>
232 forward_list(_InputIterator __first, _InputIterator __last,
233 const allocator_type& __al = allocator_type())
234 : _Base(__gnu_debug::__base(__gnu_debug::__check_valid_range(__first,
236 __gnu_debug::__base(__last), __al)
239 forward_list(const forward_list&) = default;
241 forward_list(forward_list&&) = default;
243 forward_list(std::initializer_list<_Tp> __il,
244 const allocator_type& __al = allocator_type())
248 ~forward_list() = default;
251 operator=(const forward_list&) = default;
254 operator=(forward_list&&) = default;
257 operator=(std::initializer_list<_Tp> __il)
260 this->_M_invalidate_all();
264 template<typename _InputIterator,
265 typename = std::_RequireInputIter<_InputIterator>>
267 assign(_InputIterator __first, _InputIterator __last)
269 __glibcxx_check_valid_range(__first, __last);
270 _Base::assign(__gnu_debug::__base(__first),
271 __gnu_debug::__base(__last));
272 this->_M_invalidate_all();
276 assign(size_type __n, const _Tp& __val)
278 _Base::assign(__n, __val);
279 this->_M_invalidate_all();
283 assign(std::initializer_list<_Tp> __il)
286 this->_M_invalidate_all();
289 using _Base::get_allocator;
294 before_begin() noexcept
295 { return iterator(_Base::before_begin(), this); }
298 before_begin() const noexcept
299 { return const_iterator(_Base::before_begin(), this); }
303 { return iterator(_Base::begin(), this); }
306 begin() const noexcept
307 { return const_iterator(_Base::begin(), this); }
311 { return iterator(_Base::end(), this); }
315 { return const_iterator(_Base::end(), this); }
318 cbegin() const noexcept
319 { return const_iterator(_Base::cbegin(), this); }
322 cbefore_begin() const noexcept
323 { return const_iterator(_Base::cbefore_begin(), this); }
326 cend() const noexcept
327 { return const_iterator(_Base::cend(), this); }
330 using _Base::max_size;
337 __glibcxx_check_nonempty();
338 return _Base::front();
344 __glibcxx_check_nonempty();
345 return _Base::front();
350 using _Base::emplace_front;
351 using _Base::push_front;
356 __glibcxx_check_nonempty();
357 this->_M_invalidate_if([this](_Base_const_iterator __it)
358 { return __it == this->_M_base().cbegin(); });
362 template<typename... _Args>
364 emplace_after(const_iterator __pos, _Args&&... __args)
366 __glibcxx_check_insert_after(__pos);
367 return iterator(_Base::emplace_after(__pos.base(),
368 std::forward<_Args>(__args)...),
373 insert_after(const_iterator __pos, const _Tp& __val)
375 __glibcxx_check_insert_after(__pos);
376 return iterator(_Base::insert_after(__pos.base(), __val), this);
380 insert_after(const_iterator __pos, _Tp&& __val)
382 __glibcxx_check_insert_after(__pos);
383 return iterator(_Base::insert_after(__pos.base(), std::move(__val)),
388 insert_after(const_iterator __pos, size_type __n, const _Tp& __val)
390 __glibcxx_check_insert_after(__pos);
391 return iterator(_Base::insert_after(__pos.base(), __n, __val),
395 template<typename _InputIterator,
396 typename = std::_RequireInputIter<_InputIterator>>
398 insert_after(const_iterator __pos,
399 _InputIterator __first, _InputIterator __last)
401 __glibcxx_check_insert_range_after(__pos, __first, __last);
402 return iterator(_Base::insert_after(__pos.base(),
403 __gnu_debug::__base(__first),
404 __gnu_debug::__base(__last)),
409 insert_after(const_iterator __pos, std::initializer_list<_Tp> __il)
411 __glibcxx_check_insert_after(__pos);
412 return iterator(_Base::insert_after(__pos.base(), __il), this);
417 _M_erase_after(_Base_const_iterator __pos)
419 _Base_const_iterator __next = std::next(__pos);
420 this->_M_invalidate_if([__next](_Base_const_iterator __it)
421 { return __it == __next; });
422 return _Base::erase_after(__pos);
426 erase_after(const_iterator __pos)
428 __glibcxx_check_erase_after(__pos);
429 return iterator(_M_erase_after(__pos.base()), this);
433 erase_after(const_iterator __pos, const_iterator __last)
435 __glibcxx_check_erase_range_after(__pos, __last);
436 for (_Base_const_iterator __victim = std::next(__pos.base());
437 __victim != __last.base(); ++__victim)
439 _GLIBCXX_DEBUG_VERIFY(__victim != _Base::end(),
440 _M_message(__gnu_debug::__msg_valid_range2)
441 ._M_sequence(*this, "this")
442 ._M_iterator(__pos, "pos")
443 ._M_iterator(__last, "last"));
444 this->_M_invalidate_if([__victim](_Base_const_iterator __it)
445 { return __it == __victim; });
447 return iterator(_Base::erase_after(__pos.base(), __last.base()), this);
451 swap(forward_list& __list)
452 noexcept( noexcept(declval<_Base>().swap(__list)) )
454 _Safe::_M_swap(__list);
459 resize(size_type __sz)
461 this->_M_detach_singular();
463 // if __sz < size(), invalidate all iterators in [begin+__sz, end()
464 _Base_iterator __victim = _Base::begin();
465 _Base_iterator __end = _Base::end();
466 for (size_type __i = __sz; __victim != __end && __i > 0; --__i)
469 for (; __victim != __end; ++__victim)
471 this->_M_invalidate_if([__victim](_Base_const_iterator __it)
472 { return __it == __victim; });
481 this->_M_revalidate_singular();
482 __throw_exception_again;
487 resize(size_type __sz, const value_type& __val)
489 this->_M_detach_singular();
491 // if __sz < size(), invalidate all iterators in [begin+__sz, end())
492 _Base_iterator __victim = _Base::begin();
493 _Base_iterator __end = _Base::end();
494 for (size_type __i = __sz; __victim != __end && __i > 0; --__i)
497 for (; __victim != __end; ++__victim)
499 this->_M_invalidate_if([__victim](_Base_const_iterator __it)
500 { return __it == __victim; });
505 _Base::resize(__sz, __val);
509 this->_M_revalidate_singular();
510 __throw_exception_again;
518 this->_M_invalidate_all();
521 // 23.2.3.5 forward_list operations:
523 splice_after(const_iterator __pos, forward_list&& __list)
525 __glibcxx_check_insert_after(__pos);
526 _GLIBCXX_DEBUG_VERIFY(&__list != this,
527 _M_message(__gnu_debug::__msg_self_splice)
528 ._M_sequence(*this, "this"));
529 _GLIBCXX_DEBUG_VERIFY(__list.get_allocator() == this->get_allocator(),
530 _M_message(__gnu_debug::__msg_splice_alloc)
532 ._M_sequence(__list, "__list"));
533 this->_M_transfer_from_if(__list, [&__list](_Base_const_iterator __it)
535 return __it != __list._M_base().cbefore_begin()
536 && __it != __list._M_base().end();
538 _Base::splice_after(__pos.base(), std::move(__list._M_base()));
542 splice_after(const_iterator __pos, forward_list& __list)
543 { splice_after(__pos, std::move(__list)); }
546 splice_after(const_iterator __pos, forward_list&& __list,
549 __glibcxx_check_insert_after(__pos);
550 _GLIBCXX_DEBUG_VERIFY(__i._M_before_dereferenceable(),
551 _M_message(__gnu_debug::__msg_splice_bad)
552 ._M_iterator(__i, "__i"));
553 _GLIBCXX_DEBUG_VERIFY(__i._M_attached_to(&__list),
554 _M_message(__gnu_debug::__msg_splice_other)
555 ._M_iterator(__i, "__i")
556 ._M_sequence(__list, "__list"));
557 _GLIBCXX_DEBUG_VERIFY(__list.get_allocator() == this->get_allocator(),
558 _M_message(__gnu_debug::__msg_splice_alloc)
560 ._M_sequence(__list, "__list"));
562 // _GLIBCXX_RESOLVE_LIB_DEFECTS
563 // 250. splicing invalidates iterators
564 _Base_const_iterator __next = std::next(__i.base());
565 this->_M_transfer_from_if(__list, [__next](_Base_const_iterator __it)
566 { return __it == __next; });
567 _Base::splice_after(__pos.base(), std::move(__list._M_base()),
572 splice_after(const_iterator __pos, forward_list& __list,
574 { splice_after(__pos, std::move(__list), __i); }
577 splice_after(const_iterator __pos, forward_list&& __list,
578 const_iterator __before, const_iterator __last)
580 __glibcxx_check_insert_after(__pos);
581 __glibcxx_check_valid_range(__before, __last);
582 _GLIBCXX_DEBUG_VERIFY(__before._M_attached_to(&__list),
583 _M_message(__gnu_debug::__msg_splice_other)
584 ._M_sequence(__list, "list")
585 ._M_iterator(__before, "before"));
586 _GLIBCXX_DEBUG_VERIFY(__before._M_dereferenceable()
587 || __before._M_is_before_begin(),
588 _M_message(__gnu_debug::__msg_valid_range2)
589 ._M_sequence(__list, "list")
590 ._M_iterator(__before, "before")
591 ._M_iterator(__last, "last"));
592 _GLIBCXX_DEBUG_VERIFY(__before != __last,
593 _M_message(__gnu_debug::__msg_valid_range2)
594 ._M_sequence(__list, "list")
595 ._M_iterator(__before, "before")
596 ._M_iterator(__last, "last"));
597 _GLIBCXX_DEBUG_VERIFY(__list.get_allocator() == this->get_allocator(),
598 _M_message(__gnu_debug::__msg_splice_alloc)
600 ._M_sequence(__list, "__list"));
602 for (_Base_const_iterator __tmp = std::next(__before.base());
603 __tmp != __last.base(); ++__tmp)
605 _GLIBCXX_DEBUG_VERIFY(__tmp != __list._M_base().end(),
606 _M_message(__gnu_debug::__msg_valid_range2)
607 ._M_sequence(__list, "list")
608 ._M_iterator(__before, "before")
609 ._M_iterator(__last, "last"));
610 _GLIBCXX_DEBUG_VERIFY(&__list != this || __tmp != __pos.base(),
611 _M_message(__gnu_debug::__msg_splice_overlap)
612 ._M_iterator(__tmp, "position")
613 ._M_iterator(__before, "before")
614 ._M_iterator(__last, "last"));
615 // _GLIBCXX_RESOLVE_LIB_DEFECTS
616 // 250. splicing invalidates iterators
617 this->_M_transfer_from_if(__list, [__tmp](_Base_const_iterator __it)
618 { return __it == __tmp; });
621 _Base::splice_after(__pos.base(), std::move(__list._M_base()),
622 __before.base(), __last.base());
626 splice_after(const_iterator __pos, forward_list& __list,
627 const_iterator __before, const_iterator __last)
628 { splice_after(__pos, std::move(__list), __before, __last); }
631 remove(const _Tp& __val)
633 _Base_iterator __x = _Base::before_begin();
634 _Base_iterator __old = __x++;
635 while (__x != _Base::end())
638 __x = _M_erase_after(__old);
644 template<typename _Pred>
646 remove_if(_Pred __pred)
648 _Base_iterator __x = _Base::before_begin();
649 _Base_iterator __old = __x++;
650 while (__x != _Base::end())
653 __x = _M_erase_after(__old);
662 _Base_iterator __first = _Base::begin();
663 _Base_iterator __last = _Base::end();
664 if (__first == __last)
666 _Base_iterator __next = std::next(__first);
667 while (__next != __last)
669 if (*__first == *__next)
670 __next = _M_erase_after(__first);
676 template<typename _BinPred>
678 unique(_BinPred __binary_pred)
680 _Base_iterator __first = _Base::begin();
681 _Base_iterator __last = _Base::end();
682 if (__first == __last)
684 _Base_iterator __next = std::next(__first);
685 while (__next != __last)
687 if (__binary_pred(*__first, *__next))
688 __next = _M_erase_after(__first);
695 merge(forward_list&& __list)
699 __glibcxx_check_sorted(_Base::begin(), _Base::end());
700 __glibcxx_check_sorted(__list._M_base().begin(),
701 __list._M_base().end());
702 this->_M_transfer_from_if(__list, [&__list](_Base_const_iterator __it)
704 return __it != __list._M_base().cbefore_begin()
705 && __it != __list._M_base().cend();
707 _Base::merge(std::move(__list._M_base()));
712 merge(forward_list& __list)
713 { merge(std::move(__list)); }
715 template<typename _Comp>
717 merge(forward_list&& __list, _Comp __comp)
721 __glibcxx_check_sorted_pred(_Base::begin(), _Base::end(), __comp);
722 __glibcxx_check_sorted_pred(__list._M_base().begin(),
723 __list._M_base().end(), __comp);
724 this->_M_transfer_from_if(__list,
725 [&__list](_Base_const_iterator __it)
727 return __it != __list._M_base().cbefore_begin()
728 && __it != __list._M_base().cend();
730 _Base::merge(std::move(__list._M_base()), __comp);
734 template<typename _Comp>
736 merge(forward_list& __list, _Comp __comp)
737 { merge(std::move(__list), __comp); }
740 using _Base::reverse;
743 _M_base() noexcept { return *this; }
746 _M_base() const noexcept { return *this; }
749 template<typename _Tp, typename _Alloc>
751 operator==(const forward_list<_Tp, _Alloc>& __lx,
752 const forward_list<_Tp, _Alloc>& __ly)
753 { return __lx._M_base() == __ly._M_base(); }
755 template<typename _Tp, typename _Alloc>
757 operator<(const forward_list<_Tp, _Alloc>& __lx,
758 const forward_list<_Tp, _Alloc>& __ly)
759 { return __lx._M_base() < __ly._M_base(); }
761 template<typename _Tp, typename _Alloc>
763 operator!=(const forward_list<_Tp, _Alloc>& __lx,
764 const forward_list<_Tp, _Alloc>& __ly)
765 { return !(__lx == __ly); }
767 /// Based on operator<
768 template<typename _Tp, typename _Alloc>
770 operator>(const forward_list<_Tp, _Alloc>& __lx,
771 const forward_list<_Tp, _Alloc>& __ly)
772 { return (__ly < __lx); }
774 /// Based on operator<
775 template<typename _Tp, typename _Alloc>
777 operator>=(const forward_list<_Tp, _Alloc>& __lx,
778 const forward_list<_Tp, _Alloc>& __ly)
779 { return !(__lx < __ly); }
781 /// Based on operator<
782 template<typename _Tp, typename _Alloc>
784 operator<=(const forward_list<_Tp, _Alloc>& __lx,
785 const forward_list<_Tp, _Alloc>& __ly)
786 { return !(__ly < __lx); }
788 /// See std::forward_list::swap().
789 template<typename _Tp, typename _Alloc>
791 swap(forward_list<_Tp, _Alloc>& __lx,
792 forward_list<_Tp, _Alloc>& __ly)
795 } // namespace __debug
798 namespace __gnu_debug
800 template<class _Tp, class _Alloc>
801 struct _BeforeBeginHelper<std::__debug::forward_list<_Tp, _Alloc> >
803 typedef std::__debug::forward_list<_Tp, _Alloc> _Sequence;
805 template<typename _Iterator>
807 _S_Is(const _Safe_iterator<_Iterator, _Sequence>& __it)
810 __it.base() == __it._M_get_sequence()->_M_base().before_begin();
813 template<typename _Iterator>
815 _S_Is_Beginnest(const _Safe_iterator<_Iterator, _Sequence>& __it)
816 { return _S_Is(__it); }
819 #ifndef _GLIBCXX_DEBUG_PEDANTIC
820 template<class _Tp, class _Alloc>
821 struct _Insert_range_from_self_is_safe<
822 std::__debug::forward_list<_Tp, _Alloc> >
823 { enum { __value = 1 }; };