1 // <forward_list> -*- C++ -*-
 
    3 // Copyright (C) 2010-2014 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_iterator.h>
 
   38 namespace std _GLIBCXX_VISIBILITY(default)
 
   42   /// Class std::forward_list with safety/checking/debug instrumentation.
 
   43   template<typename _Tp, typename _Alloc = std::allocator<_Tp> >
 
   45     : public _GLIBCXX_STD_C::forward_list<_Tp, _Alloc>,
 
   46       public __gnu_debug::_Safe_sequence<forward_list<_Tp, _Alloc> >
 
   48       typedef _GLIBCXX_STD_C::forward_list<_Tp, _Alloc> _Base;
 
   50       typedef typename _Base::iterator       _Base_iterator;
 
   51       typedef typename _Base::const_iterator _Base_const_iterator;
 
   53       typedef typename __gnu_cxx::__alloc_traits<_Alloc>::template
 
   54         rebind<_GLIBCXX_STD_C::_Fwd_list_node<_Tp>>::other _Node_alloc_type;
 
   56       typedef __gnu_cxx::__alloc_traits<_Node_alloc_type> _Node_alloc_traits;
 
   59       typedef typename _Base::reference             reference;
 
   60       typedef typename _Base::const_reference       const_reference;
 
   62       typedef __gnu_debug::_Safe_iterator<_Base_iterator,
 
   63                      forward_list> iterator;
 
   64       typedef __gnu_debug::_Safe_iterator<_Base_const_iterator,
 
   65                      forward_list> const_iterator;
 
   67       typedef typename _Base::size_type             size_type;
 
   68       typedef typename _Base::difference_type       difference_type;
 
   70       typedef _Tp                                   value_type;
 
   71       typedef _Alloc                                allocator_type;
 
   72       typedef typename _Base::pointer               pointer;
 
   73       typedef typename _Base::const_pointer         const_pointer;
 
   75       // 23.2.3.1 construct/copy/destroy:
 
   77       forward_list(const _Alloc& __al = _Alloc())
 
   80       forward_list(const forward_list& __list, const _Alloc& __al)
 
   84       forward_list(forward_list&& __list, const _Alloc& __al)
 
   85       : _Base(std::move(__list._M_base()), __al)
 
   87    if (__list.get_allocator() == __al)
 
   88      this->_M_swap(__list);
 
   90      __list._M_invalidate_all();
 
   94       forward_list(size_type __n, const _Alloc& __al = _Alloc())
 
   98       forward_list(size_type __n, const _Tp& __value,
 
   99                    const _Alloc& __al = _Alloc())
 
  100       : _Base(__n, __value, __al)
 
  103       template<typename _InputIterator,
 
  104           typename = std::_RequireInputIter<_InputIterator>>
 
  105    forward_list(_InputIterator __first, _InputIterator __last,
 
  106                      const _Alloc& __al = _Alloc())
 
  107         : _Base(__gnu_debug::__base(__gnu_debug::__check_valid_range(__first,
 
  109        __gnu_debug::__base(__last), __al)
 
  112       forward_list(const forward_list& __list)
 
  116       forward_list(forward_list&& __list) noexcept
 
  117       : _Base(std::move(__list._M_base()))
 
  119    this->_M_swap(__list);
 
  122       forward_list(std::initializer_list<_Tp> __il,
 
  123                    const _Alloc& __al = _Alloc())
 
  127       ~forward_list() noexcept
 
  131       operator=(const forward_list& __list)
 
  133    static_cast<_Base&>(*this) = __list;
 
  134    this->_M_invalidate_all();
 
  139       operator=(forward_list&& __list)
 
  140       noexcept(_Node_alloc_traits::_S_nothrow_move())
 
  142    __glibcxx_check_self_move_assign(__list);
 
  143    bool __xfer_memory = _Node_alloc_traits::_S_propagate_on_move_assign()
 
  144        || __list.get_allocator() == this->get_allocator();
 
  145    static_cast<_Base&>(*this) = std::move(__list);
 
  147      this->_M_swap(__list);
 
  149      this->_M_invalidate_all();
 
  150    __list._M_invalidate_all();
 
  155       operator=(std::initializer_list<_Tp> __il)
 
  157    static_cast<_Base&>(*this) = __il;
 
  158    this->_M_invalidate_all();
 
  162       template<typename _InputIterator,
 
  163           typename = std::_RequireInputIter<_InputIterator>>
 
  165         assign(_InputIterator __first, _InputIterator __last)
 
  167      __glibcxx_check_valid_range(__first, __last);
 
  168      _Base::assign(__gnu_debug::__base(__first),
 
  169            __gnu_debug::__base(__last));
 
  170      this->_M_invalidate_all();
 
  174       assign(size_type __n, const _Tp& __val)
 
  176    _Base::assign(__n, __val);
 
  177    this->_M_invalidate_all();
 
  181       assign(std::initializer_list<_Tp> __il)
 
  184    this->_M_invalidate_all();
 
  187       using _Base::get_allocator;
 
  192       before_begin() noexcept
 
  193       { return iterator(_Base::before_begin(), this); }
 
  196       before_begin() const noexcept
 
  197       { return const_iterator(_Base::before_begin(), this); }
 
  201       { return iterator(_Base::begin(), this); }
 
  204       begin() const noexcept
 
  205       { return const_iterator(_Base::begin(), this); }
 
  209       { return iterator(_Base::end(), this); }
 
  213       { return const_iterator(_Base::end(), this); }
 
  216       cbegin() const noexcept
 
  217       { return const_iterator(_Base::cbegin(), this); }
 
  220       cbefore_begin() const noexcept
 
  221       { return const_iterator(_Base::cbefore_begin(), this); }
 
  224       cend() const noexcept
 
  225       { return const_iterator(_Base::cend(), this); }
 
  228       using _Base::max_size;
 
  235    __glibcxx_check_nonempty();
 
  236    return _Base::front();
 
  242    __glibcxx_check_nonempty();
 
  243    return _Base::front();
 
  248       using _Base::emplace_front;
 
  249       using _Base::push_front;
 
  254    __glibcxx_check_nonempty();
 
  255    this->_M_invalidate_if([this](_Base_const_iterator __it)
 
  256      { return __it == this->_M_base().cbegin(); });
 
  260       template<typename... _Args>
 
  262    emplace_after(const_iterator __pos, _Args&&... __args)
 
  264      __glibcxx_check_insert_after(__pos);
 
  265      return iterator(_Base::emplace_after(__pos.base(),
 
  266                    std::forward<_Args>(__args)...),
 
  271       insert_after(const_iterator __pos, const _Tp& __val)
 
  273    __glibcxx_check_insert_after(__pos);
 
  274    return iterator(_Base::insert_after(__pos.base(), __val), this);
 
  278       insert_after(const_iterator __pos, _Tp&& __val)
 
  280    __glibcxx_check_insert_after(__pos);
 
  281    return iterator(_Base::insert_after(__pos.base(), std::move(__val)),
 
  286       insert_after(const_iterator __pos, size_type __n, const _Tp& __val)
 
  288    __glibcxx_check_insert_after(__pos);
 
  289    return iterator(_Base::insert_after(__pos.base(), __n, __val),
 
  293       template<typename _InputIterator,
 
  294           typename = std::_RequireInputIter<_InputIterator>>
 
  296         insert_after(const_iterator __pos,
 
  297                      _InputIterator __first, _InputIterator __last)
 
  299      __glibcxx_check_insert_range_after(__pos, __first, __last);
 
  300      return iterator(_Base::insert_after(__pos.base(),
 
  301                          __gnu_debug::__base(__first),
 
  302                          __gnu_debug::__base(__last)),
 
  307       insert_after(const_iterator __pos, std::initializer_list<_Tp> __il)
 
  309    __glibcxx_check_insert_after(__pos);
 
  310    return iterator(_Base::insert_after(__pos.base(), __il), this);
 
  315       _M_erase_after(_Base_const_iterator __pos)
 
  317    _Base_const_iterator __next = std::next(__pos);
 
  318    this->_M_invalidate_if([__next](_Base_const_iterator __it)
 
  319      { return __it == __next; });
 
  320    return _Base::erase_after(__pos);
 
  324       erase_after(const_iterator __pos)
 
  326    __glibcxx_check_erase_after(__pos);
 
  327    return iterator(_M_erase_after(__pos.base()), this);
 
  331       erase_after(const_iterator __pos, const_iterator __last)
 
  333    __glibcxx_check_erase_range_after(__pos, __last);
 
  334    for (_Base_const_iterator __victim = std::next(__pos.base());
 
  335        __victim != __last.base(); ++__victim)
 
  337        _GLIBCXX_DEBUG_VERIFY(__victim != _Base::end(),
 
  338                  _M_message(__gnu_debug::__msg_valid_range2)
 
  339                  ._M_sequence(*this, "this")
 
  340                  ._M_iterator(__pos, "pos")
 
  341                  ._M_iterator(__last, "last"));
 
  342        this->_M_invalidate_if([__victim](_Base_const_iterator __it)
 
  343          { return __it == __victim; });
 
  345    return iterator(_Base::erase_after(__pos.base(), __last.base()), this);
 
  349       swap(forward_list& __list)
 
  350       noexcept(_Node_alloc_traits::_S_nothrow_swap())
 
  352    if (!_Node_alloc_traits::_S_propagate_on_swap())
 
  353      __glibcxx_check_equal_allocs(__list);
 
  355    this->_M_swap(__list);
 
  359       resize(size_type __sz)
 
  361    this->_M_detach_singular();
 
  363    // if __sz < size(), invalidate all iterators in [begin+__sz, end()
 
  364    _Base_iterator __victim = _Base::begin();
 
  365    _Base_iterator __end = _Base::end();
 
  366    for (size_type __i = __sz; __victim != __end && __i > 0; --__i)
 
  369    for (; __victim != __end; ++__victim)
 
  371        this->_M_invalidate_if([__victim](_Base_const_iterator __it)
 
  372          { return __it == __victim; });
 
  381        this->_M_revalidate_singular();
 
  382        __throw_exception_again;
 
  387       resize(size_type __sz, const value_type& __val)
 
  389    this->_M_detach_singular();
 
  391    // if __sz < size(), invalidate all iterators in [begin+__sz, end())
 
  392    _Base_iterator __victim = _Base::begin();
 
  393    _Base_iterator __end = _Base::end();
 
  394    for (size_type __i = __sz; __victim != __end && __i > 0; --__i)
 
  397    for (; __victim != __end; ++__victim)
 
  399        this->_M_invalidate_if([__victim](_Base_const_iterator __it)
 
  400          { return __it == __victim; });
 
  405        _Base::resize(__sz, __val);
 
  409        this->_M_revalidate_singular();
 
  410        __throw_exception_again;
 
  418    this->_M_invalidate_all();
 
  421       // 23.2.3.5 forward_list operations:
 
  423       splice_after(const_iterator __pos, forward_list&& __list)
 
  425         __glibcxx_check_insert_after(__pos);
 
  426    _GLIBCXX_DEBUG_VERIFY(&__list != this,
 
  427                  _M_message(__gnu_debug::__msg_self_splice)
 
  428                  ._M_sequence(*this, "this"));
 
  429    _GLIBCXX_DEBUG_VERIFY(__list.get_allocator() == this->get_allocator(),
 
  430                  _M_message(__gnu_debug::__msg_splice_alloc)
 
  432                  ._M_sequence(__list, "__list"));
 
  433    this->_M_transfer_from_if(__list, [&__list](_Base_const_iterator __it)
 
  435        return __it != __list._M_base().cbefore_begin()
 
  436           && __it != __list._M_base().end();
 
  438    _Base::splice_after(__pos.base(), std::move(__list._M_base()));
 
  442       splice_after(const_iterator __pos, forward_list& __list)
 
  443       { splice_after(__pos, std::move(__list)); }
 
  446       splice_after(const_iterator __pos, forward_list&& __list,
 
  449    __glibcxx_check_insert_after(__pos);
 
  450    _GLIBCXX_DEBUG_VERIFY(__i._M_before_dereferenceable(),
 
  451                  _M_message(__gnu_debug::__msg_splice_bad)
 
  452                  ._M_iterator(__i, "__i"));
 
  453    _GLIBCXX_DEBUG_VERIFY(__i._M_attached_to(&__list),
 
  454                  _M_message(__gnu_debug::__msg_splice_other)
 
  455                  ._M_iterator(__i, "__i")
 
  456                  ._M_sequence(__list, "__list"));
 
  457    _GLIBCXX_DEBUG_VERIFY(__list.get_allocator() == this->get_allocator(),
 
  458                  _M_message(__gnu_debug::__msg_splice_alloc)
 
  460                  ._M_sequence(__list, "__list"));
 
  462    // _GLIBCXX_RESOLVE_LIB_DEFECTS
 
  463    // 250. splicing invalidates iterators
 
  464    _Base_const_iterator __next = std::next(__i.base());
 
  465    this->_M_transfer_from_if(__list, [__next](_Base_const_iterator __it)
 
  466      { return __it == __next; });
 
  467    _Base::splice_after(__pos.base(), std::move(__list._M_base()),
 
  472       splice_after(const_iterator __pos, forward_list& __list,
 
  474       { splice_after(__pos, std::move(__list), __i); }
 
  477       splice_after(const_iterator __pos, forward_list&& __list,
 
  478           const_iterator __before, const_iterator __last)
 
  480         __glibcxx_check_insert_after(__pos);
 
  481    __glibcxx_check_valid_range(__before, __last);
 
  482    _GLIBCXX_DEBUG_VERIFY(__before._M_attached_to(&__list),
 
  483                  _M_message(__gnu_debug::__msg_splice_other)
 
  484                  ._M_sequence(__list, "list")
 
  485                  ._M_iterator(__before, "before"));
 
  486    _GLIBCXX_DEBUG_VERIFY(__before._M_dereferenceable()
 
  487                  || __before._M_is_before_begin(),
 
  488                  _M_message(__gnu_debug::__msg_valid_range2)
 
  489                  ._M_sequence(__list, "list")
 
  490                  ._M_iterator(__before, "before")
 
  491                  ._M_iterator(__last, "last"));
 
  492    _GLIBCXX_DEBUG_VERIFY(__before != __last,
 
  493                  _M_message(__gnu_debug::__msg_valid_range2)
 
  494                  ._M_sequence(__list, "list")
 
  495                  ._M_iterator(__before, "before")
 
  496                  ._M_iterator(__last, "last"));
 
  497    _GLIBCXX_DEBUG_VERIFY(__list.get_allocator() == this->get_allocator(),
 
  498                  _M_message(__gnu_debug::__msg_splice_alloc)
 
  500                  ._M_sequence(__list, "__list"));
 
  502    for (_Base_const_iterator __tmp = std::next(__before.base());
 
  503         __tmp != __last.base(); ++__tmp)
 
  505        _GLIBCXX_DEBUG_VERIFY(__tmp != __list._M_base().end(),
 
  506                  _M_message(__gnu_debug::__msg_valid_range2)
 
  507                  ._M_sequence(__list, "list")
 
  508                  ._M_iterator(__before, "before")
 
  509                  ._M_iterator(__last, "last"));
 
  510        _GLIBCXX_DEBUG_VERIFY(&__list != this || __tmp != __pos.base(),
 
  511                                   _M_message(__gnu_debug::__msg_splice_overlap)
 
  512                                   ._M_iterator(__tmp, "position")
 
  513                  ._M_iterator(__before, "before")
 
  514                  ._M_iterator(__last, "last"));
 
  515        // _GLIBCXX_RESOLVE_LIB_DEFECTS
 
  516        // 250. splicing invalidates iterators
 
  517        this->_M_transfer_from_if(__list, [__tmp](_Base_const_iterator __it)
 
  518          { return __it == __tmp; });
 
  521    _Base::splice_after(__pos.base(), std::move(__list._M_base()),
 
  522                __before.base(), __last.base());
 
  526       splice_after(const_iterator __pos, forward_list& __list,
 
  527           const_iterator __before, const_iterator __last)
 
  528       { splice_after(__pos, std::move(__list), __before, __last); }
 
  531       remove(const _Tp& __val)
 
  533    _Base_iterator __x = _Base::before_begin();
 
  534    _Base_iterator __old = __x++;
 
  535    while (__x != _Base::end())
 
  538          __x = _M_erase_after(__old);
 
  544       template<typename _Pred>
 
  546         remove_if(_Pred __pred)
 
  548      _Base_iterator __x = _Base::before_begin();
 
  549      _Base_iterator __old = __x++;
 
  550      while (__x != _Base::end())
 
  553        __x = _M_erase_after(__old);
 
  562    _Base_iterator __first = _Base::begin();
 
  563    _Base_iterator __last = _Base::end();
 
  564    if (__first == __last)
 
  566    _Base_iterator __next = std::next(__first);
 
  567    while (__next != __last)
 
  569        if (*__first == *__next)
 
  570          __next = _M_erase_after(__first);
 
  576       template<typename _BinPred>
 
  578         unique(_BinPred __binary_pred)
 
  580      _Base_iterator __first = _Base::begin();
 
  581      _Base_iterator __last = _Base::end();
 
  582      if (__first == __last)
 
  584      _Base_iterator __next = std::next(__first);
 
  585      while (__next != __last)
 
  587          if (__binary_pred(*__first, *__next))
 
  588        __next = _M_erase_after(__first);
 
  595       merge(forward_list&& __list)
 
  599      __glibcxx_check_sorted(_Base::begin(), _Base::end());
 
  600      __glibcxx_check_sorted(__list._M_base().begin(),
 
  601                 __list._M_base().end());
 
  602      this->_M_transfer_from_if(__list, [&__list](_Base_const_iterator __it)
 
  604          return __it != __list._M_base().cbefore_begin()
 
  605             && __it != __list._M_base().cend();
 
  607      _Base::merge(std::move(__list._M_base()));
 
  612       merge(forward_list& __list)
 
  613       { merge(std::move(__list)); }
 
  615       template<typename _Comp>
 
  617         merge(forward_list&& __list, _Comp __comp)
 
  621        __glibcxx_check_sorted_pred(_Base::begin(), _Base::end(), __comp);
 
  622        __glibcxx_check_sorted_pred(__list._M_base().begin(),
 
  623                    __list._M_base().end(), __comp);
 
  624        this->_M_transfer_from_if(__list,
 
  625                      [&__list](_Base_const_iterator __it)
 
  627            return __it != __list._M_base().cbefore_begin()
 
  628               && __it != __list._M_base().cend();
 
  630        _Base::merge(std::move(__list._M_base()), __comp);
 
  634       template<typename _Comp>
 
  636         merge(forward_list& __list, _Comp __comp)
 
  637         { merge(std::move(__list), __comp); }
 
  640       using _Base::reverse;
 
  643       _M_base() noexcept       { return *this; }
 
  646       _M_base() const noexcept { return *this; }
 
  652    this->_M_invalidate_if([this](_Base_const_iterator __it)
 
  654        return __it != this->_M_base().cbefore_begin()
 
  655           && __it != this->_M_base().cend();
 
  658       typedef __gnu_debug::_Safe_iterator_base _Safe_iterator_base;
 
  660       _M_swap_aux(forward_list& __lhs,
 
  661          _Safe_iterator_base*& __lhs_iterators,
 
  663          _Safe_iterator_base*& __rhs_iterators);
 
  664       void _M_swap(forward_list& __list);
 
  667    template<typename _Tp, typename _Alloc>
 
  669     forward_list<_Tp, _Alloc>::
 
  670     _M_swap_aux(forward_list<_Tp, _Alloc>& __lhs,
 
  671        __gnu_debug::_Safe_iterator_base*& __lhs_iterators,
 
  672        forward_list<_Tp, _Alloc>& __rhs,
 
  673        __gnu_debug::_Safe_iterator_base*& __rhs_iterators)
 
  675       using __gnu_debug::_Safe_iterator_base;
 
  676       _Safe_iterator_base* __bbegin_its = 0;
 
  677       _Safe_iterator_base* __last_bbegin = 0;
 
  678       for (_Safe_iterator_base* __iter = __lhs_iterators; __iter;)
 
  680      // Even iterator are casted to const_iterator, not a problem.
 
  681      const_iterator* __victim = static_cast<const_iterator*>(__iter);
 
  682      __iter = __iter->_M_next;
 
  683      if (__victim->base() == __rhs._M_base().cbefore_begin())
 
  685          __victim->_M_unlink();
 
  686          if (__lhs_iterators == __victim)
 
  687        __lhs_iterators = __victim->_M_next;
 
  690          __victim->_M_next = __bbegin_its;
 
  691          __bbegin_its->_M_prior = __victim;
 
  694        __last_bbegin = __victim;
 
  695          __bbegin_its = __victim;
 
  698        __victim->_M_sequence = &__lhs;
 
  705          __rhs_iterators->_M_prior = __last_bbegin;
 
  706          __last_bbegin->_M_next = __rhs_iterators;
 
  708      __rhs_iterators = __bbegin_its;
 
  712   /* Special forward_list _M_swap version that do not swap the
 
  713    * before-begin ownership.*/
 
  714   template<typename _Tp, typename _Alloc>
 
  716     forward_list<_Tp, _Alloc>::
 
  717     _M_swap(forward_list<_Tp, _Alloc>& __list)
 
  719       __gnu_cxx::__scoped_lock sentry(this->_M_get_mutex());
 
  720       std::swap(this->_M_iterators, __list._M_iterators);
 
  721       std::swap(this->_M_const_iterators, __list._M_const_iterators);
 
  722       // Useless, always 1 on forward_list
 
  723       //std::swap(this->_M_version, __list._M_version);
 
  724       _Safe_iterator_base* __this_its = this->_M_iterators;
 
  725       _M_swap_aux(__list, __list._M_iterators, *this, this->_M_iterators);
 
  726       _Safe_iterator_base* __this_const_its = this->_M_const_iterators;
 
  727       _M_swap_aux(__list, __list._M_const_iterators, *this,
 
  728          this->_M_const_iterators);
 
  729       _M_swap_aux(*this, __this_its, __list, __list._M_iterators);
 
  730       _M_swap_aux(*this, __this_const_its, __list, __list._M_const_iterators);
 
  733   template<typename _Tp, typename _Alloc>
 
  735     operator==(const forward_list<_Tp, _Alloc>& __lx,
 
  736                const forward_list<_Tp, _Alloc>& __ly)
 
  737     { return __lx._M_base() == __ly._M_base(); }
 
  739   template<typename _Tp, typename _Alloc>
 
  741     operator<(const forward_list<_Tp, _Alloc>& __lx,
 
  742               const forward_list<_Tp, _Alloc>& __ly)
 
  743     { return __lx._M_base() < __ly._M_base(); }
 
  745   template<typename _Tp, typename _Alloc>
 
  747     operator!=(const forward_list<_Tp, _Alloc>& __lx,
 
  748                const forward_list<_Tp, _Alloc>& __ly)
 
  749     { return !(__lx == __ly); }
 
  751   /// Based on operator<
 
  752   template<typename _Tp, typename _Alloc>
 
  754     operator>(const forward_list<_Tp, _Alloc>& __lx,
 
  755               const forward_list<_Tp, _Alloc>& __ly)
 
  756     { return (__ly < __lx); }
 
  758   /// Based on operator<
 
  759   template<typename _Tp, typename _Alloc>
 
  761     operator>=(const forward_list<_Tp, _Alloc>& __lx,
 
  762                const forward_list<_Tp, _Alloc>& __ly)
 
  763     { return !(__lx < __ly); }
 
  765   /// Based on operator<
 
  766   template<typename _Tp, typename _Alloc>
 
  768     operator<=(const forward_list<_Tp, _Alloc>& __lx,
 
  769                const forward_list<_Tp, _Alloc>& __ly)
 
  770     { return !(__ly < __lx); }
 
  772   /// See std::forward_list::swap().
 
  773   template<typename _Tp, typename _Alloc>
 
  775     swap(forward_list<_Tp, _Alloc>& __lx,
 
  776     forward_list<_Tp, _Alloc>& __ly)
 
  779 } // namespace __debug
 
  782 namespace __gnu_debug
 
  784   template<class _Tp, class _Alloc>
 
  785     struct _BeforeBeginHelper<std::__debug::forward_list<_Tp, _Alloc> >
 
  787       typedef std::__debug::forward_list<_Tp, _Alloc> _Sequence;
 
  789       template<typename _Iterator>
 
  791    _S_Is(const _Safe_iterator<_Iterator, _Sequence>& __it)
 
  794        __it.base() == __it._M_get_sequence()->_M_base().before_begin();
 
  797       template<typename _Iterator>
 
  799    _S_Is_Beginnest(const _Safe_iterator<_Iterator, _Sequence>& __it)
 
  800    { return _S_Is(__it); }
 
  803 #ifndef _GLIBCXX_DEBUG_PEDANTIC
 
  804   template<class _Tp, class _Alloc>
 
  805     struct _Insert_range_from_self_is_safe<
 
  806       std::__debug::forward_list<_Tp, _Alloc> >
 
  807     { enum { __value = 1 }; };