1// <forward_list> -*- C++ -*-
2
3// Copyright (C) 2010-2013 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
38namespace std _GLIBCXX_VISIBILITY(default)
39{
40namespace __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
53      typedef typename __gnu_cxx::__alloc_traits<_Alloc>::template
54        rebind<_GLIBCXX_STD_C::_Fwd_list_node<_Tp>>::other _Node_alloc_type;
55
56      typedef __gnu_cxx::__alloc_traits<_Node_alloc_type> _Node_alloc_traits;
57
58    public:
59      typedef typename _Base::reference             reference;
60      typedef typename _Base::const_reference       const_reference;
61
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;
66
67      typedef typename _Base::size_type             size_type;
68      typedef typename _Base::difference_type       difference_type;
69
70      typedef _Tp                                   value_type;
71      typedef _Alloc                                allocator_type;
72      typedef typename _Base::pointer               pointer;
73      typedef typename _Base::const_pointer         const_pointer;
74
75      // 23.2.3.1 construct/copy/destroy:
76      explicit
77      forward_list(const _Alloc& __al = _Alloc())
78      : _Base(__al) { }
79
80      forward_list(const forward_list& __list, const _Alloc& __al)
81      : _Base(__list, __al)
82      { }
83
84      forward_list(forward_list&& __list, const _Alloc& __al)
85      : _Base(std::move(__list._M_base()), __al)
86      {
87	if (__list.get_allocator() == __al)
88	  this->_M_swap(__list);
89	else
90	  __list._M_invalidate_all();
91      }
92
93      explicit
94      forward_list(size_type __n, const _Alloc& __al = _Alloc())
95      : _Base(__n, __al)
96      { }
97
98      forward_list(size_type __n, const _Tp& __value,
99                   const _Alloc& __al = _Alloc())
100      : _Base(__n, __value, __al)
101      { }
102
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,
108								     __last)),
109		__gnu_debug::__base(__last), __al)
110        { }
111
112      forward_list(const forward_list& __list)
113      : _Base(__list)
114      { }
115
116      forward_list(forward_list&& __list) noexcept
117      : _Base(std::move(__list._M_base()))
118      {
119	this->_M_swap(__list);
120      }
121
122      forward_list(std::initializer_list<_Tp> __il,
123                   const _Alloc& __al = _Alloc())
124      : _Base(__il, __al)
125      { }
126
127      ~forward_list() noexcept
128      { }
129
130      forward_list&
131      operator=(const forward_list& __list)
132      {
133	static_cast<_Base&>(*this) = __list;
134	this->_M_invalidate_all();
135	return *this;
136      }
137
138      forward_list&
139      operator=(forward_list&& __list)
140      noexcept(_Node_alloc_traits::_S_nothrow_move())
141      {
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);
146	if (xfer_memory)
147	  this->_M_swap(__list);
148	else
149	  this->_M_invalidate_all();
150	__list._M_invalidate_all();
151	return *this;
152      }
153
154      forward_list&
155      operator=(std::initializer_list<_Tp> __il)
156      {
157	static_cast<_Base&>(*this) = __il;
158	this->_M_invalidate_all();
159        return *this;
160      }
161
162      template<typename _InputIterator,
163	       typename = std::_RequireInputIter<_InputIterator>>
164	void
165        assign(_InputIterator __first, _InputIterator __last)
166        {
167	  __glibcxx_check_valid_range(__first, __last);
168	  _Base::assign(__gnu_debug::__base(__first),
169			__gnu_debug::__base(__last));
170	  this->_M_invalidate_all();
171        }
172
173      void
174      assign(size_type __n, const _Tp& __val)
175      {
176	_Base::assign(__n, __val);
177	this->_M_invalidate_all();
178      }
179
180      void
181      assign(std::initializer_list<_Tp> __il)
182      {
183	_Base::assign(__il);
184	this->_M_invalidate_all();
185      }
186
187      using _Base::get_allocator;
188
189      // iterators:
190
191      iterator
192      before_begin() noexcept
193      { return iterator(_Base::before_begin(), this); }
194
195      const_iterator
196      before_begin() const noexcept
197      { return const_iterator(_Base::before_begin(), this); }
198
199      iterator
200      begin() noexcept
201      { return iterator(_Base::begin(), this); }
202
203      const_iterator
204      begin() const noexcept
205      { return const_iterator(_Base::begin(), this); }
206
207      iterator
208      end() noexcept
209      { return iterator(_Base::end(), this); }
210
211      const_iterator
212      end() const noexcept
213      { return const_iterator(_Base::end(), this); }
214
215      const_iterator
216      cbegin() const noexcept
217      { return const_iterator(_Base::cbegin(), this); }
218
219      const_iterator
220      cbefore_begin() const noexcept
221      { return const_iterator(_Base::cbefore_begin(), this); }
222
223      const_iterator
224      cend() const noexcept
225      { return const_iterator(_Base::cend(), this); }
226
227      using _Base::empty;
228      using _Base::max_size;
229
230      // element access:
231
232      reference
233      front()
234      {
235	__glibcxx_check_nonempty();
236	return _Base::front();
237      }
238
239      const_reference
240      front() const
241      {
242	__glibcxx_check_nonempty();
243	return _Base::front();
244      }
245
246      // modifiers:
247
248      using _Base::emplace_front;
249      using _Base::push_front;
250
251      void
252      pop_front()
253      {
254	__glibcxx_check_nonempty();
255	this->_M_invalidate_if([this](_Base_const_iterator __it)
256	  { return __it == this->_M_base().cbegin(); });
257	_Base::pop_front();
258      }
259
260      template<typename... _Args>
261	iterator
262	emplace_after(const_iterator __pos, _Args&&... __args)
263	{
264	  __glibcxx_check_insert_after(__pos);
265	  return iterator(_Base::emplace_after(__pos.base(),
266					std::forward<_Args>(__args)...),
267			  this);
268       	}
269
270      iterator
271      insert_after(const_iterator __pos, const _Tp& __val)
272      {
273	__glibcxx_check_insert_after(__pos);
274	return iterator(_Base::insert_after(__pos.base(), __val), this);
275      }
276
277      iterator
278      insert_after(const_iterator __pos, _Tp&& __val)
279      {
280	__glibcxx_check_insert_after(__pos);
281	return iterator(_Base::insert_after(__pos.base(), std::move(__val)),
282		       	this);
283      }
284
285      iterator
286      insert_after(const_iterator __pos, size_type __n, const _Tp& __val)
287      {
288	__glibcxx_check_insert_after(__pos);
289	return iterator(_Base::insert_after(__pos.base(), __n, __val),
290		       	this);
291      }
292
293      template<typename _InputIterator,
294	       typename = std::_RequireInputIter<_InputIterator>>
295        iterator
296        insert_after(const_iterator __pos,
297                     _InputIterator __first, _InputIterator __last)
298        {
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)),
303			  this);
304        }
305
306      iterator
307      insert_after(const_iterator __pos, std::initializer_list<_Tp> __il)
308      {
309	__glibcxx_check_insert_after(__pos);
310	return iterator(_Base::insert_after(__pos.base(), __il), this);
311      }
312
313    private:
314      _Base_iterator
315      _M_erase_after(_Base_const_iterator __pos)
316      {
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);
321      }
322    public:
323      iterator
324      erase_after(const_iterator __pos)
325      {
326	__glibcxx_check_erase_after(__pos);
327	return iterator(_M_erase_after(__pos.base()), this);
328      }
329
330      iterator
331      erase_after(const_iterator __pos, const_iterator __last)
332      {
333	__glibcxx_check_erase_range_after(__pos, __last);
334	for (_Base_const_iterator __victim = std::next(__pos.base());
335	    __victim != __last.base(); ++__victim)
336	  {
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; });
344	  }
345	return iterator(_Base::erase_after(__pos.base(), __last.base()), this);
346      }
347
348      void
349      swap(forward_list& __list)
350      noexcept(_Node_alloc_traits::_S_nothrow_swap())
351      {
352	if (!_Node_alloc_traits::_S_propagate_on_swap())
353	  __glibcxx_check_equal_allocs(__list);
354	_Base::swap(__list);
355	this->_M_swap(__list);
356      }
357
358      void
359      resize(size_type __sz)
360      {
361	this->_M_detach_singular();
362
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)
367	  ++__victim;
368
369	for (; __victim != __end; ++__victim)
370	  {
371	    this->_M_invalidate_if([__victim](_Base_const_iterator __it)
372	      { return __it == __victim; });
373	  }
374
375	__try
376	  {
377	    _Base::resize(__sz);
378	  }
379	__catch(...)
380	  {
381	    this->_M_revalidate_singular();
382	    __throw_exception_again;
383          }
384      }
385
386      void
387      resize(size_type __sz, const value_type& __val)
388      {
389	this->_M_detach_singular();
390
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)
395	  ++__victim;
396
397	for (; __victim != __end; ++__victim)
398	  {
399	    this->_M_invalidate_if([__victim](_Base_const_iterator __it)
400	      { return __it == __victim; });
401	  }
402
403	__try
404	  {
405	    _Base::resize(__sz, __val);
406	  }
407	__catch(...)
408	  {
409	    this->_M_revalidate_singular();
410	    __throw_exception_again;
411          }
412      }
413
414      void
415      clear() noexcept
416      {
417	_Base::clear();
418	this->_M_invalidate_all();
419      }
420
421      // 23.2.3.5 forward_list operations:
422      void
423      splice_after(const_iterator __pos, forward_list&& __list)
424      {
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)
431			      ._M_sequence(*this)
432			      ._M_sequence(__list, "__list"));
433	this->_M_transfer_from_if(__list, [&__list](_Base_const_iterator __it)
434	  {
435	    return __it != __list._M_base().cbefore_begin()
436		   && __it != __list._M_base().end();
437	  });
438	_Base::splice_after(__pos.base(), std::move(__list._M_base()));
439      }
440
441      void
442      splice_after(const_iterator __pos, forward_list& __list)
443      { splice_after(__pos, std::move(__list)); }
444
445      void
446      splice_after(const_iterator __pos, forward_list&& __list,
447		   const_iterator __i)
448      {
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)
459			      ._M_sequence(*this)
460			      ._M_sequence(__list, "__list"));
461
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()),
468			    __i.base());
469      }
470
471      void
472      splice_after(const_iterator __pos, forward_list& __list,
473		   const_iterator __i)
474      { splice_after(__pos, std::move(__list), __i); }
475
476      void
477      splice_after(const_iterator __pos, forward_list&& __list,
478		   const_iterator __before, const_iterator __last)
479      {
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)
499			      ._M_sequence(*this)
500			      ._M_sequence(__list, "__list"));
501
502	for (_Base_const_iterator __tmp = std::next(__before.base());
503	     __tmp != __last.base(); ++__tmp)
504	  {
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; });
519	  }
520
521	_Base::splice_after(__pos.base(), std::move(__list._M_base()),
522			    __before.base(), __last.base());
523      }
524
525      void
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); }
529
530      void
531      remove(const _Tp& __val)
532      {
533	_Base_iterator __x = _Base::before_begin();
534	_Base_iterator __old = __x++;
535	while (__x != _Base::end())
536	  {
537	    if (*__x == __val)
538	      __x = _M_erase_after(__old);
539	    else
540	      __old = __x++;
541	  }
542      }
543
544      template<typename _Pred>
545        void
546        remove_if(_Pred __pred)
547	{
548	  _Base_iterator __x = _Base::before_begin();
549	  _Base_iterator __old = __x++;
550	  while (__x != _Base::end())
551	    {
552	      if (__pred(*__x))
553		__x = _M_erase_after(__old);
554	      else
555		__old = __x++;
556	    }
557	}
558
559      void
560      unique()
561      {
562	_Base_iterator __first = _Base::begin();
563	_Base_iterator __last = _Base::end();
564	if (__first == __last)
565	  return;
566	_Base_iterator __next = std::next(__first);
567	while (__next != __last)
568	  {
569	    if (*__first == *__next)
570	      __next = _M_erase_after(__first);
571	    else
572	      __first = __next++;
573	  }
574      }
575
576      template<typename _BinPred>
577        void
578        unique(_BinPred __binary_pred)
579	{
580	  _Base_iterator __first = _Base::begin();
581	  _Base_iterator __last = _Base::end();
582	  if (__first == __last)
583	    return;
584	  _Base_iterator __next = std::next(__first);
585	  while (__next != __last)
586	    {
587	      if (__binary_pred(*__first, *__next))
588		__next = _M_erase_after(__first);
589	      else
590		__first = __next++;
591	    }
592	}
593
594      void
595      merge(forward_list&& __list)
596      {
597	if (this != &__list)
598	{
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)
603	    {
604	      return __it != __list._M_base().cbefore_begin()
605		     && __it != __list._M_base().cend();
606	    });
607	  _Base::merge(std::move(__list._M_base()));
608	}
609      }
610
611      void
612      merge(forward_list& __list)
613      { merge(std::move(__list)); }
614
615      template<typename _Comp>
616        void
617        merge(forward_list&& __list, _Comp __comp)
618	{
619	  if (this != &__list)
620	  {
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)
626	      {
627	        return __it != __list._M_base().cbefore_begin()
628		       && __it != __list._M_base().cend();
629	      });
630	    _Base::merge(std::move(__list._M_base()), __comp);
631	  }
632	}
633
634      template<typename _Comp>
635        void
636        merge(forward_list& __list, _Comp __comp)
637        { merge(std::move(__list), __comp); }
638
639      using _Base::sort;
640      using _Base::reverse;
641
642      _Base&
643      _M_base() noexcept       { return *this; }
644
645      const _Base&
646      _M_base() const noexcept { return *this; }
647
648    private:
649      void
650      _M_invalidate_all()
651      {
652	this->_M_invalidate_if([this](_Base_const_iterator __it)
653	  {
654	    return __it != this->_M_base().cbefore_begin()
655		   && __it != this->_M_base().cend();
656	  });
657      }
658      typedef __gnu_debug::_Safe_iterator_base _Safe_iterator_base;
659      static void
660      _M_swap_aux(forward_list& __lhs,
661		  _Safe_iterator_base*& __lhs_iterators,
662		  forward_list& __rhs,
663		  _Safe_iterator_base*& __rhs_iterators);
664      void _M_swap(forward_list& __list);
665    };
666
667   template<typename _Tp, typename _Alloc>
668    void
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)
674    {
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;)
679	{
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())
684	    {
685	      __victim->_M_unlink();
686	      if (__lhs_iterators == __victim)
687		__lhs_iterators = __victim->_M_next;
688	      if (__bbegin_its)
689		{
690		  __victim->_M_next = __bbegin_its;
691		  __bbegin_its->_M_prior = __victim;
692		}
693	      else
694		__last_bbegin = __victim;
695	      __bbegin_its = __victim;
696	    }
697	  else
698	    __victim->_M_sequence = &__lhs;
699	}
700
701      if (__bbegin_its)
702	{
703	  if (__rhs_iterators)
704	    {
705	      __rhs_iterators->_M_prior = __last_bbegin;
706	      __last_bbegin->_M_next = __rhs_iterators;
707	    }
708	  __rhs_iterators = __bbegin_its;
709	}
710    }
711
712  /* Special forward_list _M_swap version that do not swap the
713   * before-begin ownership.*/
714  template<typename _Tp, typename _Alloc>
715    void
716    forward_list<_Tp, _Alloc>::
717    _M_swap(forward_list<_Tp, _Alloc>& __list)
718    {
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);
731    }
732
733  template<typename _Tp, typename _Alloc>
734    bool
735    operator==(const forward_list<_Tp, _Alloc>& __lx,
736               const forward_list<_Tp, _Alloc>& __ly)
737    { return __lx._M_base() == __ly._M_base(); }
738
739  template<typename _Tp, typename _Alloc>
740    inline bool
741    operator<(const forward_list<_Tp, _Alloc>& __lx,
742              const forward_list<_Tp, _Alloc>& __ly)
743    { return __lx._M_base() < __ly._M_base(); }
744
745  template<typename _Tp, typename _Alloc>
746    inline bool
747    operator!=(const forward_list<_Tp, _Alloc>& __lx,
748               const forward_list<_Tp, _Alloc>& __ly)
749    { return !(__lx == __ly); }
750
751  /// Based on operator<
752  template<typename _Tp, typename _Alloc>
753    inline bool
754    operator>(const forward_list<_Tp, _Alloc>& __lx,
755              const forward_list<_Tp, _Alloc>& __ly)
756    { return (__ly < __lx); }
757
758  /// Based on operator<
759  template<typename _Tp, typename _Alloc>
760    inline bool
761    operator>=(const forward_list<_Tp, _Alloc>& __lx,
762               const forward_list<_Tp, _Alloc>& __ly)
763    { return !(__lx < __ly); }
764
765  /// Based on operator<
766  template<typename _Tp, typename _Alloc>
767    inline bool
768    operator<=(const forward_list<_Tp, _Alloc>& __lx,
769               const forward_list<_Tp, _Alloc>& __ly)
770    { return !(__ly < __lx); }
771
772  /// See std::forward_list::swap().
773  template<typename _Tp, typename _Alloc>
774    inline void
775    swap(forward_list<_Tp, _Alloc>& __lx,
776	 forward_list<_Tp, _Alloc>& __ly)
777    { __lx.swap(__ly); }
778
779} // namespace __debug
780} // namespace std
781
782namespace __gnu_debug
783{
784  template<class _Tp, class _Alloc>
785    struct _BeforeBeginHelper<std::__debug::forward_list<_Tp, _Alloc> >
786    {
787      typedef std::__debug::forward_list<_Tp, _Alloc> _Sequence;
788      typedef typename _Sequence::const_iterator _It;
789      typedef typename _It::iterator_type _BaseIt;
790
791      static bool
792      _S_Is(_BaseIt __it, const _Sequence* __seq)
793      { return __it == __seq->_M_base().cbefore_begin(); }
794
795      static bool
796      _S_Is_Beginnest(_BaseIt __it, const _Sequence* __seq)
797      { return _S_Is(__it, __seq); }
798    };
799}
800
801#endif
802