Home | History | Annotate | Download | only in debug
      1 // <forward_list> -*- C++ -*-
      2 
      3 // Copyright (C) 2010 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/forward_list
     26  *  This file is a GNU debug extension to the Standard C++ Library.
     27  */
     28 
     29 #ifndef _GLIBCXX_DEBUG_FORWARD_LIST
     30 #define _GLIBCXX_DEBUG_FORWARD_LIST 1
     31 
     32 #pragma GCC system_header
     33 
     34 #include <forward_list>
     35 #include <debug/safe_sequence.h>
     36 #include <debug/safe_iterator.h>
     37 
     38 namespace std _GLIBCXX_VISIBILITY(default)
     39 {
     40 namespace __debug
     41 {
     42   /// Class std::forward_list with safety/checking/debug instrumentation.
     43   template<typename _Tp, typename _Alloc = std::allocator<_Tp> >
     44     class forward_list
     45     : public _GLIBCXX_STD_C::forward_list<_Tp, _Alloc>,
     46       public __gnu_debug::_Safe_sequence<forward_list<_Tp, _Alloc> >
     47     {
     48       typedef _GLIBCXX_STD_C::forward_list<_Tp, _Alloc> _Base;
     49 
     50       typedef typename _Base::iterator       _Base_iterator;
     51       typedef typename _Base::const_iterator _Base_const_iterator;
     52     public:
     53       typedef typename _Base::reference             reference;
     54       typedef typename _Base::const_reference       const_reference;
     55 
     56       typedef __gnu_debug::_Safe_iterator<_Base_iterator,
     57 					  forward_list> iterator;
     58       typedef __gnu_debug::_Safe_iterator<_Base_const_iterator,
     59 					  forward_list> const_iterator;
     60 
     61       typedef typename _Base::size_type             size_type;
     62       typedef typename _Base::difference_type       difference_type;
     63 
     64       typedef _Tp                                   value_type;
     65       typedef _Alloc                                allocator_type;
     66       typedef typename _Base::pointer               pointer;
     67       typedef typename _Base::const_pointer         const_pointer;
     68 
     69       // 23.2.3.1 construct/copy/destroy:
     70       explicit
     71       forward_list(const _Alloc& __al = _Alloc())
     72       : _Base(__al) { }
     73 
     74       forward_list(const forward_list& __list, const _Alloc& __al)
     75       : _Base(__list, __al)
     76       { }
     77 
     78       forward_list(forward_list&& __list, const _Alloc& __al)
     79       : _Base(std::move(__list._M_base()), __al)
     80       {
     81 	this->_M_swap(__list);
     82       }
     83 
     84       explicit
     85       forward_list(size_type __n)
     86       : _Base(__n)
     87       { }
     88 
     89       forward_list(size_type __n, const _Tp& __value,
     90                    const _Alloc& __al = _Alloc())
     91       : _Base(__n, __value, __al)
     92       { }
     93 
     94       template<typename _InputIterator>
     95         forward_list(_InputIterator __first, _InputIterator __last,
     96                      const _Alloc& __al = _Alloc())
     97         : _Base(__gnu_debug::__base(__gnu_debug::__check_valid_range(__first,
     98 								     __last)),
     99 		__gnu_debug::__base(__last), __al)
    100         { }
    101 
    102       forward_list(const forward_list& __list)
    103       : _Base(__list)
    104       { }
    105 
    106       forward_list(forward_list&& __list) noexcept
    107       : _Base(std::move(__list._M_base()))
    108       {
    109 	this->_M_swap(__list);
    110       }
    111 
    112       forward_list(std::initializer_list<_Tp> __il,
    113                    const _Alloc& __al = _Alloc())
    114       : _Base(__il, __al)
    115       { }
    116 
    117       ~forward_list() noexcept
    118       { }
    119 
    120       forward_list&
    121       operator=(const forward_list& __list)
    122       {
    123 	static_cast<_Base&>(*this) = __list;
    124 	this->_M_invalidate_all();
    125 	return *this;
    126       }
    127 
    128       forward_list&
    129       operator=(forward_list&& __list)
    130       {
    131 	// NB: DR 1204.
    132 	// NB: DR 675.
    133 	clear();
    134 	swap(__list);
    135 	return *this;
    136       }
    137 
    138       forward_list&
    139       operator=(std::initializer_list<_Tp> __il)
    140       {
    141 	static_cast<_Base&>(*this) = __il;
    142 	this->_M_invalidate_all();
    143         return *this;
    144       }
    145 
    146       template<typename _InputIterator>
    147         void
    148         assign(_InputIterator __first, _InputIterator __last)
    149         {
    150 	  __glibcxx_check_valid_range(__first, __last);
    151 	  _Base::assign(__gnu_debug::__base(__first),
    152 			__gnu_debug::__base(__last));
    153 	  this->_M_invalidate_all();
    154         }
    155 
    156       void
    157       assign(size_type __n, const _Tp& __val)
    158       {
    159 	_Base::assign(__n, __val);
    160 	this->_M_invalidate_all();
    161       }
    162 
    163       void
    164       assign(std::initializer_list<_Tp> __il)
    165       {
    166 	_Base::assign(__il);
    167 	this->_M_invalidate_all();
    168       }
    169 
    170       using _Base::get_allocator;
    171 
    172       // iterators:
    173 
    174       iterator
    175       before_begin() noexcept
    176       { return iterator(_Base::before_begin(), this); }
    177 
    178       const_iterator
    179       before_begin() const noexcept
    180       { return const_iterator(_Base::before_begin(), this); }
    181 
    182       iterator
    183       begin() noexcept
    184       { return iterator(_Base::begin(), this); }
    185 
    186       const_iterator
    187       begin() const noexcept
    188       { return const_iterator(_Base::begin(), this); }
    189 
    190       iterator
    191       end() noexcept
    192       { return iterator(_Base::end(), this); }
    193 
    194       const_iterator
    195       end() const noexcept
    196       { return const_iterator(_Base::end(), this); }
    197 
    198       const_iterator
    199       cbegin() const noexcept
    200       { return const_iterator(_Base::cbegin(), this); }
    201 
    202       const_iterator
    203       cbefore_begin() const noexcept
    204       { return const_iterator(_Base::cbefore_begin(), this); }
    205 
    206       const_iterator
    207       cend() const noexcept
    208       { return const_iterator(_Base::cend(), this); }
    209 
    210       using _Base::empty;
    211       using _Base::max_size;
    212 
    213       // element access:
    214 
    215       reference
    216       front()
    217       {
    218 	__glibcxx_check_nonempty();
    219 	return _Base::front();
    220       }
    221 
    222       const_reference
    223       front() const
    224       {
    225 	__glibcxx_check_nonempty();
    226 	return _Base::front();
    227       }
    228 
    229       // modiers:
    230 
    231       using _Base::emplace_front;
    232       using _Base::push_front;
    233 
    234       void
    235       pop_front()
    236       {
    237 	__glibcxx_check_nonempty();
    238 	this->_M_invalidate_if([this](_Base_const_iterator __it)
    239 	  { return __it == this->_M_base().cbegin(); });
    240 	_Base::pop_front();
    241       }
    242 
    243       template<typename... _Args>
    244 	iterator
    245 	emplace_after(const_iterator __pos, _Args&&... __args)
    246 	{
    247 	  __glibcxx_check_insert_after(__pos);
    248 	  return iterator(_Base::emplace_after(__pos.base(),
    249 					std::forward<_Args>(__args)...),
    250 			  this);
    251        	}
    252 
    253       iterator
    254       insert_after(const_iterator __pos, const _Tp& __val)
    255       {
    256 	__glibcxx_check_insert_after(__pos);
    257 	return iterator(_Base::insert_after(__pos.base(), __val), this);
    258       }
    259 
    260       iterator
    261       insert_after(const_iterator __pos, _Tp&& __val)
    262       {
    263 	__glibcxx_check_insert_after(__pos);
    264 	return iterator(_Base::insert_after(__pos.base(), std::move(__val)),
    265 		       	this);
    266       }
    267 
    268       iterator
    269       insert_after(const_iterator __pos, size_type __n, const _Tp& __val)
    270       {
    271 	__glibcxx_check_insert_after(__pos);
    272 	return iterator(_Base::insert_after(__pos.base(), __n, __val),
    273 		       	this);
    274       }
    275 
    276       template<typename _InputIterator>
    277         iterator
    278         insert_after(const_iterator __pos,
    279                      _InputIterator __first, _InputIterator __last)
    280         {
    281 	  __glibcxx_check_insert_range_after(__pos, __first, __last);
    282 	  return iterator(_Base::insert_after(__pos.base(),
    283 					      __gnu_debug::__base(__first),
    284 					      __gnu_debug::__base(__last)),
    285 			  this);
    286         }
    287 
    288       iterator
    289       insert_after(const_iterator __pos, std::initializer_list<_Tp> __il)
    290       {
    291 	__glibcxx_check_insert_after(__pos);
    292 	return iterator(_Base::insert_after(__pos.base(), __il), this);
    293       }
    294 
    295     private:
    296       _Base_iterator
    297       _M_erase_after(_Base_const_iterator __pos)
    298       {
    299 	_Base_const_iterator __next = std::next(__pos);
    300 	this->_M_invalidate_if([__next](_Base_const_iterator __it)
    301 	  { return __it == __next; });
    302 	return _Base::erase_after(__pos);
    303       }
    304     public:
    305       iterator
    306       erase_after(const_iterator __pos)
    307       {
    308 	__glibcxx_check_erase_after(__pos);
    309 	return iterator(_M_erase_after(__pos.base()), this);
    310       }
    311 
    312       iterator
    313       erase_after(const_iterator __pos, const_iterator __last)
    314       {
    315 	__glibcxx_check_erase_range_after(__pos, __last);
    316 	for (_Base_const_iterator __victim = std::next(__pos.base());
    317 	    __victim != __last.base(); ++__victim)
    318 	  {
    319 	    _GLIBCXX_DEBUG_VERIFY(__victim != _Base::end(),
    320 				  _M_message(__gnu_debug::__msg_valid_range2)
    321 				  ._M_sequence(*this, "this")
    322 				  ._M_iterator(__pos, "pos")
    323 				  ._M_iterator(__last, "last"));
    324 	    this->_M_invalidate_if([__victim](_Base_const_iterator __it)
    325 	      { return __it == __victim; });
    326 	  }
    327 	return iterator(_Base::erase_after(__pos.base(), __last.base()), this);
    328       }
    329 
    330       void
    331       swap(forward_list& __list)
    332       {
    333 	_Base::swap(__list);
    334 	this->_M_swap(__list);
    335       }
    336 
    337       void
    338       resize(size_type __sz)
    339       {
    340 	this->_M_detach_singular();
    341 
    342 	// if __sz < size(), invalidate all iterators in [begin+__sz, end()
    343 	_Base_iterator __victim = _Base::begin();
    344 	_Base_iterator __end = _Base::end();
    345 	for (size_type __i = __sz; __victim != __end && __i > 0; --__i)
    346 	  ++__victim;
    347 
    348 	for (; __victim != __end; ++__victim)
    349 	  {
    350 	    this->_M_invalidate_if([__victim](_Base_const_iterator __it)
    351 	      { return __it == __victim; });
    352 	  }
    353 
    354 	__try
    355 	  {
    356 	    _Base::resize(__sz);
    357 	  }
    358 	__catch(...)
    359 	  {
    360 	    this->_M_revalidate_singular();
    361 	    __throw_exception_again;
    362           }
    363       }
    364 
    365       void
    366       resize(size_type __sz, const value_type& __val)
    367       {
    368 	this->_M_detach_singular();
    369 
    370 	// if __sz < size(), invalidate all iterators in [begin+__sz, end())
    371 	_Base_iterator __victim = _Base::begin();
    372 	_Base_iterator __end = _Base::end();
    373 	for (size_type __i = __sz; __victim != __end && __i > 0; --__i)
    374 	  ++__victim;
    375 
    376 	for (; __victim != __end; ++__victim)
    377 	  {
    378 	    this->_M_invalidate_if([__victim](_Base_const_iterator __it)
    379 	      { return __it == __victim; });
    380 	  }
    381 
    382 	__try
    383 	  {
    384 	    _Base::resize(__sz, __val);
    385 	  }
    386 	__catch(...)
    387 	  {
    388 	    this->_M_revalidate_singular();
    389 	    __throw_exception_again;
    390           }
    391       }
    392 
    393       void
    394       clear() noexcept
    395       {
    396 	_Base::clear();
    397 	this->_M_invalidate_all();
    398       }
    399 
    400       // 23.2.3.5 forward_list operations:
    401       void
    402       splice_after(const_iterator __pos, forward_list&& __list)
    403       {
    404         __glibcxx_check_insert_after(__pos);
    405 	_GLIBCXX_DEBUG_VERIFY(&__list != this,
    406 			      _M_message(__gnu_debug::__msg_self_splice)
    407 			      ._M_sequence(*this, "this"));
    408 	this->_M_transfer_from_if(__list, [&__list](_Base_const_iterator __it)
    409 	  {
    410 	    return __it != __list._M_base().cbefore_begin()
    411 		   && __it != __list._M_base().end();
    412 	  });
    413 	_Base::splice_after(__pos.base(), std::move(__list._M_base()));
    414       }
    415 
    416       void
    417       splice_after(const_iterator __pos, forward_list& __list)
    418       { splice_after(__pos, std::move(__list)); }
    419 
    420       void
    421       splice_after(const_iterator __pos, forward_list&& __list,
    422 		   const_iterator __i)
    423       {
    424 	__glibcxx_check_insert_after(__pos);
    425 	_GLIBCXX_DEBUG_VERIFY(__i._M_before_dereferenceable(),
    426 			      _M_message(__gnu_debug::__msg_splice_bad)
    427 			      ._M_iterator(__i, "__i"));
    428 	_GLIBCXX_DEBUG_VERIFY(__i._M_attached_to(&__list),
    429 			      _M_message(__gnu_debug::__msg_splice_other)
    430 			      ._M_iterator(__i, "__i")
    431 			      ._M_sequence(__list, "__list"));
    432 
    433 	// _GLIBCXX_RESOLVE_LIB_DEFECTS
    434 	// 250. splicing invalidates iterators
    435 	_Base_const_iterator __next = std::next(__i.base());
    436 	this->_M_transfer_from_if(__list, [__next](_Base_const_iterator __it)
    437 	  { return __it == __next; });
    438 	_Base::splice_after(__pos.base(), std::move(__list._M_base()),
    439 			    __i.base());
    440       }
    441 
    442       void
    443       splice_after(const_iterator __pos, forward_list& __list,
    444 		   const_iterator __i)
    445       { splice_after(__pos, std::move(__list), __i); }
    446 
    447       void
    448       splice_after(const_iterator __pos, forward_list&& __list,
    449 		   const_iterator __before, const_iterator __last)
    450       {
    451         __glibcxx_check_insert_after(__pos);
    452 	__glibcxx_check_valid_range(__before, __last);
    453 	_GLIBCXX_DEBUG_VERIFY(__before._M_attached_to(&__list),
    454 			      _M_message(__gnu_debug::__msg_splice_other)
    455 			      ._M_sequence(__list, "list")
    456 			      ._M_iterator(__before, "before"));
    457 	_GLIBCXX_DEBUG_VERIFY(__before._M_dereferenceable()
    458 			      || __before._M_is_before_begin(),
    459 			      _M_message(__gnu_debug::__msg_valid_range2)
    460 			      ._M_sequence(__list, "list")
    461 			      ._M_iterator(__before, "before")
    462 			      ._M_iterator(__last, "last"));
    463 	_GLIBCXX_DEBUG_VERIFY(__before != __last,
    464 			      _M_message(__gnu_debug::__msg_valid_range2)
    465 			      ._M_sequence(__list, "list")
    466 			      ._M_iterator(__before, "before")
    467 			      ._M_iterator(__last, "last"));
    468 
    469 	for (_Base_const_iterator __tmp = std::next(__before.base());
    470 	     __tmp != __last.base(); ++__tmp)
    471 	  {
    472 	    _GLIBCXX_DEBUG_VERIFY(__tmp != __list._M_base().end(),
    473 				  _M_message(__gnu_debug::__msg_valid_range2)
    474 				  ._M_sequence(__list, "list")
    475 				  ._M_iterator(__before, "before")
    476 				  ._M_iterator(__last, "last"));
    477 	    _GLIBCXX_DEBUG_VERIFY(&__list != this || __tmp != __pos.base(),
    478                                   _M_message(__gnu_debug::__msg_splice_overlap)
    479                                   ._M_iterator(__tmp, "position")
    480 				  ._M_iterator(__before, "before")
    481 				  ._M_iterator(__last, "last"));
    482 	    // _GLIBCXX_RESOLVE_LIB_DEFECTS
    483 	    // 250. splicing invalidates iterators
    484 	    this->_M_transfer_from_if(__list, [__tmp](_Base_const_iterator __it)
    485 	      { return __it == __tmp; });
    486 	  }
    487 
    488 	_Base::splice_after(__pos.base(), std::move(__list._M_base()),
    489 			    __before.base(), __last.base());
    490       }
    491 
    492       void
    493       splice_after(const_iterator __pos, forward_list& __list,
    494 		   const_iterator __before, const_iterator __last)
    495       { splice_after(__pos, std::move(__list), __before, __last); }
    496 
    497       void
    498       remove(const _Tp& __val)
    499       {
    500 	_Base_iterator __x = _Base::before_begin();
    501 	_Base_iterator __old = __x++;
    502 	while (__x != _Base::end())
    503 	  {
    504 	    if (*__x == __val)
    505 	      __x = _M_erase_after(__old);
    506 	    else
    507 	      __old = __x++;
    508 	  }
    509       }
    510 
    511       template<typename _Pred>
    512         void
    513         remove_if(_Pred __pred)
    514 	{
    515 	  _Base_iterator __x = _Base::before_begin();
    516 	  _Base_iterator __old = __x++;
    517 	  while (__x != _Base::end())
    518 	    {
    519 	      if (__pred(*__x))
    520 		__x = _M_erase_after(__old);
    521 	      else
    522 		__old = __x++;
    523 	    }
    524 	}
    525 
    526       void
    527       unique()
    528       {
    529 	_Base_iterator __first = _Base::begin();
    530 	_Base_iterator __last = _Base::end();
    531 	if (__first == __last)
    532 	  return;
    533 	_Base_iterator __next = std::next(__first);
    534 	while (__next != __last)
    535 	  {
    536 	    if (*__first == *__next)
    537 	      __next = _M_erase_after(__first);
    538 	    else
    539 	      __first = __next++;
    540 	  }
    541       }
    542 
    543       template<typename _BinPred>
    544         void
    545         unique(_BinPred __binary_pred)
    546 	{
    547 	  _Base_iterator __first = _Base::begin();
    548 	  _Base_iterator __last = _Base::end();
    549 	  if (__first == __last)
    550 	    return;
    551 	  _Base_iterator __next = std::next(__first);
    552 	  while (__next != __last)
    553 	    {
    554 	      if (__binary_pred(*__first, *__next))
    555 		__next = _M_erase_after(__first);
    556 	      else
    557 		__first = __next++;
    558 	    }
    559 	}
    560 
    561       void
    562       merge(forward_list&& __list)
    563       {
    564 	if (this != &__list)
    565 	{
    566 	  __glibcxx_check_sorted(_Base::begin(), _Base::end());
    567 	  __glibcxx_check_sorted(__list._M_base().begin(),
    568 				 __list._M_base().end());
    569 	  this->_M_transfer_from_if(__list, [&__list](_Base_const_iterator __it)
    570 	    {
    571 	      return __it != __list._M_base().cbefore_begin()
    572 		     && __it != __list._M_base().cend();
    573 	    });
    574 	  _Base::merge(std::move(__list._M_base()));
    575 	}
    576       }
    577 
    578       void
    579       merge(forward_list& __list)
    580       { merge(std::move(__list)); }
    581 
    582       template<typename _Comp>
    583         void
    584         merge(forward_list&& __list, _Comp __comp)
    585 	{
    586 	  if (this != &__list)
    587 	  {
    588 	    __glibcxx_check_sorted_pred(_Base::begin(), _Base::end(), __comp);
    589 	    __glibcxx_check_sorted_pred(__list._M_base().begin(),
    590 					__list._M_base().end(), __comp);
    591 	    this->_M_transfer_from_if(__list,
    592 				      [&__list](_Base_const_iterator __it)
    593 	      {
    594 	        return __it != __list._M_base().cbefore_begin()
    595 		       && __it != __list._M_base().cend();
    596 	      });
    597 	    _Base::merge(std::move(__list._M_base()), __comp);
    598 	  }
    599 	}
    600 
    601       template<typename _Comp>
    602         void
    603         merge(forward_list& __list, _Comp __comp)
    604         { merge(std::move(__list), __comp); }
    605 
    606       using _Base::sort;
    607       using _Base::reverse;
    608 
    609       _Base&
    610       _M_base() noexcept       { return *this; }
    611 
    612       const _Base&
    613       _M_base() const noexcept { return *this; }
    614 
    615     private:
    616       void
    617       _M_invalidate_all()
    618       {
    619 	this->_M_invalidate_if([this](_Base_const_iterator __it)
    620 	  {
    621 	    return __it != this->_M_base().cbefore_begin()
    622 		   && __it != this->_M_base().cend();
    623 	  });
    624       }
    625       typedef __gnu_debug::_Safe_iterator_base _Safe_iterator_base;
    626       static void
    627       _M_swap_aux(forward_list& __lhs,
    628 		  _Safe_iterator_base*& __lhs_iterators,
    629 		  forward_list& __rhs,
    630 		  _Safe_iterator_base*& __rhs_iterators);
    631       void _M_swap(forward_list& __list);
    632     };
    633 
    634    template<typename _Tp, typename _Alloc>
    635     void
    636     forward_list<_Tp, _Alloc>::
    637     _M_swap_aux(forward_list<_Tp, _Alloc>& __lhs,
    638 		__gnu_debug::_Safe_iterator_base*& __lhs_iterators,
    639 		forward_list<_Tp, _Alloc>& __rhs,
    640 		__gnu_debug::_Safe_iterator_base*& __rhs_iterators)
    641     {
    642       using __gnu_debug::_Safe_iterator_base;
    643       _Safe_iterator_base* __bbegin_its = 0;
    644       _Safe_iterator_base* __last_bbegin = 0;
    645       for (_Safe_iterator_base* __iter = __lhs_iterators; __iter;)
    646 	{
    647 	  // Even iterator are casted to const_iterator, not a problem.
    648 	  const_iterator* __victim = static_cast<const_iterator*>(__iter);
    649 	  __iter = __iter->_M_next;
    650 	  if (__victim->base() == __rhs._M_base().cbefore_begin())
    651 	    {
    652 	      __victim->_M_unlink();
    653 	      if (__lhs_iterators == __victim)
    654 		__lhs_iterators = __victim->_M_next;
    655 	      if (__bbegin_its)
    656 		{
    657 		  __victim->_M_next = __bbegin_its;
    658 		  __bbegin_its->_M_prior = __victim;
    659 		}
    660 	      else
    661 		__last_bbegin = __victim;
    662 	      __bbegin_its = __victim;
    663 	    }
    664 	  else
    665 	    __victim->_M_sequence = &__lhs;
    666 	}
    667 
    668       if (__bbegin_its)
    669 	{
    670 	  if (__rhs_iterators)
    671 	    {
    672 	      __rhs_iterators->_M_prior = __last_bbegin;
    673 	      __last_bbegin->_M_next = __rhs_iterators;
    674 	    }
    675 	  __rhs_iterators = __bbegin_its;
    676 	}
    677     }
    678 
    679   /* Special forward_list _M_swap version that do not swap the
    680    * before-begin ownership.*/
    681   template<typename _Tp, typename _Alloc>
    682     void
    683     forward_list<_Tp, _Alloc>::
    684     _M_swap(forward_list<_Tp, _Alloc>& __list)
    685     {
    686       __gnu_cxx::__scoped_lock sentry(this->_M_get_mutex());
    687       std::swap(this->_M_iterators, __list._M_iterators);
    688       std::swap(this->_M_const_iterators, __list._M_const_iterators);
    689       // Useless, always 1 on forward_list
    690       //std::swap(this->_M_version, __list._M_version);
    691       _Safe_iterator_base* __this_its = this->_M_iterators;
    692       _M_swap_aux(__list, __list._M_iterators, *this, this->_M_iterators);
    693       _Safe_iterator_base* __this_const_its = this->_M_const_iterators;
    694       _M_swap_aux(__list, __list._M_const_iterators, *this,
    695 		  this->_M_const_iterators);
    696       _M_swap_aux(*this, __this_its, __list, __list._M_iterators);
    697       _M_swap_aux(*this, __this_const_its, __list, __list._M_const_iterators);
    698     }
    699 
    700   template<typename _Tp, typename _Alloc>
    701     bool
    702     operator==(const forward_list<_Tp, _Alloc>& __lx,
    703                const forward_list<_Tp, _Alloc>& __ly)
    704     { return __lx._M_base() == __ly._M_base(); }
    705 
    706   template<typename _Tp, typename _Alloc>
    707     inline bool
    708     operator<(const forward_list<_Tp, _Alloc>& __lx,
    709               const forward_list<_Tp, _Alloc>& __ly)
    710     { return __lx._M_base() < __ly._M_base(); }
    711 
    712   template<typename _Tp, typename _Alloc>
    713     inline bool
    714     operator!=(const forward_list<_Tp, _Alloc>& __lx,
    715                const forward_list<_Tp, _Alloc>& __ly)
    716     { return !(__lx == __ly); }
    717 
    718   /// Based on operator<
    719   template<typename _Tp, typename _Alloc>
    720     inline bool
    721     operator>(const forward_list<_Tp, _Alloc>& __lx,
    722               const forward_list<_Tp, _Alloc>& __ly)
    723     { return (__ly < __lx); }
    724 
    725   /// Based on operator<
    726   template<typename _Tp, typename _Alloc>
    727     inline bool
    728     operator>=(const forward_list<_Tp, _Alloc>& __lx,
    729                const forward_list<_Tp, _Alloc>& __ly)
    730     { return !(__lx < __ly); }
    731 
    732   /// Based on operator<
    733   template<typename _Tp, typename _Alloc>
    734     inline bool
    735     operator<=(const forward_list<_Tp, _Alloc>& __lx,
    736                const forward_list<_Tp, _Alloc>& __ly)
    737     { return !(__ly < __lx); }
    738 
    739   /// See std::forward_list::swap().
    740   template<typename _Tp, typename _Alloc>
    741     inline void
    742     swap(forward_list<_Tp, _Alloc>& __lx,
    743 	 forward_list<_Tp, _Alloc>& __ly)
    744     { __lx.swap(__ly); }
    745 
    746 } // namespace __debug
    747 } // namespace std
    748 
    749 namespace __gnu_debug
    750 {
    751   template<class _Tp, class _Alloc>
    752     struct _BeforeBeginHelper<std::__debug::forward_list<_Tp, _Alloc> >
    753     {
    754       typedef std::__debug::forward_list<_Tp, _Alloc> _Sequence;
    755       typedef typename _Sequence::const_iterator _It;
    756       typedef typename _It::iterator_type _BaseIt;
    757 
    758       static bool
    759       _S_Is(_BaseIt __it, const _Sequence* __seq)
    760       { return __it == __seq->_M_base().cbefore_begin(); }
    761 
    762       static bool
    763       _S_Is_Beginnest(_BaseIt __it, const _Sequence* __seq)
    764       { return _S_Is(__it, __seq); }
    765     };
    766 }
    767 
    768 #endif
    769