/* Metrowerks Standard Library
 * Copyright  1995-2004 Metrowerks Corporation.  All rights reserved.
 *
 * $Date: 2004/09/21 20:06:31 $
 * $Revision: 1.27.2.4 $
 */

// slist

#ifndef _SLIST
#define _SLIST

/*
 *  WARNING
 *
 *  slist is a non-standard header and container.
 *
 *
 *    slist has not yet been approved by the ANSI/ISO Standards
 *    Committee; therefore, we are supplying this class as largely
 *    specified by the Silicon Graphics, Inc. (SGI) , Standard
 *    Template Library (STL).  For further information, refer to
 *          <http://www.sgi.com/Technology/STL/Slist.html>
 *
 *    The implementation herein belongs to Metrowerks, Inc., and
 *    is protected by copyright.  Those parts of the interface
 *    unique to SGI's specification are supplied by SGI, and are
 *    likewise protected by copyright.
 *
 *    Copyright  1996-1999
 *    Silicon Graphics Computer Systems, Inc.
 *
 */

/*  slist synopsis

namespace Metrowerks
{

template <class T, class Allocator = std::allocator<T> >
class slist
{
public:
	typedef T                                        value_type;
	typedef Allocator                                allocator_type;
	typedef typename allocator_type::reference       reference;
	typedef typename allocator_type::const_reference const_reference;
	typedef typename allocator_type::size_type       size_type;
	typedef typename allocator_type::difference_type difference_type;
	typedef typename allocator_type::pointer         pointer;
	typedef typename allocator_type::const_pointer   const_pointer;

	class                                            iterator;        // forward
	class                                            const_iterator;  // forward

	explicit slist(const allocator_type& a = allocator_type());
	explicit slist(size_type n, const value_type& value = value_type(), const allocator_type& a = allocator_type());
	template <class InputIterator>
		slist(InputIterator first, InputIterator last, const allocator_type& a = allocator_type());

	slist(const slist& x);
	slist& operator=(const slist& x);
	~slist();

	allocator_type get_allocator() const;
	size_type max_size() const;

	size_type size() const;
	bool      empty() const;

	template <class InputIterator>
		void assign(InputIterator first, InputIterator last);
	void assign(size_type n, const T& t);

	iterator       begin();
	const_iterator begin() const;
	iterator       end();
	const_iterator end() const;

	iterator       previous(iterator x);
	const_iterator previous(const_iterator x) const;

	void resize(size_type sz, const T& c = T());

	reference       front();
	const_reference front() const;

	void push_front(const T& x);
	void pop_front();

	iterator insert_after(iterator pos, const value_type& value);
	void     insert_after(iterator pos, size_type n, const value_type& value);
	template <class InputIterator>
		void insert_after(iterator pos, InputIterator first, InputIterator last);

	iterator insert(iterator pos, const value_type& value);
	void     insert(iterator pos, size_type n, const value_type& value);
	template <class InputIterator>
		void insert(iterator pos, InputIterator first, InputIterator last);

	iterator erase_after(iterator pos);
	iterator erase_after(iterator first, iterator last);
	iterator erase(iterator pos);
	iterator erase(iterator first, iterator last);
	void     clear();

	void swap(slist& x);

	void splice_after(iterator pos, slist& x);
	void splice_after(iterator pos, slist& x, iterator f);
	void splice_after(iterator pos, slist& x, iterator f, iterator l);
	void splice(iterator pos, slist& x);
	void splice(iterator pos, slist& x, iterator f);
	void splice(iterator pos, slist& x, iterator f, iterator l);

	void remove(const value_type& value);
	template <class Predicate> void remove_if(Predicate pred);

	void unique();
	template <class BinaryPredicate> void unique(BinaryPredicate binary_pred);

	void merge(slist& x);
	template <class Compare> void merge(slist& x, Compare comp);

	void sort();
	template <class Compare> void sort(Compare comp);

	void reverse();

	bool invariants() const;  // Metrowerks extension
};

template <class T, class A> bool operator==(const slist<T, A>& x, const slist<T, A>& y);
template <class T, class A> bool operator!=(const slist<T, A>& x, const slist<T, A>& y);
template <class T, class A> bool operator< (const slist<T, A>& x, const slist<T, A>& y);
template <class T, class A> bool operator> (const slist<T, A>& x, const slist<T, A>& y);
template <class T, class A> bool operator>=(const slist<T, A>& x, const slist<T, A>& y);
template <class T, class A> bool operator<=(const slist<T, A>& x, const slist<T, A>& y);

template <class T, class A> void swap(slist<T, A>& x, slist<T, A>& y);

}  // Metrowerks
*/

#include <mslconfig>
#include <memory>
#include <msl_int_limits>
#include <stdexcept>
#include <iterator>
#include <algorithm>

#ifndef RC_INVOKED

#ifdef __MWERKS__
#pragma options align=native
#endif

#ifdef _MSL_FORCE_ENUMS_ALWAYS_INT
	#if _MSL_FORCE_ENUMS_ALWAYS_INT
		#pragma enumsalwaysint on
	#else
		#pragma enumsalwaysint off
	#endif
#endif  // _MSL_FORCE_ENUMS_ALWAYS_INT

#ifdef _MSL_FORCE_ENABLE_BOOL_SUPPORT
	#if _MSL_FORCE_ENABLE_BOOL_SUPPORT
		#pragma bool on
	#else
		#pragma bool off
	#endif
#endif  // _MSL_FORCE_ENABLE_BOOL_SUPPORT

#ifdef min
#undef min
#endif

#ifdef max
#undef max
#endif

#ifndef _MSL_NO_CPP_NAMESPACE
	namespace Metrowerks {
#else
	#ifndef Metrowerks
		#define Metrowerks
	#endif
#endif  // _MSL_NO_CPP_NAMESPACE

template <class T, class Allocator, bool IsPOD> class __slist_imp;

// __slist_deleter_common

template <class T, class Allocator>
class __slist_deleter_common
{
public:
	// types:
	typedef T                                        value_type;
	typedef Allocator                                allocator_type;
	typedef typename allocator_type::reference       reference;
	typedef typename allocator_type::const_reference const_reference;
	typedef typename allocator_type::size_type       size_type;
	typedef typename allocator_type::difference_type difference_type;
	typedef typename allocator_type::pointer         pointer;
	typedef typename allocator_type::const_pointer   const_pointer;

	struct node;

	typedef typename allocator_type::rebind<node>::other node_allocator_type;
	typedef typename node_allocator_type::pointer          node_pointer;
	typedef typename node_allocator_type::const_pointer    node_const_pointer;

	struct node_base
	{
		node_base() : next_(0) {}
		node_pointer next_;
	};

	struct node
		: node_base
	{
		value_type     data_;
	};

	template <bool is_const>
	class __generic_iterator
	{
		typedef typename select<is_const, typename __slist_deleter_common::node_const_pointer,
		                                  typename __slist_deleter_common::node_pointer>::type node_pointer;
	public:
		typedef typename __slist_deleter_common::value_type       value_type;
		typedef typename __slist_deleter_common::difference_type  difference_type;
		typedef typename select<is_const, typename __slist_deleter_common::const_pointer,
		                                  typename __slist_deleter_common::pointer>::type pointer;
		typedef typename select<is_const, typename __slist_deleter_common::const_reference,
		                                  typename __slist_deleter_common::reference>::type reference;
		typedef _STD::forward_iterator_tag iterator_category;

		__generic_iterator() {}
		__generic_iterator(const __generic_iterator<false>& i)
			: node_(i.node_) {}
		reference operator * () const {return node_->data_;}
		pointer operator -> () const  {return &node_->data_;}
		__generic_iterator& operator ++ ()
			{
				node_ = node_->next_;
				return *this;
			}
		__generic_iterator operator ++ (int) {__generic_iterator tmp(*this); ++(*this); return tmp;}
		friend bool operator ==(const __generic_iterator& x, const __generic_iterator& y) {return x.node_ == y.node_;}
		friend bool operator !=(const __generic_iterator& x, const __generic_iterator& y) {return x.node_ != y.node_;}

#ifndef __GNUC__
	private:

		friend class __generic_iterator<true>;
		friend class __slist_deleter_common;
#endif  // __GNUC__

		node_pointer node_;

		explicit __generic_iterator(node_pointer node)
			: node_(node) {}
	};

	typedef __generic_iterator<false> iterator;
	typedef __generic_iterator<true>  const_iterator;

	iterator       make_iterator(node_pointer p)       {return       iterator(p);}
	const_iterator make_iterator(node_pointer p) const {return const_iterator(p);}

	compressed_pair<node_base, allocator_type>         head_;
	compressed_pair<node_pointer, node_allocator_type> tail_;

	node_pointer&       head()       {return head_.first().next_;}
	node_const_pointer  head() const {return head_.first().next_;}

	node_pointer        tail()       {return       (node_pointer)&head_;}
	node_const_pointer  tail() const {return (node_const_pointer)&head_;}

	node_pointer&        last_node()       {return tail_.first();}
	node_const_pointer   last_node() const {return tail_.first();}

	allocator_type&       alloc()       {return head_.second();}
	const allocator_type& alloc() const {return head_.second();}

	node_allocator_type&       node_alloc()       {return tail_.second();}
	const node_allocator_type& node_alloc() const {return tail_.second();}

	__slist_deleter_common() {head() = last_node() = tail();}
	explicit __slist_deleter_common(const allocator_type& a)
		: head_(a), tail_(a) {head() = last_node() = tail();}
	~__slist_deleter_common();
	__slist_deleter_common& operator=(const __slist_deleter_common& x)
	{
		if (this != &x)
			assign(x.begin(), x.end());
		return *this;
	}

	void init(size_type n, const value_type& value);
	template <class InputIterator>
		void init(InputIterator f, InputIterator l);

	iterator       begin()       {return       iterator(head());}
	const_iterator begin() const {return const_iterator(head());}
	iterator       end()         {return       iterator(tail());}
	const_iterator end() const   {return const_iterator(tail());}

	iterator       previous(iterator x)           // returns --x (linear time)
	{
		iterator p = end();
		if (x == p)
			return iterator(last_node());
		for (iterator i = begin(); i != x; ++i)
			p = i;
		return p;
	}
	const_iterator previous(const_iterator x) const
	{
		const_iterator p = end();
		if (x == p)
			return const_iterator(last_node());
		for (const_iterator i = begin(); i != x; ++i)
			p = i;
		return p;
	}

	reference       front()       {return head()->data_;}
	const_reference front() const {return head()->data_;}
	void push_front(const value_type& value);
	void pop_front();

	size_type size() const {return static_cast<size_type>(_STD::distance(begin(), end()));}
	bool empty() const {return head() == tail();}
	size_type max_size() const {return (size_type)_STD::numeric_limits<difference_type>::max();}

	void splice_after(iterator pos, __slist_deleter_common& x);
	void splice_after(iterator pos, __slist_deleter_common& x, iterator f);
	void splice_after(iterator pos, __slist_deleter_common& x, iterator f, iterator l);
	void assign(size_type n, const value_type& value);
	template <class InputIterator>
		void assign(InputIterator f, InputIterator l);
	iterator insert_after(iterator pos, const value_type& value);
	void     insert_after(iterator pos, size_type n, const value_type& value);
	template <class InputIterator>
		void insert_after(iterator pos, InputIterator f, InputIterator l);
	iterator erase_after(iterator pos);
	iterator erase_after(iterator first, iterator last);
	void clear();
	void resize(size_type n);
	void resize(size_type n, const value_type& value);
	void reverse();
	void swap(__slist_deleter_common& x);
#ifdef _MSL_EXTENDED_BINDERS
	void remove(const value_type& value)
		{remove_if(_STD::binder2nd<_STD::equal_to<value_type>, const value_type&>(_STD::equal_to<value_type>(), value));}
#else  // _MSL_EXTENDED_BINDERS
	void remove(const value_type& value)
		{remove_if(_STD::bind2nd(_STD::equal_to<value_type>(), value));}
#endif  // _MSL_EXTENDED_BINDERS
	template <class Predicate> void remove_if(Predicate pred);

	void unique() {unique(_STD::equal_to<value_type>());}
	template <class BinaryPredicate> void unique(BinaryPredicate binary_pred);

	void merge(__slist_deleter_common& x) {merge(x, _STD::less<value_type>());}
	template <class Compare> void merge(__slist_deleter_common& x, Compare comp);

	void sort() {sort(_STD::less<value_type>());}
	template <class Compare> void sort(Compare comp);

	bool invariants() const;
};

template <class T, class Allocator>
bool
__slist_deleter_common<T, Allocator>::invariants() const
{
	if (head() == tail())
	{
		if (last_node() != tail())
			return false;
	}
	else
	{
		if (last_node()->next_ != tail())
			return false;
		const_iterator i = begin();
		const_iterator e = end();
		for (; i != e; ++i)
			{}
	}
	return true;
}

template <class T, class Allocator>
void
__slist_deleter_common<T, Allocator>::init(size_type n, const value_type& value)
{
	for (; n > 0; --n)
		push_front(value);
}

template <class T, class Allocator>
template <class InputIterator>
void
__slist_deleter_common<T, Allocator>::init(InputIterator f, InputIterator l)
{
	for (iterator p = end(); f != l; ++f)
		p = insert_after(p, *f);
}

template <class T, class Allocator>
inline
__slist_deleter_common<T, Allocator>::~__slist_deleter_common()
{
	clear();
}

// splices x into this
template <class T, class Allocator>
inline
void
__slist_deleter_common<T, Allocator>::splice_after(iterator pos, __slist_deleter_common& x)
{
	splice_after(pos, x, x.end(), iterator(x.last_node()));
}

// splices f+1 into this
template <class T, class Allocator>
inline
void
__slist_deleter_common<T, Allocator>::splice_after(iterator pos, __slist_deleter_common& x, iterator f)
{
	iterator l = f;
	splice_after(pos, x, f, ++l);
}

// splices (f, l]
template <class T, class Allocator>
void
__slist_deleter_common<T, Allocator>::splice_after(iterator pos, __slist_deleter_common& x, iterator f, iterator l)
{
	if (f != l && pos.node_ != f.node_ && pos.node_ != l.node_)
	{
		if (alloc() != x.alloc())
			_MSL_ERROR(_STD::runtime_error, "slist::splice called with unequal allocators");
		node_pointer p = pos.node_->next_;
		pos.node_->next_ = f.node_->next_;
		f.node_->next_ = l.node_->next_;
		l.node_->next_ = p;
		if (x.last_node() == l.node_)
			x.last_node() = f.node_;
		if (last_node() == pos.node_)
			last_node() = l.node_;
	}
}

template <class T, class Allocator>
inline
void
__slist_deleter_common<T, Allocator>::push_front(const value_type& value)
{
	insert_after(end(), value);
}

template <class T, class Allocator>
inline
void
__slist_deleter_common<T, Allocator>::pop_front()
{
	erase_after(end());
}

template <class T, class Allocator>
typename __slist_deleter_common<T, Allocator>::iterator
__slist_deleter_common<T, Allocator>::insert_after(iterator pos,  const value_type& value)
{
	alloc_ptr<node, node_allocator_type&> ap(node_alloc().allocate(1), node_alloc());
	alloc().construct(&ap->data_, value);
	node_pointer newnode = ap.release();
	node_pointer p = pos.node_;
	newnode->next_ = p->next_;
	p->next_ = newnode;
	if (newnode->next_ == tail())
		last_node() = newnode;
	return iterator(newnode);
}

template <class T, class Allocator>
void
__slist_deleter_common<T, Allocator>::insert_after(iterator pos,  size_type n, const value_type& value)
{
	if (n > 0)
	{
		__slist_deleter_common s(alloc());
		iterator p;
		for (p = s.end(); n > 0; --n)
			p = s.insert_after(p, value);
		splice_after(pos, s, s.end(), p);
	}
}

template <class T, class Allocator>
template <class InputIterator>
void
__slist_deleter_common<T, Allocator>::insert_after(iterator pos, InputIterator f, InputIterator l)
{
	__slist_deleter_common s(alloc());
	iterator p;
	for (p = s.end(); f != l; ++f)
		p = s.insert_after(p, *f);
	if (!s.empty())
		splice_after(pos, s, s.end(), p);
}

template <class T, class Allocator>
typename __slist_deleter_common<T, Allocator>::iterator
__slist_deleter_common<T, Allocator>::erase_after(iterator pos)
{
	node_pointer f = pos.node_->next_;
	pos.node_->next_ = f->next_;
	if (last_node() == f)
		last_node() = pos.node_;
	alloc().destroy(&f->data_);
	node_alloc().deallocate(f, 1);
	return pos;
}

// erases (first, last]
template <class T, class Allocator>
typename __slist_deleter_common<T, Allocator>::iterator
__slist_deleter_common<T, Allocator>::erase_after(iterator first,  iterator last)
{
	if (first != last)
	{
		node_allocator_type& na = node_alloc();
		allocator_type& a = alloc();
		node_pointer f = first.node_->next_;
		node_pointer l = last.node_->next_;
		while (f != l)
		{
			node_pointer prev = f;
			f = f->next_;
			if (last_node() == prev)
				last_node() = first.node_;
			a.destroy(&prev->data_);
			na.deallocate(prev, 1);
		}
		first.node_->next_ = l;
	}
	return first;
}

template <class T, class Allocator>
inline
void
__slist_deleter_common<T, Allocator>::clear()
{
	erase_after(end(), iterator(last_node()));
}

template <class T, class Allocator>
void
__slist_deleter_common<T, Allocator>::resize(size_type n)
{
	if (n == 0)
		clear();
	else
	{
		iterator i = begin();
		iterator e = end();
		iterator p = e;
		for (; i != e && n > 0; ++i, --n)
			p = i;
		if (n > 0)
			insert_after(p, n, value_type());
		else
			erase_after(p, iterator(last_node()));
	}
}

template <class T, class Allocator>
void
__slist_deleter_common<T, Allocator>::resize(size_type n, const value_type& value)
{
	if (n == 0)
		clear();
	else
	{
		iterator i = begin();
		iterator e = end();
		iterator p = e;
		for (; i != e && n > 0; ++i, --n)
			p = i;
		if (n > 0)
			insert_after(p, n, value);
		else
			erase_after(p, iterator(last_node()));
	}
}

template <class T, class Allocator>
void
__slist_deleter_common<T, Allocator>::assign(size_type n, const value_type& value)
{
	if (n == 0)
	{
		clear();
		return;
	}
	node_pointer p = head();
	node_pointer const t = tail();
	if (p != t)
	{
		node_pointer prev = p;
		while (n != 0 && p != t)
		{
			p->data_ = value;
			--n;
			prev = p;
			p = p->next_;
		}
		p = prev;
	}
	else
	{
		push_front(value);
		p = head();
		--n;
	}
	iterator i(p);
	if (n != 0)
		insert_after(i, n, value);
	else
		erase_after(i, iterator(last_node()));
}

template <class T, class Allocator>
template <class InputIterator>
void
__slist_deleter_common<T, Allocator>::assign(InputIterator f, InputIterator l)
{
	if (f == l)
	{
		clear();
		return;
	}
	node_pointer p = head();
	node_pointer const t = tail();
	if (p != t)
	{
		node_pointer prev = p;
		while (f != l && p != t)
		{
			p->data_ = *f;
			++f;
			prev = p;
			p = p->next_;
		}
		p = prev;
	}
	else
	{
		push_front(*f);
		p = head();
		++f;
	}
	iterator i(p);
	if (f != l)
		insert_after(i, f, l);
	else
		erase_after(i, iterator(last_node()));
}

template <class T, class Allocator>
void
__slist_deleter_common<T, Allocator>::reverse()
{
	node_pointer& f = head();
	node_pointer const e = tail();
	if (f != e)
	{
		node_pointer last = f;
		node_pointer p = f;
		while (p->next_ != e)
		{
			node_pointer p2 = p->next_;
			p->next_ = p2->next_;
			p2->next_ = f;
			f = p2;
		}
		last_node() = last;
	}
}

template <class T, class Allocator>
void
__slist_deleter_common<T, Allocator>::swap(__slist_deleter_common& x)
{
	if (this != &x)
	{
		head_.swap(x.head_);
		tail_.swap(x.tail_);
		if (head() != x.tail())
			last_node()->next_ = tail();
		else
			head() = last_node() = tail();
		if (x.head() != tail())
			x.last_node()->next_ = x.tail();
		else
			x.head() = x.last_node() = x.tail();
	}
}

template <class T, class Allocator>
template <class Predicate>
void
__slist_deleter_common<T, Allocator>::remove_if(Predicate pred)
{
	iterator e = end();
	iterator p1 = e;
	for (iterator i = begin(); i != e; ++i)
	{
		if (pred(*i))
		{
			iterator j = i;
			iterator p2 = j;
			for (++j; j != e; ++j)
			{
				if (!pred(*j))
					break;
				p2 = j;
			}
			erase_after(p1, p2);
			i = j;
			if (i == e)
				break;
		}
		p1 = i;
	}
}

template <class T, class Allocator>
template <class BinaryPredicate>
void
__slist_deleter_common<T, Allocator>::unique(BinaryPredicate binary_pred)
{
	iterator e = end();
	for (iterator i = begin(); i != e;)
	{
		iterator j = i;
		iterator p = j;
		for (++j; j != e; ++j)
		{
			if (!binary_pred(*i, *j))
				break;
			p = j;
		}
		if (i != p)
			erase_after(i, p);
		++i;
	}
}

template <class T, class Allocator>
template <class Compare>
void
__slist_deleter_common<T, Allocator>::merge(__slist_deleter_common& x, Compare comp)
{
	if (this == &x)
		return;
	iterator first1 = begin();
	iterator last1 = end();
	iterator first2 = x.begin();
	iterator last2 = x.end();
	iterator pfirst1 = last1;
	iterator pfirst2 = last2;
	for (; first1 != last1 && first2 != last2; ++first1)
	{
		if (comp(*first2, *first1))
		{
			iterator j = first2;
			iterator pj = j;
			for (++j; j != last2; ++j)
			{
				if (!comp(*j, *first1))
					break;
				pj = j;
			}
			splice_after(pfirst1, x, pfirst2, pj);
			first2 = j;
		}
		pfirst1 = first1;
	}
	if (first2 != last2)
		splice_after(pfirst1, x);
}

template <class T, class Allocator>
template <class Compare>
void
__slist_deleter_common<T, Allocator>::sort(Compare comp)
{
	size_type sz = size();
	switch (sz)
	{
	case 0:
	case 1:
		break;
	case 2:
		{
		iterator i = begin();
		iterator j = i;
		++j;
		if (comp(*j, *i))
			reverse();
		}
		break;
	default:
		{
		size_type lower_size = sz / 2;
		iterator i = begin();
		_STD::advance(i, lower_size - 1);
		__slist_deleter_common upper_half(alloc());
		upper_half.splice_after(upper_half.end(), *this, i, iterator(last_node()));
		sort<Compare>(comp);
		upper_half.template sort<Compare>(comp);
		merge<Compare>(upper_half, comp);
		}
		break;
	}
}

#ifndef _Inhibit_Container_Optimization

// __slist_imp<true> for PODs

template <class T, class Allocator>
class __slist_imp<T, Allocator, true>
	: public __slist_deleter_common<typename store_as<T>::type,
	                                typename Allocator::rebind<typename store_as<T>::type>::other>,
	  private compile_assert<bool(sizeof(T) == sizeof(typename store_as<T>::type))>
{
	typedef typename store_as<T>::type base_type;
	typedef typename Allocator::rebind<base_type>::other base_allocator_type;
	typedef __slist_deleter_common<base_type, base_allocator_type> base;
public:
	// types:
	typedef T                                        value_type;
	typedef Allocator                                allocator_type;
	typedef typename allocator_type::reference       reference;
	typedef typename allocator_type::const_reference const_reference;
	typedef typename allocator_type::size_type       size_type;
	typedef typename allocator_type::difference_type difference_type;
	typedef typename allocator_type::pointer         pointer;
	typedef typename allocator_type::const_pointer   const_pointer;

	template <bool is_const>
	class __generic_iterator
	{
		typedef typename select<is_const, typename base::const_iterator,
		                                  typename base::iterator>::type base_iterator;
	public:
		typedef typename __slist_imp::value_type       value_type;
		typedef typename __slist_imp::difference_type  difference_type;
		typedef typename select<is_const, typename __slist_imp::const_pointer,
		                                  typename __slist_imp::pointer>::type pointer;
		typedef typename select<is_const, typename __slist_imp::const_reference,
		                                  typename __slist_imp::reference>::type reference;
		typedef _STD::forward_iterator_tag iterator_category;

		__generic_iterator() {}
		__generic_iterator(const __generic_iterator<false>& i)
			: i_(i.i_) {}
		reference operator * () const {return reference(*i_);}
		pointer operator -> () const  {return pointer(&*i_);}
		__generic_iterator& operator ++ ()
			{
				++i_;
				return *this;
			}
		__generic_iterator operator ++ (int) {__generic_iterator tmp(*this); ++(*this); return tmp;}
		friend bool operator ==(const __generic_iterator& x, const __generic_iterator& y) {return x.i_ == y.i_;}
		friend bool operator !=(const __generic_iterator& x, const __generic_iterator& y) {return x.i_ != y.i_;}

#ifndef __GNUC__
	private:

		friend class __generic_iterator<true>;
		friend class __slist_imp;
#endif  // __GNUC__

		base_iterator i_;

		explicit __generic_iterator(const base_iterator& i)
			: i_(i) {}
	};

	typedef __generic_iterator<false> iterator;
	typedef __generic_iterator<true>  const_iterator;

	__slist_imp() {}
	explicit __slist_imp(const allocator_type& a) : base(a) {}
	explicit __slist_imp(size_type n) {base::init(n, to_base_type(value_type()));}
	__slist_imp(size_type n, const value_type& value) {base::init(n, to_base_type(value));}
	__slist_imp(size_type n, const value_type& value, const allocator_type& a)
		: base(a) {base::init(n, to_base_type(value));}
	__slist_imp(const __slist_imp& x)
		: base(x.alloc()) {choose_init(x.begin(), x.end(), int2type<false>());}

	template <class InputIterator>
		void choose_init(InputIterator f, InputIterator l, int2type<true>)
			{base::init(static_cast<size_type>(f), to_base_type((value_type)(l)));}
	template <class InputIterator>
		void choose_init(InputIterator f, InputIterator l, int2type<false>)
		{
			typedef typename _STD::iterator_traits<InputIterator>::value_type outside_value;
			choose_init(f, l, int2type<is_same<outside_value, value_type>::value>(),
			                  int2type<is_same<value_type, base_type>::value>());
		}

	iterator       begin()       {return       iterator(base::begin());}
	const_iterator begin() const {return const_iterator(base::begin());}
	iterator       end()         {return       iterator(base::end());}
	const_iterator end() const   {return const_iterator(base::end());}

	iterator       previous(iterator x)             {return       iterator(base::previous(x.i_));}
	const_iterator previous(const_iterator x) const {return const_iterator(base::previous(x.i_));}

	reference       front()       {return       reference(base::front());}
	const_reference front() const {return const_reference(base::front());}

	void push_front(const value_type& value) {base::push_front(to_base_type(value));}
	iterator insert_after(iterator pos, const value_type& value)
		{return iterator(base::insert_after(pos.i_, to_base_type(value)));}
	void insert_after(iterator pos, size_type n, const value_type& value)
		{base::insert_after(pos.i_, n, to_base_type(value));}

	void assign(size_type n, const value_type& value) {base::assign(n, to_base_type(value));}
	template <class InputIterator>
		void
		choose_assign(InputIterator first, InputIterator last, int2type<true>)
			{base::assign(static_cast<size_type>(first), to_base_type((value_type)last));}
	template <class InputIterator>
		void choose_assign(InputIterator f, InputIterator l, int2type<false>)
		{
			typedef typename _STD::iterator_traits<InputIterator>::value_type outside_value;
			choose_assign(f, l, int2type<is_same<outside_value, value_type>::value>(),
			                    int2type<is_same<value_type, base_type>::value>());
		}
	template <class InputIterator>
		void
		choose_insert_after(iterator pos, InputIterator first, InputIterator last, int2type<true>)
			{base::insert_after(pos.i_, static_cast<size_type>(first), to_base_type((value_type)(last)));}
	template <class InputIterator>
		void
		choose_insert_after(iterator p, InputIterator f, InputIterator l, int2type<false>)
		{
			typedef typename _STD::iterator_traits<InputIterator>::value_type outside_value;
			choose_insert_after(p, f, l, int2type<is_same<outside_value, value_type>::value>(),
			                             int2type<is_same<value_type, base_type>::value>());
		}
	iterator erase_after(iterator pos)                  {return iterator(base::erase_after(pos.i_));}
	iterator erase_after(iterator first, iterator last) {return iterator(base::erase_after(first.i_, last.i_));}

	void resize(size_type n)                          {base::resize(n);}
	void resize(size_type n, const value_type& value) {base::resize(n, to_base_type(value));}

	void splice_after(iterator pos, __slist_imp& x)                         {base::splice_after(pos.i_, x);}
	void splice_after(iterator pos, __slist_imp& x, iterator f)             {base::splice_after(pos.i_, x, f.i_);}
	void splice_after(iterator pos, __slist_imp& x, iterator f, iterator l) {base::splice_after(pos.i_, x, f.i_, l.i_);}

#ifdef _MSL_EXTENDED_BINDERS
	void remove(const value_type& value)
		{remove_if(_STD::binder2nd<_STD::equal_to<value_type>, const value_type&>(_STD::equal_to<value_type>(), value));}
#else  // _MSL_EXTENDED_BINDERS
	void remove(const value_type& value)
		{remove_if(_STD::bind2nd(_STD::equal_to<value_type>(), value));}
#endif  // _MSL_EXTENDED_BINDERS
	template <class Predicate> void remove_if(Predicate pred)
		{base::remove_if(unary_convert<Predicate>(pred));}

	void unique() {unique(_STD::equal_to<value_type>());}
	template <class BinaryPredicate> void unique(BinaryPredicate binary_pred)
		{base::unique(binary_convert<BinaryPredicate>(binary_pred));}

	void merge(__slist_imp& x)                   {merge(x, _STD::less<value_type>());}
	template <class Compare>
		void merge(__slist_imp& x, Compare comp) {base::merge(x, binary_convert<Compare>(comp));}

	void sort() {sort(_STD::less<value_type>());}
	template <class Compare> void sort(Compare comp) {base::sort(binary_convert<Compare>(comp));}
private:

	template <class InputIterator>
		void choose_init(InputIterator f, InputIterator l, int2type<true>, int2type<true>)
			{base::init(f, l);}
	template <class InputIterator>
		void choose_init(InputIterator f, InputIterator l, int2type<false>, int2type<true>)
		{
			typedef _STD::__convert_iterator<_STD::__implicit_convert<pointer, InputIterator> > first_convert;
			base::init(first_convert(f), first_convert(l));
		}
	template <class InputIterator>
		void choose_init(InputIterator f, InputIterator l, int2type<true>, int2type<false>)
		{
			typedef _STD::__convert_iterator<_STD::__reinterpret_convert<typename base::pointer, InputIterator> > second_convert;
			base::init(second_convert(f), second_convert(l));
		}
	template <class InputIterator>
		void choose_init(InputIterator f, InputIterator l, int2type<false>, int2type<false>)
		{
			typedef _STD::__convert_iterator<_STD::__implicit_convert<pointer, InputIterator> > first_convert;
			typedef _STD::__convert_iterator<_STD::__reinterpret_convert<typename base::pointer, first_convert> > second_convert;
			base::init(second_convert(first_convert(f)), second_convert(first_convert(l)));
		}

	template <class InputIterator>
		void choose_assign(InputIterator f, InputIterator l, int2type<true>, int2type<true>)
			{base::assign(f, l);}
	template <class InputIterator>
		void choose_assign(InputIterator f, InputIterator l, int2type<false>, int2type<true>)
		{
			typedef _STD::__convert_iterator<_STD::__implicit_convert<pointer, InputIterator> > first_convert;
			base::assign(first_convert(f), first_convert(l));
		}
	template <class InputIterator>
		void choose_assign(InputIterator f, InputIterator l, int2type<true>, int2type<false>)
		{
			typedef _STD::__convert_iterator<_STD::__reinterpret_convert<typename base::pointer, InputIterator> > second_convert;
			base::assign(second_convert(f), second_convert(l));
		}
	template <class InputIterator>
		void choose_assign(InputIterator f, InputIterator l, int2type<false>, int2type<false>)
		{
			typedef _STD::__convert_iterator<_STD::__implicit_convert<pointer, InputIterator> > first_convert;
			typedef _STD::__convert_iterator<_STD::__reinterpret_convert<typename base::pointer, first_convert> > second_convert;
			base::assign(second_convert(first_convert(f)), second_convert(first_convert(l)));
		}

	template <class InputIterator>
		void choose_insert_after(iterator p, InputIterator f, InputIterator l, int2type<true>, int2type<true>)
			{base::insert_after(p.i_, f, l);}
	template <class InputIterator>
		void choose_insert_after(iterator p, InputIterator f, InputIterator l, int2type<false>, int2type<true>)
		{
			typedef _STD::__convert_iterator<_STD::__implicit_convert<pointer, InputIterator> > first_convert;
			base::insert_after(p.i_, first_convert(f), first_convert(l));
		}
	template <class InputIterator>
		void choose_insert_after(iterator p, InputIterator f, InputIterator l, int2type<true>, int2type<false>)
		{
			typedef _STD::__convert_iterator<_STD::__reinterpret_convert<typename base::pointer, InputIterator> > second_convert;
			base::insert_after(p.i_, second_convert(f), second_convert(l));
		}
	template <class InputIterator>
		void choose_insert_after(iterator p, InputIterator f, InputIterator l, int2type<false>, int2type<false>)
		{
			typedef _STD::__convert_iterator<_STD::__implicit_convert<pointer, InputIterator> > first_convert;
			typedef _STD::__convert_iterator<_STD::__reinterpret_convert<typename base::pointer, first_convert> > second_convert;
			base::insert_after(p.i_, second_convert(first_convert(f)), second_convert(first_convert(l)));
		}

	template <class Compare>
	class unary_convert
	{
	public:
		unary_convert(Compare comp) : comp_(comp) {}
		bool operator() (const base_type& x) {return comp_(const_reference(x));}
	private:
		Compare comp_;
	};

	template <class Compare>
	class binary_convert
	{
	public:
		binary_convert(Compare comp) : comp_(comp) {}
		bool operator() (const base_type& x, const base_type& y) {return comp_(const_reference(x), const_reference(y));}
	private:
		Compare comp_;
	};

	const base_type& to_base_type(const value_type& value) {return (const base_type&)value;}
};

#endif  // _Inhibit_Container_Optimization

// __slist_imp<false> for non-PODs

template <class T, class Allocator>
class __slist_imp<T, Allocator, false>
	: public __slist_deleter_common<T, Allocator>
{
	typedef __slist_deleter_common<T, Allocator> base;
public:
	// types:
	typedef T                                        value_type;
	typedef Allocator                                allocator_type;
	typedef typename allocator_type::reference       reference;
	typedef typename allocator_type::const_reference const_reference;
	typedef typename allocator_type::size_type       size_type;
	typedef typename allocator_type::difference_type difference_type;
	typedef typename allocator_type::pointer         pointer;
	typedef typename allocator_type::const_pointer   const_pointer;
	typedef typename base::iterator                  iterator;
	typedef typename base::const_iterator            const_iterator;

	__slist_imp() {}
	explicit __slist_imp(const allocator_type& a) : base(a) {}
	explicit __slist_imp(size_type n)                 {base::init(n, value_type());}
	__slist_imp(size_type n, const value_type& value) {base::init(n, value);}
	__slist_imp(size_type n, const value_type& value, const allocator_type& a)
		: base(a) {base::init(n, value);}
	template <class InputIterator>
		void choose_init(InputIterator f, InputIterator l, int2type<true>)
			{base::init(static_cast<size_type>(f), static_cast<value_type>(l));}
	template <class InputIterator>
		void choose_init(InputIterator f, InputIterator l, int2type<false>)
			{base::init(f, l);}
	__slist_imp(const __slist_imp& x)
		: base(x.alloc()) {choose_init(x.begin(), x.end(), int2type<false>());}

	template <class InputIterator>
		void
		choose_assign(InputIterator first, InputIterator last, int2type<true>)
			{base::assign(static_cast<size_type>(first), static_cast<value_type>(last));}
	template <class InputIterator>
		void
		choose_assign(InputIterator first, InputIterator last, int2type<false>)
			{base::assign(first, last);}
	template <class InputIterator>
		void
		choose_insert_after(iterator pos, InputIterator first, InputIterator last, int2type<true>)
			{base::insert_after(pos, static_cast<size_type>(first), static_cast<value_type>(last));}
	template <class InputIterator>
		void
		choose_insert_after(iterator pos, InputIterator first, InputIterator last, int2type<false>)
			{base::insert_after(pos, first, last);}
};

#ifdef _MSL_DEBUG

	template <class Predicate, class ForwardIterator>
	class __slist_remove_pred
	{
	public:
		__slist_remove_pred(const Predicate& pred) : pred_(pred) {}

		bool operator() (const ForwardIterator& it) const
			{return pred_(*it);}
	private:
		Predicate pred_;
	};

#endif  // _MSL_DEBUG

// slist

template <class T, class Allocator = _STD::allocator<T> >
class slist
#ifndef _Inhibit_Container_Optimization
	: private __slist_imp<T, Allocator, is_POD<T>::value>
#else
	: private __slist_imp<T, Allocator, false>
#endif
{
#ifndef _Inhibit_Container_Optimization
	typedef __slist_imp<T, Allocator, is_POD<T>::value> base;
#else
	typedef __slist_imp<T, Allocator, false>            base;
#endif
public:
	typedef slist                                    __self;
	typedef T                                        value_type;
	typedef Allocator                                allocator_type;
	typedef typename allocator_type::reference       reference;
	typedef typename allocator_type::const_reference const_reference;
	typedef typename allocator_type::size_type       size_type;
	typedef typename allocator_type::difference_type difference_type;
	typedef typename allocator_type::pointer         pointer;
	typedef typename allocator_type::const_pointer   const_pointer;
#ifndef _MSL_DEBUG
	typedef typename base::iterator                  iterator;
	typedef typename base::const_iterator            const_iterator;
#else  // _MSL_DEBUG
	typedef typename base::iterator                  __uncheck_iterator;
	typedef typename base::const_iterator            __uncheck_const_iterator;
	typedef _STD::__debug_iterator<slist, __uncheck_iterator, true>        iterator;
	typedef _STD::__debug_iterator<slist, __uncheck_const_iterator, true>  const_iterator;
private:
	__uncheck_iterator __iterator2base(const iterator& i)
		{
			if (i.owner_ != this)
				_MSL_DEBUG_ERROR(_STD::logic_error, "MSL DEBUG: invalid iterator given to slist");
			return i.base();
		}
	__uncheck_const_iterator __iterator2base(const const_iterator& i) const
		{
			if (i.owner_ != this)
				_MSL_DEBUG_ERROR(_STD::logic_error, "MSL DEBUG: invalid iterator given to slist");
			return i.base();
		}
	iterator       __base2iterator(const __uncheck_iterator& p)             {return iterator(this, p);}
	const_iterator __base2iterator(const __uncheck_const_iterator& p) const {return const_iterator(this, p);}

	void __invalidate_all_iterators()
	{
		if (iterator_list<iterator>())
			iterator_list<iterator>()->remove(_STD::__unary_true_value<__uncheck_iterator>());
		if (iterator_list<const_iterator>())
			iterator_list<const_iterator>()->remove(_STD::__unary_true_value<__uncheck_const_iterator>());
	}
	void __invalidate_iterator(const iterator& i)
	{
		if (iterator_list<iterator>())
			iterator_list<iterator>()->remove(_STD::bind2nd(_STD::equal_to<__uncheck_iterator>(), i.base()));
		if (iterator_list<const_iterator>())
			iterator_list<const_iterator>()->remove(_STD::bind2nd(_STD::equal_to<__uncheck_const_iterator>(), i.base()));
	}
public:
#endif  // _MSL_DEBUG

	slist() {}
	explicit slist(const allocator_type& a) : base(a) {}
	explicit slist(size_type n) : base(n) {}
	slist(size_type n, const value_type& value) : base(n, value) {}
	slist(size_type n, const value_type& value, const allocator_type& a) : base(n, value, a) {}
	template <class InputIterator>
		slist(InputIterator first, InputIterator last)
			{base::choose_init(first, last, int2type<is_integral<InputIterator>::value>());}
	template <class InputIterator>
		slist(InputIterator first, InputIterator last, const allocator_type& a)
			: base(a)
			{base::choose_init(first, last, int2type<is_integral<InputIterator>::value>());}

#ifdef _MSL_DEBUG
	slist(const slist& x) : base(x) {}
	~slist() {__invalidate_all_iterators();}
	slist& operator=(const slist& x)
	{
		if (this != &x)
		{
			__invalidate_all_iterators();
			base::operator=(x);
		}
		return *this;
	}

#endif  // _MSL_DEBUG

	using base::size;
	using base::empty;
	using base::max_size;

	using base::front;
	using base::push_front;

	allocator_type get_allocator() const {return base::alloc();}

//	using base::sort;
	void sort() {base::sort();}
	template <class Compare> void sort(Compare comp) {base::template sort<Compare>(comp);}

	using base::reverse;
	//  void reverse();

	using base::invariants;

#ifndef _MSL_DEBUG
	using base::begin;
	using base::end;
	using base::previous;

	using base::pop_front;

	iterator insert_after(iterator pos, const value_type& value)
		{return base::insert_after(pos, value);}
	void     insert_after(iterator pos, size_type n, const value_type& value)
		{base::insert_after(pos, n, value);}
	template <class InputIterator>
		void
		insert_after(iterator pos, InputIterator first, InputIterator last)
			{base::choose_insert_after(pos, first, last, int2type<is_integral<InputIterator>::value>());}

	iterator insert(iterator pos, const value_type& value)
		{return insert_after(previous(pos), value);}
	void insert(iterator pos, size_type n, const value_type& value)
		{insert_after(previous(pos), n, value);}
	template <class InputIterator>
		void insert(iterator pos, InputIterator first, InputIterator last)
			{insert_after(previous(pos), first, last);}

	using base::erase_after;
	iterator erase(iterator pos)
		{return ++erase_after(previous(pos));}
	iterator erase(iterator first, iterator last)
		{return ++erase_after(previous(first), previous(last));}
	using base::clear;

	void assign(size_type n, const value_type& value) {base::assign(n, value);}
	template <class InputIterator>
		void
		assign(InputIterator first, InputIterator last)
			{base::choose_assign(first, last, int2type<is_integral<InputIterator>::value>());}

	using base::resize;
	void swap(slist& x) {base::swap(x);}
	void splice_after(iterator pos, slist& x)                         {base::splice_after(pos, x);}
	void splice_after(iterator pos, slist& x, iterator f)             {base::splice_after(pos, x, f);}
	void splice_after(iterator pos, slist& x, iterator f, iterator l) {base::splice_after(pos, x, f, l);}
	void splice(iterator pos, slist& x)                         {splice_after(previous(pos), x);}
	void splice(iterator pos, slist& x, iterator f)             {splice_after(previous(pos), x, x.previous(f));}
	void splice(iterator pos, slist& x, iterator f, iterator l) {splice_after(previous(pos), x, x.previous(f), x.previous(l));}

	using base::remove;
	//  void remove(const value_type& value);
//	using base::remove_if;
	template <class Predicate> void remove_if(Predicate pred) {base::template remove_if<Predicate>(pred);}

//	using base::unique;
	void unique() {base::unique();}
	template <class BinaryPredicate> void unique(BinaryPredicate binary_pred) {base::template unique<BinaryPredicate>(binary_pred);}

	void merge(slist& x)                   {base::merge(x);}
	template <class Compare>
		void merge(slist& x, Compare comp) {base::template merge<Compare>(x, comp);}

#else  // _MSL_DEBUG

	__uncheck_iterator       __uncheck_begin()       {return base::begin();}
	__uncheck_const_iterator __uncheck_begin() const {return base::begin();}
	__uncheck_iterator       __uncheck_end()         {return base::end();}
	__uncheck_const_iterator __uncheck_end() const   {return base::end();}

	iterator               begin()       {return __base2iterator(base::begin());}
	const_iterator         begin() const {return __base2iterator(base::begin());}
	iterator               end()         {return __base2iterator(base::end());}
	const_iterator         end() const   {return __base2iterator(base::end());}

	iterator       previous(iterator x)             {return __base2iterator(base::previous(__iterator2base(x)));}
	const_iterator previous(const_iterator x) const {return __base2iterator(base::previous(__iterator2base(x)));}

	void pop_front()
		{
		#ifdef _MSL_DEBUG
			if (empty())
				_MSL_DEBUG_ERROR(_STD::logic_error, "MSL DEBUG: pop_front called on empty slist");
		#endif  // _MSL_DEBUG
			__invalidate_iterator(begin());
			base::pop_front();
		}

	iterator insert_after(iterator pos, const value_type& value)
		{return __base2iterator(base::insert_after(__iterator2base(pos), value));}
	void     insert_after(iterator pos, size_type n, const value_type& value)
		{base::insert_after(__iterator2base(pos), n, value);}
	template <class InputIterator>
		void insert_after(iterator pos, InputIterator f, InputIterator l)
			{base::choose_insert_after(__iterator2base(pos), f, l, int2type<is_integral<InputIterator>::value>());}

	iterator insert(iterator pos, const value_type& value)
		{return __base2iterator(base::insert_after(base::previous(__iterator2base(pos)), value));}
	void insert(iterator pos, size_type n, const value_type& value)
		{base::insert_after(base::previous(__iterator2base(pos)), n, value);}
	template <class InputIterator>
		void insert(iterator pos, InputIterator first, InputIterator last)
			{base::choose_insert_after(base::previous(__iterator2base(pos)), first, last, int2type<is_integral<InputIterator>::value>());}

	iterator erase_after(iterator pos)
		{
			typename base::iterator p = __iterator2base(pos);
			++pos;
			pos.deref();
			__invalidate_iterator(pos);
			return __base2iterator(base::erase_after(p));
		}
	iterator erase_after(iterator first, iterator last)
		{
			typename base::iterator f = __iterator2base(first);
			typename base::iterator l = __iterator2base(last);
			if (first != last)
			{
				bool notdone = true;
				iterator i = first;
				for (++i; notdone;)
				{
					if (i == last)
						notdone = false;
					i.deref();
					if (notdone)
						__invalidate_iterator(i++);
					else
						__invalidate_iterator(i);
				}
			}
			return __base2iterator(base::erase_after(f, l));
		}
	iterator erase(iterator pos)
		{return ++erase_after(previous(pos));}
	iterator erase(iterator first, iterator last)
		{return ++erase_after(previous(first), previous(last));}

	void clear() {__invalidate_all_iterators(); base::clear();}

	void assign(size_type n, const value_type& value)
		{__invalidate_all_iterators(); base::assign(n, value);}
	template <class InputIterator>
		void
		assign(InputIterator first, InputIterator last)
			{
				__invalidate_all_iterators();
				base::choose_assign(first, last, int2type<is_integral<InputIterator>::value>());
			}

	void resize(size_type n)
		{
			iterator i = begin();
			iterator e = end();
			for (size_type c = n; i != e && c > 0; ++i)
				--c;
			while (i != e)
				__invalidate_iterator(i++);
			base::resize(n);
		}
	void resize(size_type n, const value_type& value)
		{
			iterator i = begin();
			iterator e = end();
			for (size_type c = n; i != e && c > 0; ++i)
				--c;
			while (i != e)
				__invalidate_iterator(i++);
			base::resize(n, value);
		}

	void swap(slist& x)
		{
			iterator::swap(this, &x);
			const_iterator::swap(this, &x);
			base::swap(x);
		}

	void splice_after(iterator pos, slist& x)
	{
		if (x.template iterator_list<iterator>())
			x.template iterator_list<iterator>()->add(this, _STD::__unary_true_value<__uncheck_iterator>());
		if (x.template iterator_list<const_iterator>())
			x.template iterator_list<const_iterator>()->add(this, _STD::__unary_true_value<__uncheck_const_iterator>());
		base::splice_after(__iterator2base(pos), x);
	}
	void splice_after(iterator pos, slist& x, iterator f)
	{
		typename base::iterator i = x.__iterator2base(f);
		++f;
		f.deref();
		if (this != &x)
		{
			if (x.template iterator_list<iterator>())
				x.template iterator_list<iterator>()->add(this, _STD::bind2nd(_STD::equal_to<__uncheck_iterator>(), f.base()));
			if (x.template iterator_list<const_iterator>())
				x.template iterator_list<const_iterator>()->add(this, _STD::bind2nd(_STD::equal_to<__uncheck_const_iterator>(), f.base()));
		}
		base::splice_after(__iterator2base(pos), x, i);
	}
	void splice_after(iterator pos, slist& x, iterator first, iterator last)
	{
		typename base::iterator f = x.__iterator2base(first);
		typename base::iterator l = x.__iterator2base(last);
		if (first != last)
		{
			iterator i = first;
			bool notdone = true;
			for (++i;  notdone;)
			{
				if (i == last)
					notdone = false;
				iterator j = i;
				++i;
				j.deref();
				if (this != &x)
				{
					if (x.template iterator_list<iterator>())
						x.template iterator_list<iterator>()->add(this, _STD::bind2nd(_STD::equal_to<__uncheck_iterator>(), j.base()));
					if (x.template iterator_list<const_iterator>())
						x.template iterator_list<const_iterator>()->add(this, _STD::bind2nd(_STD::equal_to<__uncheck_const_iterator>(), j.base()));
				}
			}
		}
		base::splice_after(__iterator2base(pos), x, f, l);
	}

	void splice(iterator pos, slist& x)                         {splice_after(previous(pos), x);}
	void splice(iterator pos, slist& x, iterator f)             {splice_after(previous(pos), x, x.previous(f));}
	void splice(iterator pos, slist& x, iterator f, iterator l) {splice_after(previous(pos), x, x.previous(f), x.previous(l));}

#ifdef _MSL_EXTENDED_BINDERS
	void remove(const value_type& value)
		{remove_if(_STD::binder2nd<_STD::equal_to<value_type>, const value_type&>(_STD::equal_to<value_type>(), value));}
#else  // _MSL_EXTENDED_BINDERS
	void remove(const value_type& value)
		{remove_if(_STD::bind2nd(_STD::equal_to<value_type>(), value));}
#endif  // _MSL_EXTENDED_BINDERS
	template <class Predicate> void remove_if(Predicate pred)
	{
		if (iterator_list<iterator>())
			iterator_list<iterator>()->remove(__slist_remove_pred<Predicate, __uncheck_iterator>(pred));
		if (iterator_list<const_iterator>())
			iterator_list<const_iterator>()->remove(__slist_remove_pred<Predicate, __uncheck_const_iterator>(pred));
		base::template remove_if<Predicate>(pred);
	}

	void unique() {unique(_STD::equal_to<value_type>());}
	template <class BinaryPredicate> void unique(BinaryPredicate binary_pred)
	{
		iterator e = end();
		for (iterator i = begin(); i != e;)
		{
			iterator j = i;
			for (++j; j != e;)
			{
				if (!binary_pred(*i, *j))
					break;
				__invalidate_iterator(j++);
			}
			i = j;
		}
		base::template unique<BinaryPredicate>(binary_pred);
	}

	void merge(slist& x)
	{
		if (x.template iterator_list<iterator>())
			x.template iterator_list<iterator>()->add(this, _STD::__unary_true_value<__uncheck_iterator>());
		if (x.template iterator_list<const_iterator>())
			x.template iterator_list<const_iterator>()->add(this, _STD::__unary_true_value<__uncheck_const_iterator>());
		base::merge(x);
	}
	template <class Compare>
		void merge(slist& x, Compare comp)
		{
			if (x.template iterator_list<iterator>())
				x.template iterator_list<iterator>()->add(this, _STD::__unary_true_value<__uncheck_iterator>());
			if (x.template iterator_list<const_iterator>())
				x.template iterator_list<const_iterator>()->add(this, _STD::__unary_true_value<__uncheck_const_iterator>());
			base::template merge<Compare>(x, comp);
		}

private:
	_STD::pair<iterator*, const_iterator*> iterator_list_;

	iterator*&       iterator_list(iterator*)       {return iterator_list_.first;}
	const_iterator*& iterator_list(const_iterator*) {return iterator_list_.second;}
	template <class Iterator>
	Iterator*& iterator_list() {return iterator_list((Iterator*)0);}

	friend class iterator;
	friend class const_iterator;
#endif  // _MSL_DEBUG
};

template <class T, class Allocator>
inline
bool
operator==(const slist<T, Allocator>& x, const slist<T, Allocator>& y)
{
	return x.size() == y.size() && _STD::equal(x.begin(), x.end(), y.begin());
}

template <class T, class Allocator>
inline
bool
operator!=(const slist<T, Allocator>& x, const slist<T, Allocator>& y)
{
	return !(x == y);
}

template <class T, class Allocator>
inline
bool
operator< (const slist<T, Allocator>& x, const slist<T, Allocator>& y)
{
	return _STD::lexicographical_compare(x.begin(), x.end(), y.begin(), y.end());
}

template <class T, class Allocator>
inline
bool
operator> (const slist<T, Allocator>& x, const slist<T, Allocator>& y)
{
	return y < x;
}

template <class T, class Allocator>
inline
bool
operator>=(const slist<T, Allocator>& x, const slist<T, Allocator>& y)
{
	return !(x < y);
}

template <class T, class Allocator>
inline
bool
operator<=(const slist<T, Allocator>& x, const slist<T, Allocator>& y)
{
	return !(y < x);
}

// specialized algorithms:

template <class T, class Allocator>
inline
void
swap(slist<T, Allocator>& x, slist<T, Allocator>& y)
{
	x.swap(y);
}

#ifndef _MSL_DEBUG

template<class T, class Allocator>
struct has_trivial_dtor_after_move_ctor<slist<T, Allocator> >
{
	static const bool value = has_trivial_dtor<Allocator>::value;
};

#endif  // _MSL_DEBUG

template<class T, class Allocator>
struct move_with_swap<slist<T, Allocator> >
{
	static const bool value = has_trivial_copy_ctor<Allocator>::value &&
	                          has_trivial_assignment<Allocator>::value;
};

template<class T, class Allocator>
struct has_nothrow_constructor<slist<T, Allocator> >
{
	static const bool value = has_nothrow_constructor<Allocator>::value;
};

#ifndef _MSL_NO_CPP_NAMESPACE
	} // namespace Metrowerks
#endif

#ifdef _MSL_FORCE_ENUMS_ALWAYS_INT
	#pragma enumsalwaysint reset
#endif

#ifdef _MSL_FORCE_ENABLE_BOOL_SUPPORT
	#pragma bool reset
#endif

#ifdef __MWERKS__
#pragma options align=reset
#endif

#endif // RC_INVOKED

#endif // _SLIST

// hh 990629 Rewrote
// hh 990825 changed void* to const void*
// hh 991116 Fixed pointer conversion bug in T* specialization by introducing __convert_iterator
// hh 000129 Moved into namespace Metrowerks
// hh 001011 Fixed scoping error in remove_if
// hh 001011 Fixed several typename bugs
// hh 001011 Disabled friends of iterators for gcc
// hh 010125 Changed function prototype to variable initialization in constructor
// hh 010301 Protected min and max from macro abuse.
// hh 010402 Removed 68K CMF support
// hh 020102 Rewrote
// hh 020529 Changed <limits> to <msl_int_limits>
// hh 030212 Added empty check for pop_front under _MSL_DEBUG
// hh 030527 Made pseudo movable
// hh 030711 Worked around friend class T problem
