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

// list

#ifndef _LIST
#define _LIST

/*  list synopsis

namespace std
{

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

	class                                         iterator;        // bidirectional
	class                                         const_iterator;  // bidirectional
	typedef std::reverse_iterator<iterator>       reverse_iterator;
	typedef std::reverse_iterator<const_iterator> const_reverse_iterator;

	explicit list(const Allocator& = Allocator());
	explicit list(size_type n, const T& value = T(), const Allocator& = Allocator());
	template <class InputIterator>
		list(InputIterator first, InputIterator last, const Allocator& = Allocator());
	list(const list& x);
	list& operator=(const list& x);
	~list();

	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;

	reverse_iterator       rbegin();
	const_reverse_iterator rbegin() const;
	reverse_iterator       rend();
	const_reverse_iterator rend() const;

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

	reference       front();
	const_reference front() const;
	reference       back();
	const_reference back() const;

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

	iterator insert(iterator position, const T& x);
	void     insert(iterator position, size_type n, const T& x);
	template <class InputIterator>
		void insert(iterator position, InputIterator first , InputIterator last);

	iterator erase(iterator position);
	iterator erase(iterator position, iterator last);
	void     clear();

	void swap(list&);

	void splice(iterator position, list& x);
	void splice(iterator position, list& x, iterator i);
	void splice(iterator position, list& x, iterator first, iterator last);
	void splice(iterator position, list& x, iterator first, iterator last, size_type n);  // Metrowerks extension

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

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

	void merge(list& x);
	template <class Compare> void merge(list& 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 list<T,A>& x, const list<T,A>& y);
template <class T, class A> bool operator< (const list<T,A>& x, const list<T,A>& y);
template <class T, class A> bool operator!=(const list<T,A>& x, const list<T,A>& y);
template <class T, class A> bool operator> (const list<T,A>& x, const list<T,A>& y);
template <class T, class A> bool operator>=(const list<T,A>& x, const list<T,A>& y);
template <class T, class A> bool operator<=(const list<T,A>& x, const list<T,A>& y);

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

}  // std
*/

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

#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 std {
#endif

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

	struct node;

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

	struct node_base
	{
		node_pointer prev_;
		node_pointer next_;
	};

	struct node
		: public node_base
	{
		value_type data_;
	};

	typedef typename allocator_type::rebind<node_base>::other::pointer node_base_pointer;

	template <bool is_const>
	class generic_iterator
	{
	public:
		typedef T value_type;
		typedef typename __list_deleter::difference_type  difference_type;
		typedef typename Metrowerks::select<is_const, typename __list_deleter::const_pointer,
		                                              typename __list_deleter::pointer>::type pointer;
		typedef typename Metrowerks::select<is_const, typename __list_deleter::const_reference,
		                                              typename __list_deleter::reference>::type reference;
		typedef bidirectional_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); node_ = node_->next_; return tmp;}
		generic_iterator& operator -- () {node_ = node_->prev_; return *this;}
		generic_iterator operator -- (int) {generic_iterator tmp(*this); node_ = node_->prev_; 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_;}
	private:
		typedef typename Metrowerks::select<is_const, typename node_allocator_type::const_pointer,
		                                              typename node_allocator_type::pointer>::type node_pointer;
		typedef typename node_allocator_type::rebind<node_base>::other node_base_allocator;
		typedef typename Metrowerks::select<is_const, typename node_base_allocator::const_pointer,
		                                              typename node_base_allocator::pointer>::type node_base_pointer;

#ifdef __GNUC__
		typedef typename Metrowerks::friend_helper<generic_iterator<true>,generic_iterator>::type friend_type;
		friend class generic_iterator::friend_type;
#else  // __GNUC__
		friend class generic_iterator<true>;
#endif
		friend class __list_deleter;

		node_pointer node_;

		explicit generic_iterator(node_pointer n) : node_(n) {}
		explicit generic_iterator(node_base_pointer n) : node_((node_pointer)n) {}
	};
#ifndef _MSL_DEBUG
	typedef generic_iterator<false> iterator;
	typedef generic_iterator<true>  const_iterator;

	static node_pointer __iterator2pointer(iterator& i) {return i.node_;}
	static iterator __pointer2iterator(node_pointer p) {return iterator(p);}
#else  // _MSL_DEBUG
private:
	typedef generic_iterator<false> __uncheck_iterator;
	typedef generic_iterator<true>  __uncheck_const_iterator;
public:
	typedef __debug_iterator<__list_deleter, __uncheck_iterator>        iterator;
	typedef __debug_iterator<__list_deleter, __uncheck_const_iterator>  const_iterator;
private:
	void __invalidate_iterator(const iterator& i)
	{
		if (iterator_list<iterator>())
			iterator_list<iterator>()->remove(bind2nd(equal_to<__uncheck_iterator>(), i.base()));
		if (iterator_list<const_iterator>())
			iterator_list<const_iterator>()->remove(bind2nd(equal_to<__uncheck_const_iterator>(), i.base()));
	}

	node_pointer __iterator2pointer(iterator& i)
	{
		if (i.owner_ != this)
			_MSL_DEBUG_ERROR(logic_error, "MSL DEBUG: invalid iterator given to list");
		return i.base().node_;
	}
	iterator __pointer2iterator(node_pointer p) {return iterator(this, __uncheck_iterator(p));}
public:
#endif  // _MSL_DEBUG

	__list_deleter();
	explicit __list_deleter(const allocator_type& a);

	~__list_deleter()
	{
		erase(begin(), end());
	#ifdef _MSL_DEBUG
		__invalidate_iterator(end());
	#endif
	}

#ifndef _MSL_DEBUG
	iterator       begin()       {return iterator(tail().next_);}
	const_iterator begin() const {return const_iterator(tail().next_);}
	iterator       end()         {return iterator(&tail());}
	const_iterator end() const   {return const_iterator(&tail());}
#else  // _MSL_DEBUG
	iterator       begin()       {return iterator(this, __uncheck_begin());}
	const_iterator begin() const {return const_iterator(this, __uncheck_begin());}
	iterator       end()         {return iterator(this, __uncheck_end());}
	const_iterator end() const   {return const_iterator(this, __uncheck_end());}
private:
	__uncheck_iterator       __uncheck_begin()       {return __uncheck_iterator(tail().next_);}
	__uncheck_const_iterator __uncheck_begin() const {return __uncheck_const_iterator(tail().next_);}
	__uncheck_iterator       __uncheck_end()         {return __uncheck_iterator(&tail());}
	__uncheck_const_iterator __uncheck_end() const   {return __uncheck_const_iterator(&tail());}
public:
#endif  // _MSL_DEBUG

	//  element access:
	reference       front()       {return tail().next_->data_;}
	const_reference front() const {return tail().next_->data_;}
	reference       back()        {return tail().prev_->data_;}
	const_reference back() const  {return tail().prev_->data_;}

	iterator insert(iterator position, const value_type& x);

	iterator erase(iterator position);
	iterator erase(iterator first, iterator last);
	void clear() {erase(begin(), end());}

	void pop_front()
		{
		#ifdef _MSL_DEBUG
			if (sz() == 0)
				_MSL_DEBUG_ERROR(logic_error, "MSL DEBUG: pop_front called on empty list");
		#endif  // _MSL_DEBUG
			erase(__pointer2iterator(tail().next_));
		}
	void pop_back()
		{
		#ifdef _MSL_DEBUG
			if (sz() == 0)
				_MSL_DEBUG_ERROR(logic_error, "MSL DEBUG: pop_back called on empty list");
		#endif  // _MSL_DEBUG
			erase(__pointer2iterator(tail().prev_));
		}

	void splice(iterator position, __list_deleter& x);
	void splice(iterator position, __list_deleter& x, iterator i);
	void splice(iterator position, __list_deleter& x, iterator first, iterator last);
	void splice(iterator position, __list_deleter& x, iterator first, iterator last, size_type n);

	void swap(__list_deleter& x);

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

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

	void reverse();

	allocator_type&       alloc()       {return size_.first();}
	const allocator_type& alloc() const {return size_.first();}

	size_type&       sz()       {return size_.second();}
	const size_type& sz() const {return size_.second();}

	node_allocator_type&       node_alloc()       {return end_.first();}
	const node_allocator_type& node_alloc() const {return end_.first();}

	node_base&       tail()       {return end_.second();}
	const node_base& tail() const {return end_.second();}

	bool invariants() const;
private:
	Metrowerks::compressed_pair<allocator_type, size_type>      size_;
	Metrowerks::compressed_pair<node_allocator_type, node_base> end_;

#ifdef _MSL_DEBUG
	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

	__list_deleter(const __list_deleter&);  // not defined
	__list_deleter& operator=(const __list_deleter&);  // not defined

	static void remove_nodes(node_base_pointer first, node_base_pointer last);
	static void insert_nodes(node_base_pointer here, node_base_pointer first, node_base_pointer last);
};

// range is [first, last] NOT [first, last)
template <class T, class Allocator>
inline
void
__list_deleter<T, Allocator>::remove_nodes(node_base_pointer first, node_base_pointer last)
{
	first->prev_->next_ = last->next_;
	last->next_->prev_ = first->prev_;
}

// range is [first, last] NOT [first, last)
template <class T, class Allocator>
inline
void
__list_deleter<T, Allocator>::insert_nodes(node_base_pointer here, node_base_pointer first, node_base_pointer last)
{
	here->prev_->next_ = (node_pointer)first;
	first->prev_ = here->prev_;
	here->prev_ = (node_pointer)last;
	last->next_ = (node_pointer)here;
}

template <class T, class Allocator>
bool
__list_deleter<T, Allocator>::invariants() const
{
	size_type s = sz();
	const node_base& t = tail();
	if (s == 0)
	{
		if (t.prev_ != t.next_)
			return false;
	}
	else
	{
		if (t.next_->prev_ != &t)
			return false;
		if (t.prev_->next_ != &t)
			return false;
		if (s != static_cast<size_type>(distance(begin(), end())))
			return false;
		size_type  c = 0;
		const_iterator b = begin();
		const_iterator e = end();
		for (; b != e; --e)
			++c;
		if (s != c)
			return false;
	}
	return true;
}

template <class T, class Allocator>
inline
__list_deleter<T, Allocator>::__list_deleter()
	: size_(size_type(0)),
	  end_(alloc())
{
	node_base& t = tail();
	t.prev_ = t.next_ = (node_pointer)&t;
}

template <class T, class Allocator>
inline
__list_deleter<T, Allocator>::__list_deleter(const allocator_type& a)
	: size_(a, 0),
	  end_(alloc())
{
	node_base& t = tail();
	t.prev_ = t.next_ = (node_pointer)&t;
}

template <class T, class Allocator>
typename __list_deleter<T, Allocator>::iterator
__list_deleter<T, Allocator>::insert(iterator position, const value_type& x)
{
	Metrowerks::alloc_ptr<node, node_allocator_type&> ap(node_alloc().allocate(1), node_alloc());
	alloc().construct(&ap->data_, x);
	node_pointer newnode = ap.release();
	insert_nodes(__iterator2pointer(position), newnode, newnode);
	++sz();
	return __pointer2iterator(newnode);
}

template <class T, class Allocator>
typename __list_deleter<T, Allocator>::iterator
__list_deleter<T, Allocator>::erase(iterator position)
{
#ifdef _MSL_DEBUG
	position.deref();
#endif
	node_pointer oldnode = __iterator2pointer(position);
#ifndef _MSL_DEBUG
	++position;
#else
	__invalidate_iterator(position++);
#endif
	remove_nodes(oldnode, oldnode);
	alloc().destroy(&oldnode->data_);
	node_alloc().deallocate(oldnode, 1);
	--sz();
	return position;
}

template <class T, class Allocator>
typename __list_deleter<T, Allocator>::iterator
__list_deleter<T, Allocator>::erase(iterator first, iterator last)
{
	if (first == last)
		return last;
	remove_nodes(__iterator2pointer(first), __iterator2pointer(last)->prev_);
	while (first != last)
	{
		alloc().destroy(&*first);
		node_pointer t = __iterator2pointer(first);
	#ifndef _MSL_DEBUG
		++first;
	#else
		__invalidate_iterator(first++);
	#endif
		node_alloc().deallocate(t, 1);
		--sz();
	}
	return last;
}

template <class T, class Allocator>
void
__list_deleter<T, Allocator>::splice(iterator position, __list_deleter& x)
{
	if (x.sz() > 0)
	{
		if (alloc() != x.alloc())
		#ifndef _MSL_NO_EXCEPTIONS
			throw runtime_error("list::splice called with unequal allocators");
		#else
			__msl_error("list::splice called with unequal allocators\n");
		#endif
		node_base& x_tail = x.tail();
		node_base_pointer s1 = x_tail.next_;
		node_base_pointer s2 = x_tail.prev_;
		x_tail.prev_ = x_tail.next_ = (node_pointer)&x_tail;
		insert_nodes(__iterator2pointer(position), s1, s2);
		sz() += x.sz();
	#ifdef _MSL_DEBUG
		if (x.template iterator_list<iterator>())
			x.template iterator_list<iterator>()->add(this, __unary_true_value<__uncheck_iterator>());
		if (x.template iterator_list<const_iterator>())
			x.template iterator_list<const_iterator>()->add(this, __unary_true_value<__uncheck_const_iterator>());
	#endif  // _MSL_DEBUG
		x.sz() = 0;
	}
}

template <class T, class Allocator>
void
__list_deleter<T, Allocator>::splice(iterator position, __list_deleter& x, iterator i)
{
#ifdef _MSL_DEBUG
	i.deref();
#endif
	if (this != &x)
	{
		if (alloc() != x.alloc())
		#ifndef _MSL_NO_EXCEPTIONS
			throw runtime_error("list::splice called with unequal allocators");
		#else
			__msl_error("list::splice called with unequal allocators\n");
		#endif
		--x.sz();
		++sz();
	#ifdef _MSL_DEBUG
		if (x.template iterator_list<iterator>())
			x.template iterator_list<iterator>()->add(this, bind2nd(equal_to<__uncheck_iterator>(), i.base()));
		if (x.template iterator_list<const_iterator>())
			x.template iterator_list<const_iterator>()->add(this, bind2nd(equal_to<__uncheck_const_iterator>(), i.base()));
	#endif  // _MSL_DEBUG
	}
	node_base_pointer p = __iterator2pointer(position);
	node_base_pointer s1 = __iterator2pointer(i);
	if (s1 == p->prev_ || s1 == p)
		return;
	remove_nodes(s1, s1);
	insert_nodes(p, s1, s1);
}

template <class T, class Allocator>
void
__list_deleter<T, Allocator>::splice(iterator position, __list_deleter& x, iterator first, iterator last)
{
	if (first == last)
		return;
	if (this != &x)
	{
		if (alloc() != x.alloc())
		#ifndef _MSL_NO_EXCEPTIONS
			throw runtime_error("list::splice called with unequal allocators");
		#else
			__msl_error("list::splice called with unequal allocators\n");
		#endif
	#ifndef _MSL_DEBUG
		size_type delta = (size_type)_STD::distance(first, last);
	#else
		size_type delta = 0;
		for (iterator i = first; i != last; ++delta)
		{
			i.deref();
			iterator j = i;
			++i;
			if (x.template iterator_list<iterator>())
				x.template iterator_list<iterator>()->add(this, bind2nd(equal_to<__uncheck_iterator>(), j.base()));
			if (x.template iterator_list<const_iterator>())
				x.template iterator_list<const_iterator>()->add(this, bind2nd(equal_to<__uncheck_const_iterator>(), j.base()));
		}
	#endif  // _MSL_DEBUG
		x.sz() -= delta;
		sz() += delta;
	}
	node_base_pointer s1 = __iterator2pointer(first);
	node_base_pointer s2 = x.__iterator2pointer(last)->prev_;
	remove_nodes(s1, s2);
	insert_nodes(__iterator2pointer(position), s1, s2);
}

template <class T, class Allocator>
void
__list_deleter<T, Allocator>::splice(iterator position, __list_deleter& x, iterator first, iterator last, size_type n)
{
	if (n == 0)
		return;
	if (this != &x)
	{
		if (alloc() != x.alloc())
			_MSL_ERROR(runtime_error, "list::splice called with unequal allocators");
	#ifdef _MSL_DEBUG
		size_type delta = 0;
		for (iterator i = first; i != last; ++delta)
		{
			i.deref();
			iterator j = i;
			++i;
			if (x.template iterator_list<iterator>())
				x.template iterator_list<iterator>()->add(this, bind2nd(equal_to<__uncheck_iterator>(), j.base()));
			if (x.template iterator_list<const_iterator>())
				x.template iterator_list<const_iterator>()->add(this, bind2nd(equal_to<__uncheck_const_iterator>(), j.base()));
		}
		if (delta != n)
			_MSL_DEBUG_ERROR(logic_error, "MSL DEBUG: list::splice, n != distance(first, last)");
	#endif  // _MSL_DEBUG
		x.sz() -= n;
		sz() += n;
	}
	node_base_pointer s1 = __iterator2pointer(first);
	node_base_pointer s2 = x.__iterator2pointer(last)->prev_;
	remove_nodes(s1, s2);
	insert_nodes(__iterator2pointer(position), s1, s2);
}

template <class T, class Allocator>
void
__list_deleter<T, Allocator>::swap(__list_deleter& x)
{
	if (this != &x)
	{
		size_.swap(x.size_);
		end_.swap(x.end_);
		node_base& t = tail();
		if (sz() > 0)
			t.next_->prev_ = t.prev_->next_ = (node_pointer)&t;
		else
			t.next_ = t.prev_ = (node_pointer)&t;
		node_base& x_t = x.tail();
		if (x.sz() > 0)
			x_t.next_->prev_ = x_t.prev_->next_ = (node_pointer)&x_t;
		else
			x_t.next_ = x_t.prev_ = (node_pointer)&x_t;
	#ifdef _MSL_DEBUG
		iterator::swap(this, &x);
		const_iterator::swap(this, &x);
	#endif  // _MSL_DEBUG
	}
}

template <class T, class Allocator>
template <class Compare>
void
__list_deleter<T, Allocator>::merge(__list_deleter& x, Compare comp)
{
	if (this == &x)
		return;
	if (alloc() != x.alloc())
	#ifndef _MSL_NO_EXCEPTIONS
		throw runtime_error("list::merge called with unequal allocators");
	#else
		__msl_error("list::merge called with unequal allocators\n");
	#endif
	iterator first1 = begin();
	iterator last1 = end();
	iterator first2 = x.begin();
	iterator last2 = x.end();
	for (; first1 != last1 && first2 != last2; ++first1)
	{
		if (comp(*first2, *first1))
		{
			iterator j = first2;
			size_t count = 1;
			for (++j; j != last2; ++j, ++count)
				if (!comp(*j, *first1))
					break;
		#ifdef _MSL_DEBUG
			for (iterator t1 = first2; t1 != j;)
			{
				iterator t2 = t1;
				++t1;
				if (x.template iterator_list<iterator>())
					x.template iterator_list<iterator>()->add(this, bind2nd(equal_to<__uncheck_iterator>(), t2.base()));
				if (x.template iterator_list<const_iterator>())
					x.template iterator_list<const_iterator>()->add(this, bind2nd(equal_to<__uncheck_const_iterator>(), t2.base()));
			}
		#endif  // _MSL_DEBUG
			node_base_pointer k = x.__iterator2pointer(j)->prev_;
			remove_nodes(__iterator2pointer(first2), k);
			insert_nodes(__iterator2pointer(first1), __iterator2pointer(first2), k);
			x.sz() -= count;
			sz() += count;
			first2 = j;
		}
	}
	if (first2 != last2)
		splice(first1, x);
}

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

template <class T, class Allocator>
void
__list_deleter<T, Allocator>::reverse()
{
	if (sz() < 2)
		return;
	node_pointer e = node_pointer(&tail());
	for (node_pointer i = tail().next_; i != e; i = i->prev_)
		_STD::swap(i->prev_, i->next_);
	_STD::swap(tail().prev_, tail().next_);
}

template <class T, class Allocator>
class __list_imp
	: private __list_deleter<T, Allocator>
{
protected:
	typedef __list_deleter<T, Allocator> base;
	template <bool b> struct chooser {};
	// types:
	typedef typename Allocator::reference         reference;
	typedef typename Allocator::const_reference   const_reference;
	typedef typename base::iterator               iterator;
	typedef typename base::const_iterator         const_iterator;
	typedef typename Allocator::size_type         size_type;
	typedef typename Allocator::difference_type   difference_type;
	typedef T                                     value_type;
	typedef Allocator                             allocator_type;
	typedef typename Allocator::pointer           pointer;
	typedef typename Allocator::const_pointer     const_pointer;

	__list_imp() {}
	explicit __list_imp(const allocator_type& a) : base(a) {}
	explicit __list_imp(size_type n)                          {init(n, value_type());}
	         __list_imp(size_type n, const value_type& value) {init(n, value);}
	         __list_imp(size_type n, const value_type& value, const allocator_type& a)
	             : base(a) {init(n, value);}
	template <class InputIterator>
		__list_imp(InputIterator first, InputIterator last, const allocator_type& a) : base(a)
			{choose_init(first, last, chooser<Metrowerks::is_integral<InputIterator>::value>());}
	template <class InputIterator>
		void choose_init(InputIterator first, InputIterator last, chooser<true>)
			{init(static_cast<size_type>(first), static_cast<value_type>(last));}
	template <class InputIterator>
		void choose_init(InputIterator first, InputIterator last, chooser<false>)
			{init(first, last);}
	__list_imp(const __list_imp& x) : base(x.alloc()) {init(x.begin(), x.end());}

	__list_imp& operator=(const __list_imp& x)
		{if (this != &x)
			do_assign(x.begin(), x.advance_to(_STD::min(size(), x.size())), x.end()); return *this;}

	template <class InputIterator>
		void choose_assign(InputIterator first, InputIterator last, chooser<true>)
			{assign(static_cast<size_type>(first), static_cast<value_type>(last));}

	template <class InputIterator>
		void choose_assign(InputIterator first, InputIterator last, chooser<false>)
			{do_assign(first, last, typename iterator_traits<InputIterator>::iterator_category());}

	void assign(size_type n, const value_type& t);

	template <class InputIterator>
		void do_assign(InputIterator first, InputIterator last, input_iterator_tag);

	template <class ForwardIterator>
		void do_assign(ForwardIterator first, ForwardIterator last, forward_iterator_tag);

	template <class RandomAccessIterator>
		void do_assign(RandomAccessIterator first, RandomAccessIterator last, random_access_iterator_tag);

	template <class ForwardIterator>
		void do_assign(ForwardIterator first, ForwardIterator f, ForwardIterator last);

	using base::alloc;
	//  allocator_type&       alloc();
	//  const allocator_type& alloc() const;

	using base::begin;
	//  iterator       begin();
	//  const_iterator begin() const;

	using base::end;
	//  iterator       end();
	//  const_iterator end() const;

	bool      empty()    const {return base::sz() == 0;}
	size_type size()     const {return base::sz();}
	size_type max_size() const {return (size_type)numeric_limits<difference_type>::max();}
	void resize(size_type sz);
	void resize(size_type sz, const value_type& value);

	using base::front;
	//  reference       front();
	//  const_reference front() const;

	using base::back;
	//  reference       back();
	//  const_reference back() const;

	void push_front(const value_type& x) {base::insert(base::begin(), x);}
	using base::pop_front;
	//  void pop_front();

	void push_back (const value_type& x) {base::insert(base::end(), x);}
	using base::pop_back;
	//  void pop_back();

	iterator insert(iterator position, const value_type& x)
		{return base::insert(position, x);}
	void insert(iterator position, size_type n, const value_type& x);

	template <class InputIterator>
		void choose_insert(iterator position, InputIterator first, InputIterator last, chooser<true>)
			{insert(position, static_cast<size_type>(first), static_cast<value_type>(last));}

	template <class InputIterator>
		void choose_insert(iterator position, InputIterator first, InputIterator last, chooser<false>);

	using base::erase;
	//  iterator erase(iterator position);
	//  iterator erase(iterator first, iterator last);

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

	void swap(__list_imp& x) {base::swap(x);}

	void splice(iterator position, __list_imp& x)                                {base::splice(position, x);}
	void splice(iterator position, __list_imp& x, iterator i)                    {base::splice(position, x, i);}
	void splice(iterator position, __list_imp& x, iterator first, iterator last) {base::splice(position, x, first, last);}
	void splice(iterator position, __list_imp& x, iterator first, iterator last, size_type n)
		{base::splice(position, x, first, last, n);}

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

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

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

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

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

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

	using base::invariants;
	// bool invariants() const;
private:
	iterator       advance_to(size_type p);
	const_iterator advance_to(size_type p) const {return const_cast<__list_imp&>(*this).advance_to(p);}
};

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

template <class T, class Allocator>
template <class InputIterator>
void
__list_imp<T, Allocator>::init(InputIterator first, InputIterator last)
{
	for (; first != last; ++first)
		push_back(*first);
}

template <class T, class Allocator>
typename __list_imp<T, Allocator>::iterator
__list_imp<T, Allocator>::advance_to(size_type p)
{
	size_type sz = size();
	iterator i;
	if (p <= sz/2)
	{
		i = base::begin();
		_STD::advance(i, difference_type(p));
	}
	else
	{
		i = base::end();
		_STD::advance(i, difference_type(p - sz));
	}
	return i;
}

template <class T, class Allocator>
void
__list_imp<T, Allocator>::assign(size_type n, const value_type& t)
{
	size_type sz = size();
	iterator i = base::begin();
	iterator e = base::end();
	if (n > sz)
	{
		__list_imp temp(n - sz, t, base::alloc());
		for (; i != e; ++i)
			*i = t;
		splice(i, temp);
	}
	else
	{
		for (; n != 0; --n, ++i)
			*i = t;
		base::erase(i, e);
	}
}

template <class T, class Allocator>
template <class InputIterator>
void
__list_imp<T, Allocator>::do_assign(InputIterator first, InputIterator last, input_iterator_tag)
{
	iterator i = base::begin();
	iterator e = base::end();
	for (; first != last && i != e; ++first, ++i)
		*i = *first;
	if (i == e)
		choose_insert(i, first, last, chooser<false>());
	else
		base::erase(i, e);
}

template <class T, class Allocator>
template <class ForwardIterator>
void
__list_imp<T, Allocator>::do_assign(ForwardIterator first, ForwardIterator f, ForwardIterator last)
{
	if (f != last)
	{
		__list_imp temp(f, last, base::alloc());
		splice(_STD::copy(first, f, base::begin()), temp);
	}
	else
		base::erase(_STD::copy(first, f, base::begin()), base::end());
}

template <class T, class Allocator>
template <class ForwardIterator>
void
__list_imp<T, Allocator>::do_assign(ForwardIterator first, ForwardIterator last, forward_iterator_tag)
{
	ForwardIterator f = first;
	for (size_type c = size(); c != 0 && f != last; --c)
		++f;
	do_assign(first, f, last);
}

template <class T, class Allocator>
template <class RandomAccessIterator>
inline
void
__list_imp<T, Allocator>::do_assign(RandomAccessIterator first, RandomAccessIterator last, random_access_iterator_tag)
{
	typedef typename iterator_traits<RandomAccessIterator>::difference_type difference_type;
	do_assign(first, first + _STD::min(difference_type(size()), last - first), last);
}

template <class T, class Allocator>
void
__list_imp<T, Allocator>::insert(iterator position, size_type n, const value_type& x)
{
	__list_imp temp(n, x, base::alloc());
	splice(position, temp);
}

template <class T, class Allocator>
template <class InputIterator>
void
__list_imp<T, Allocator>::choose_insert(iterator position, InputIterator first, InputIterator last, chooser<false>)
{
	__list_imp temp(first, last, base::alloc());
	splice(position, temp);
}

template <class T, class Allocator>
void
__list_imp<T, Allocator>::resize(size_type sz)
{
	size_type cs = size();
	if (sz > cs)
		insert(base::end(), sz-cs, value_type());
	else if (sz < cs)
		base::erase(advance_to(sz), base::end());
}

template <class T, class Allocator>
void
__list_imp<T, Allocator>::resize(size_type sz, const value_type& value)
{
	size_type cs = size();
	if (sz > cs)
		insert(base::end(), sz-cs, value);
	else if (sz < cs)
		base::erase(advance_to(sz), base::end());
}

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

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

template <class T, class Allocator = allocator<T> >
class list
	: private __list_imp<T, Allocator>
{
	typedef __list_imp<T, Allocator> base;
public:
	//  types:
	typedef typename Allocator::reference          reference;
	typedef typename Allocator::const_reference    const_reference;
	typedef typename base::iterator                iterator;
	typedef typename base::const_iterator          const_iterator;
	typedef typename Allocator::size_type          size_type;
	typedef typename Allocator::difference_type    difference_type;
	typedef T                                      value_type;
	typedef Allocator                              allocator_type;
	typedef typename Allocator::pointer            pointer;
	typedef typename Allocator::const_pointer      const_pointer;
	typedef _STD::reverse_iterator<iterator>       reverse_iterator;
	typedef _STD::reverse_iterator<const_iterator> const_reverse_iterator;

	//  lib.list.cons construct/copy/destroy:
	         list() {}
	explicit list(const allocator_type& a) : base(a) {}
	explicit list(size_type n) : base(n) {}
	         list(size_type n, const value_type& value) : base(n, value) {}
	         list(size_type n, const value_type& value, const allocator_type& a) : base(n, value, a) {}
	template <class InputIterator>
		list(InputIterator first, InputIterator last)
			{base::choose_init(first, last, typename base::chooser<Metrowerks::is_integral<InputIterator>::value>());}
	template <class InputIterator>
		list(InputIterator first, InputIterator last, const allocator_type& a) : base(a)
			{base::choose_init(first, last, typename base::chooser<Metrowerks::is_integral<InputIterator>::value>());}

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

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

	using base::begin;
	//  iterator       begin();
	//  const_iterator begin() const;
	using base::end;
	//  iterator       end();
	//  const_iterator end() const;

	reverse_iterator       rbegin()       {return       reverse_iterator(base::end());}
	const_reverse_iterator rbegin() const {return const_reverse_iterator(base::end());}
	reverse_iterator       rend()         {return       reverse_iterator(base::begin());}
	const_reverse_iterator rend()   const {return const_reverse_iterator(base::begin());}

	using base::empty;
	//  bool      empty()    const;
	using base::size;
	//  size_type size() const;
	using base::max_size;
	//  size_type max_size() const;
	using base::resize;
	//  void resize(size_type sz);
	//  void resize(size_type sz, const value_type& value);

	using base::front;
	//  reference       front();
	//  const_reference front() const;
	using base::back;
	//  reference       back();
	//  const_reference back() const;

	iterator insert(iterator position, const value_type& x)
		{return base::insert(position, x);}
	void insert(iterator position, size_type n, const value_type& x)
		{base::insert(position, n, x);}
	template <class InputIterator>
		void insert(iterator position, InputIterator first, InputIterator last)
			{base::choose_insert(position, first, last, typename base::chooser<Metrowerks::is_integral<InputIterator>::value>());}

	using base::push_front;
	//  void push_front(const value_type& x);
	using base::push_back;
	//  void push_back (const value_type& x);
	using base::pop_front;
	//  void pop_front();
	using base::pop_back;
	//  void pop_back();

	using base::erase;
	//  iterator erase(iterator position);
	//  iterator erase(iterator first, iterator last);

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

	void swap(list& x) {base::swap(x);}

	void splice(iterator position, list& x)                                {base::splice(position, x);}
	void splice(iterator position, list& x, iterator i)                    {base::splice(position, x, i);}
	void splice(iterator position, list& x, iterator first, iterator last) {base::splice(position, x, first, last);}
	void splice(iterator position, list& x, iterator first, iterator last, size_type n)
		{base::splice(position, x, first, last, n);}

	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(list& x)                   {base::merge(x, less<value_type>());}
	template <class Compare>
		void merge(list& x, Compare comp) {base::template merge<Compare>(x, comp);}

//	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;
	//  bool invariants() const;
};

#ifndef _Inhibit_Container_Optimization

template <class T, class Allocator>
class list<T*, Allocator>
	: private __list_imp<const void*, typename Allocator::rebind<const void*>::other>
{
	typedef __list_imp<const void*, typename Allocator::rebind<const void*>::other> base;
public:
	//  types:
	typedef Allocator                              allocator_type;
	typedef typename Allocator::reference          reference;
	typedef typename Allocator::const_reference    const_reference;
	typedef typename Allocator::size_type          size_type;
	typedef typename Allocator::difference_type    difference_type;
	typedef T*                                     value_type;
	typedef typename Allocator::pointer            pointer;
	typedef typename Allocator::const_pointer      const_pointer;

	template <bool is_const>
	class generic_iterator
	{
	public:
		typedef typename list::value_type value_type;
		typedef typename list::difference_type  difference_type;
		typedef typename Metrowerks::select<is_const, typename list::const_pointer,
		                                              typename list::pointer>::type pointer;
		typedef typename Metrowerks::select<is_const, typename list::const_reference,
		                                              typename list::reference>::type reference;
		typedef bidirectional_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_.operator->());}
		generic_iterator& operator ++ () {++i_; return *this;}
		generic_iterator operator ++ (int) {generic_iterator tmp(*this); ++i_; return tmp;}
		generic_iterator& operator -- () {--i_; return *this;}
		generic_iterator operator -- (int) {generic_iterator tmp(*this); --i_; 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_;}
	#ifdef _MSL_DEBUG
		bool is_invalidated() const {return i_.is_invalidated();}
	#endif
	private:
		typedef typename Metrowerks::select<is_const, typename base::const_iterator,
		                                              typename base::iterator>::type base_iterator;

		friend class generic_iterator<true>;
		friend class list;

		base_iterator i_;

		generic_iterator(base_iterator i) : i_(i) {}
		operator base_iterator() const {return i_;}
	};

	typedef generic_iterator<false>                iterator;
	typedef generic_iterator<true>                 const_iterator;
	typedef _STD::reverse_iterator<iterator>       reverse_iterator;
	typedef _STD::reverse_iterator<const_iterator> const_reverse_iterator;

	         list() {}
	explicit list(const allocator_type& a) : base(a) {}
	explicit list(size_type n) : base(n) {}
	         list(size_type n, const value_type& value) : base(n, (const void*)value) {}
	         list(size_type n, const value_type& value, const allocator_type& a) : base(n, (const void*)value, a) {}
	template <class InputIterator>
		list(InputIterator first, InputIterator last)
			{choose_init(first, last, typename base::chooser<Metrowerks::is_integral<InputIterator>::value>());}
	template <class InputIterator>
		list(InputIterator first, InputIterator last, const allocator_type& a) : base(a)
			{choose_init(first, last, typename base::chooser<Metrowerks::is_integral<InputIterator>::value>());}

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

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

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

	reverse_iterator       rbegin()       {return       reverse_iterator(base::end());}
	const_reverse_iterator rbegin() const {return const_reverse_iterator(base::end());}
	reverse_iterator       rend()         {return       reverse_iterator(base::begin());}
	const_reverse_iterator rend()   const {return const_reverse_iterator(base::begin());}

	using base::empty;
	//  bool      empty()    const;
	using base::size;
	//  size_type size() const;
	using base::max_size;
	//  size_type max_size() const;
	void resize(size_type sz)                          {base::resize(sz);}
	void resize(size_type sz, const value_type& value) {base::resize(sz, (const void*)value);}

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

	iterator insert(iterator position, const value_type& x)       {return base::insert(position, (const void*)x);}
	void     insert(iterator position, size_type n, const value_type& x) {base::insert(position, n, (const void*)x);}
	template <class InputIterator>
		void insert(iterator position, InputIterator first, InputIterator last)
			{choose_insert(position, first, last, typename base::chooser<Metrowerks::is_integral<InputIterator>::value>());}

	void push_front(const value_type& x) {base::push_front((const void*)x);}
	void push_back (const value_type& x) {base::push_back((const void*)x);}
	using base::pop_front;
	//  void pop_front();
	using base::pop_back;
	//  void pop_back();

	iterator erase(iterator position)             {return base::erase(position);}
	iterator erase(iterator first, iterator last) {return base::erase(first, last);}

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

	void swap(list& x) {base::swap(x);}

	void splice(iterator position, list& x)                                {base::splice(position, x);}
	void splice(iterator position, list& x, iterator i)                    {base::splice(position, x, i);}
	void splice(iterator position, list& x, iterator first, iterator last) {base::splice(position, x, first, last);}
	void splice(iterator position, list& x, iterator first, iterator last, size_type n)
		{base::splice(position, x, first, last, n);}

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

	using base::invariants;
	// bool invariants() const;
private:
	template <class Compare>
	class unary_convert
	{
	public:
		unary_convert(Compare comp) : comp_(comp) {}
		bool operator() (const void* x) {return comp_((T*)x);}
	private:
		Compare comp_;
	};

	template <class Compare>
	class binary_convert
	{
	public:
		binary_convert(Compare comp) : comp_(comp) {}
		bool operator() (const void* x, const void* y) {return comp_((T*)x, (T*)y);}
	private:
		Compare comp_;
	};

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

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

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

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

private:

	template <class InputIterator>
		void choose_init(InputIterator first, InputIterator last, typename base::chooser<true>)
			{base::init(static_cast<size_type>(first), (value_type)last);}
	template <class InputIterator>
		void choose_init(InputIterator first, InputIterator last, typename base::chooser<false>)
			{
			typedef __convert_iterator<__implicit_convert<pointer, InputIterator> > first_convert;
			typedef __convert_iterator<__reinterpret_convert<const void**, first_convert> > second_convert;
			base::init(second_convert(first_convert(first)),
			           second_convert(first_convert(last)));
			}

	template <class InputIterator>
		void choose_assign(InputIterator first, InputIterator last, typename base::chooser<true>)
			{base::assign(static_cast<size_type>(first), (value_type)last);}
	template <class InputIterator>
		void choose_assign(InputIterator first, InputIterator last, typename base::chooser<false> c)
			{
			typedef __convert_iterator<__implicit_convert<pointer, InputIterator> > first_convert;
			typedef __convert_iterator<__reinterpret_convert<const void**, first_convert> > second_convert;
			base::choose_assign(second_convert(first_convert(first)),
			                    second_convert(first_convert(last)), c);
			}

	template <class InputIterator>
		void choose_insert(iterator position, InputIterator first, InputIterator last, typename base::chooser<true>)
			{base::insert(position, static_cast<size_type>(first), (value_type)last);}
	template <class InputIterator>
		void choose_insert(iterator position, InputIterator first, InputIterator last, typename base::chooser<false> c)
			{
			typedef __convert_iterator<__implicit_convert<pointer, InputIterator> > first_convert;
			typedef __convert_iterator<__reinterpret_convert<const void**, first_convert> > second_convert;
			base::choose_insert(position,
				second_convert(first_convert(first)),
				second_convert(first_convert(last)), c);
			}
};

#endif  // _Inhibit_Container_Optimization

template <class T, class Allocator>
inline
bool
operator==(const list<T, Allocator>& x, const list<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 list<T, Allocator>& x, const list<T, Allocator>& y)
{
	return !(x == y);
}

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

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

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

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

// specialized algorithms:

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

#ifndef _MSL_NO_CPP_NAMESPACE
	} // namespace std
#endif

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

#ifndef _MSL_DEBUG

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

#endif  // _MSL_DEBUG

template<class T, class Allocator>
struct move_with_swap<_STD::list<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<_STD::list<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 // _LIST

// hh 971220 fixed MOD_INCLUDE
// hh 971222 added alignment wrapper
// hh 971222 Changed filename from list.h to list
// hh 971222 Made include guards standard
// hh 971222 Added qualified name to const_iterator and iterator in several places
// hh 971230 added RC_INVOKED wrapper
// hh 980105 changed pointer & reference to const versions in const_iterator base class
// hh 980106 rewrote iterator and const_iterator constructors to silence unused arg warning
// hh 980111 <stdexcept> commented out.  Not needed.
// hh 980713 Temporarily moved member templates into class definition to support compiler
// hh 980902 #ifdef'd out exception code when ndef MSIPL_EXCEPT
// hh 981120 Rewrote
// hh 981208 Protected swap with if (this == &x)
// hh 981208 changed static_cast to reinterpret_cast on the value_type (pointer specialization only)
// hh 981220 Added typename to appropriate return types
// hh 981220 Modifed some method signitures to simplified syntax
// hh 981220 Added typename to appropriate return types
// hh 981221 changed static_cast to reinterpret_cast on the value_type (pointer specialization only)
// hh 990120 changed name of MSIPL flags
// hh 990218 Fixed bug in swap when one of the lists is empty
// hh 990521 Rewrote do_assign for input iterators to be more conservative with memory
// hh 990720 Made iterator comparison functions global friends
// hh 990825 changed void* to const void*
// hh 990826 Seperated out calls involving T()
// hh 991116 Fixed pointer conversion bug in T* specialization by introducing __convert_iterator
// 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 010314 Qualified internal calls with std::
// hh 010402 Removed 68K CMF support
// hh 010525 Rewrote (again)
// hh 010821 Put casts back on allocators for 2.3 old_argmatch compatibility
// hh 011120 Installed _MSL_DEBUG
// hh 020529 Changed <limits> to <msl_int_limits>
// hh 030212 Added empty check for pop_front and pop_back under _MSL_DEBUG
// hh 030527 Made pseudo movable
// hh 030711 Worked around friend class T problem
// hh 030715 Added splice extension
// hh 031101 Removed some extraneous typenames
// hh 031228 Simplified sort with new splice signature
// hh 030104 Fixed up for function pointers
