/*  Metrowerks Standard Library  Version 4.0  1998 August 10  */

/*  $Date: 1998/12/11 19:09:08 $ 
 *  $Revision: 1.3 $ 
 *  $NoKeywords: $ 
 *
 *		Portions Copyright  1995-1998 Metrowerks, Inc.
 *		All rights reserved.
 */

/**
 **  list
 **/

#ifndef _LIST
#define _LIST
 
#include <mcompile.h>
#include <memory>
#include <limits>
#include <stdexcept>
#include <iterator>
#include <algorithm>
#include <string>

#ifndef RC_INVOKED

#pragma options align=native
#if defined(__CFM68K__) && !defined(__USING_STATIC_LIBS__)
	#pragma import on
#endif

#ifdef MSIPL_USING_NAMESPACE
	namespace std {
#endif

template <class T, class Allocator = allocator<T> >
class list
{
	#ifdef MSIPL_MEMBER_TEMPLATE
		template <bool b> struct chooser {};
	#endif
public:
	//  types:
	typedef typename Allocator::reference         reference;
	typedef typename Allocator::const_reference   const_reference;
	class                                         iterator;
	class                                         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;

private:

	struct node;

	struct node_base
	{
		node* prev_;
		node* next_;
	};

	struct node
		: public node_base
	{
		value_type data_;
	};

	typedef ALLOC_BIND (node)                     node_allocator_type;

public:

	class iterator
		: public _STD::iterator<bidirectional_iterator_tag, T, difference_type, pointer, reference>
	{
	public:
		iterator() {}
		reference operator * () const {return node_->data_;}
		pointer operator -> () const {return &node_->data_;}
		iterator& operator ++ () {node_ = node_->next_; return *this;}
		iterator operator ++ (int) {iterator tmp(*this); node_ = node_->next_; return tmp;}
		iterator& operator -- () {node_ = node_->prev_; return *this;}
		iterator operator -- (int) {iterator tmp(*this); node_ = node_->prev_; return tmp;}
		bool operator ==(const iterator& rhs) const {return node_ == rhs.node_;}
		bool operator !=(const iterator& rhs) const {return node_ != rhs.node_;}
	private:
		node* node_;

		iterator(node* node) : node_(node) {}

		friend class list;
		friend class list::const_iterator;
	};

	class const_iterator
		: public _STD::iterator<bidirectional_iterator_tag, T, difference_type, const_pointer, const_reference>
	{
	public:
		const_iterator() {}
		const_iterator(const list::iterator& x) : node_(x.node_) {}
		const_reference operator * () const {return node_->data_;}
		const_pointer operator -> () const {return &node_->data_;}
		const_iterator& operator ++ () {node_ = node_->next_; return *this;}
		const_iterator operator ++ (int) {const_iterator tmp(*this); node_ = node_->next_; return tmp;}
		const_iterator& operator -- () {node_ = node_->prev_; return *this;}
		const_iterator operator -- (int) {const_iterator tmp(*this); node_ = node_->prev_; return tmp;}
		bool operator ==(const const_iterator& rhs) const {return node_ == rhs.node_;}
		bool operator !=(const const_iterator& rhs) const {return node_ != rhs.node_;}
	private:
		const node* node_;

		const_iterator(const node* node) : node_(node) {}

		friend class list;
	};

	//  lib.list.cons construct/copy/destroy:
	explicit list(const Allocator& = Allocator());
	explicit list(size_type n, const T& value = T(), const Allocator& = Allocator());
	#ifdef MSIPL_MEMBER_TEMPLATE
		template <class InputIterator>
			list(InputIterator first, InputIterator last, const Allocator& a = Allocator())
				: alloc_(a, 0),
				  node_alloc_(node_allocator_type(a))
			{
				node_base& tail = node_alloc_.m_;
				tail.prev_ = tail.next_ = (node*)&tail;
				choose_init(first, last, chooser<numeric_limits<InputIterator>::is_integer>());
			}
	#else
		list(const_iterator first, const_iterator last, const Allocator& a = Allocator());
	#endif
	list(const list<T,Allocator>& x);
	~list();
	list<T,Allocator>& operator=(const list<T,Allocator>& x);
	#ifdef MSIPL_MEMBER_TEMPLATE
		template <class InputIterator>
			inline
			void assign(InputIterator first, InputIterator last)
			{
				choose_assign(first, last, chooser<numeric_limits<InputIterator>::is_integer>());
			}
	#else
		void assign(const_iterator first, const_iterator last);
	#endif
	void assign(size_type n, const T& t);
	allocator_type get_allocator() const;

	//  iterators:
	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;

	//  lib.list.capacity capacity:
	bool      empty() const;
	size_type size() const;
	size_type max_size() const;
	void      resize(size_type sz, T c = T());

	//  element access:
	reference       front();
	const_reference front() const;
	reference       back();
	const_reference back() const;

	//  lib.list.modifiers modifiers:
	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);
	#ifdef MSIPL_MEMBER_TEMPLATE
		template <class InputIterator>
			void insert(iterator position, InputIterator first, InputIterator last)
			{
				list temp(first, last, alloc_);
				splice(position, temp);
			}
	#else
		void insert(iterator position, const_iterator first, const_iterator last);
	#endif

	iterator erase(iterator position);
	iterator erase(iterator position, iterator last);
	void     swap(list<T,Allocator>& x);
	void     clear();

	//  lib.list.ops list operations:
	void splice(iterator position, list<T,Allocator>& x);
	void splice(iterator position, list<T,Allocator>& x, iterator i);
	void splice(iterator position, list<T,Allocator>& x, iterator first, iterator last);

	void remove(const T& value);
	#ifdef MSIPL_MEMBER_TEMPLATE
		template <class Predicate>
			void remove_if(Predicate pred)
			{
				iterator e = end();
				for (iterator i = begin(); i != e; ++i)
				{
					if (pred(*i))
					{
						iterator j = i;
						for (++j; j != e; ++j)
							if (!pred(*j))
								break;
						i = erase(i, j);
						if (i == e)
							break;
					}
				}
			}
	#endif

	void unique();
	#ifdef MSIPL_MEMBER_TEMPLATE
		template <class BinaryPredicate>
			void unique(BinaryPredicate binary_pred)
			{
				iterator e = end();
				for (iterator i = begin(); i != e;)
				{
					iterator j = i;
					for (++j; j != e; ++j)
						if (!binary_pred(*i, *j))
							break;
					++i;
					if (i != j)
						i = erase(i, j);
				}
			}
	#endif

	void merge(list<T,Allocator>& x);
	#ifdef MSIPL_MEMBER_TEMPLATE
		template <class Compare>
			void merge(list<T,Allocator>& x, Compare comp)
			{
				if (this == &x)
					return;
				if (size() > max_size() - x.size())
					#ifdef MSIPL_EXCEPT
						throw length_error("list::merge length error");
					#else
					{
						fprintf(stderr, "list::merge length error\n");
						abort();
					}
					#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;
						node_base* k = j.node_->prev_;
						remove_nodes(first2.node_, k);
						insert_nodes(first1.node_, first2.node_, k);
						x.alloc_.m_ -= count;
						alloc_.m_ += count;
						first2 = j;
					}
				}
				if (first2 != last2)
					splice(first1, x);
			}
	#endif

	void sort();
	#ifdef MSIPL_MEMBER_TEMPLATE
		template <class Compare>
			void sort(Compare comp)
			{
				switch (size())
				{
				case 0:
				case 1:
					break;
				case 2:
				{
					iterator i = begin();
					iterator j = i;
					++j;
					if (comp(*j, *i))
					{	// reverse()
						_STD::swap(i.node_->prev_, i.node_->next_);
						_STD::swap(j.node_->prev_, j.node_->next_);
						_STD::swap(node_alloc_.m_.prev_, node_alloc_.m_.next_);
					}
				}
					break;
				default:
				{
					iterator i = begin();
					size_type lower_size = size() / 2;
					advance(i, lower_size);
					list upper_half;
					// upper_half.splice(upper_half.begin(), *this, i, end());
					node_base* s1 = i.node_;
					node_base* s2 = node_alloc_.m_.prev_;
					remove_nodes(s1, s2);
					insert_nodes(&upper_half.node_alloc_.m_, s1, s2);
					upper_half.alloc_.m_ = alloc_.m_ - lower_size;
					alloc_.m_ = lower_size;
					sort(comp);
					upper_half.sort(comp);
					merge(upper_half, comp);
					break;
				}
				}
			}
	#endif

	void reverse();
private:
	_EmptyMemberOpt<Allocator, size_type> alloc_;  // alloc_.m_ is size_
	_EmptyMemberOpt<node_allocator_type, node_base> node_alloc_;  // node_alloc_.m_ is tail pseudo node
	                                                              // node_alloc_.m_.next_ is first node
	                                                              // node_alloc_.m_.prev_ is last node

	#ifdef MSIPL_MEMBER_TEMPLATE
		template <class InputIterator>
			void
			choose_init(InputIterator first, InputIterator last, chooser<true>)
			{
				size_type n = static_cast<size_type>(first);
				if (n > max_size())
					#ifdef MSIPL_EXCEPT
						throw length_error("list::construction length error");
					#else
					{
						fprintf(stderr, "list::construction length error\n");
						abort();
					}
					#endif
				#ifdef MSIPL_EXCEPT
				try
				{
				#endif
					for (; n > 0; --n)
						push_back(static_cast<value_type>(last));
				#ifdef MSIPL_EXCEPT
				}
				catch (...)
				{
					clear();
					throw;
				}
				#endif
			}

		template <class InputIterator>
			void
			choose_init(InputIterator first, InputIterator last, chooser<false>)
			{
				#ifdef MSIPL_EXCEPT
				try
				{
				#endif
					for (; first != last; ++first)
						push_back(*first);
				#ifdef MSIPL_EXCEPT
				}
				catch (...)
				{
					clear();
					throw;
				}
				#endif
			}

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

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

		template <class InputIterator>
			void
			do_assign(InputIterator first, InputIterator last, input_iterator_tag)
			{
				list temp(first, last, alloc_);
				clear();
				splice(begin(), temp);
			}

		template <class ForwardIterator>
			void
			do_assign(ForwardIterator first, ForwardIterator last, forward_iterator_tag)
			{
				ForwardIterator f = first;
				for (size_type c = size(); c != 0 && f != last; --c)
					++f;
				list temp(f, last, alloc_);
				if (size() > max_size() - temp.size())
					#ifdef MSIPL_EXCEPT
						throw length_error("list::assign length error");
					#else
					{
						fprintf(stderr, "list::assign length error\n");
						abort();
					}
					#endif
				iterator i = copy(first, f, begin());
				if (temp.size() > 0)
					splice(i, temp);
				else
					erase(i, end());
			}

		template <class RandomAccessIterator>
			void
			do_assign(RandomAccessIterator first, RandomAccessIterator last, random_access_iterator_tag)
			{
				RandomAccessIterator f = first + min(size(), size_type(last - first));
				if (last - first > max_size())
					#ifdef MSIPL_EXCEPT
						throw length_error("list::assign length error");
					#else
					{
						fprintf(stderr, "list::assign length error\n");
						abort();
					}
					#endif
				list temp(f, last, alloc_);
				iterator i = copy(first, f, begin());
				if (temp.size() > 0)
					splice(i, temp);
				else
					erase(i, end());
			}

	#endif
	static void remove_nodes(node_base* first, node_base* last);
	static void insert_nodes(node_base* here, node_base* first, node_base* last);

};

template <class T, class Allocator>
bool
operator==(const list<T,Allocator>& x, const list<T,Allocator>& y);

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

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

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

template <class T, class Allocator>
bool
operator>=(const list<T,Allocator>& x, const list<T,Allocator>& y);

template <class T, class Allocator>
bool
operator<=(const list<T,Allocator>& x, const list<T,Allocator>& y);

// specialized algorithms:

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

// Implementation list

template <class T, class Allocator>
list<T, Allocator>::list(const Allocator& a)
	: alloc_(a, 0)
#ifdef MSIPL_MEMBER_TEMPLATE
	, node_alloc_(node_allocator_type(a))
#endif
{
	node_base& tail = node_alloc_.m_;
	tail.prev_ = tail.next_ = (node*)&tail;
}

template <class T, class Allocator>
list<T, Allocator>::list(size_type n, const value_type& value, const Allocator& a)
	: alloc_(a, 0)
#ifdef MSIPL_MEMBER_TEMPLATE
	, node_alloc_(node_allocator_type(a))
#endif
{
	if (n > max_size())
		#ifdef MSIPL_EXCEPT
			throw length_error("list::construction length error");
		#else
		{
			fprintf(stderr, "list::construction length error\n");
			abort();
		}
		#endif
	node_base& tail = node_alloc_.m_;
	tail.prev_ = tail.next_ = (node*)&tail;
	#ifdef MSIPL_EXCEPT
	try
	{
	#endif
		for (; n > 0; --n)
			push_back(value);
	#ifdef MSIPL_EXCEPT
	}
	catch (...)
	{
		clear();
		throw;
	}
	#endif
}

#ifndef MSIPL_MEMBER_TEMPLATE

	template <class T, class Allocator>
	list<T, Allocator>::list(const_iterator first, const_iterator last, const Allocator& a)
		: alloc_(a, 0)
	{
		node_base& tail = node_alloc_.m_;
		tail.prev_ = tail.next_ = (node*)&tail;
		#ifdef MSIPL_EXCEPT
		try
		{
		#endif
			for (; first != last; ++first)
				push_back(*first);
		#ifdef MSIPL_EXCEPT
		}
		catch (...)
		{
			clear();
			throw;
		}
		#endif
	}

#endif

template <class T, class Allocator>
list<T, Allocator>::list(const list<T,Allocator>& x)
	: alloc_(x.alloc_, 0),
	  node_alloc_(x.node_alloc_)
{
	node_base& tail = node_alloc_.m_;
	tail.prev_ = tail.next_ = (node*)&tail;
	const_iterator e = x.end();
	#ifdef MSIPL_EXCEPT
	try
	{
	#endif
		for (const_iterator i = x.begin(); i != e; ++i)
			push_back(*i);
	#ifdef MSIPL_EXCEPT
	}
	catch (...)
	{
		clear();
		throw;
	}
	#endif
}

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

template <class T, class Allocator>
inline
list<T, Allocator>&
list<T, Allocator>::operator=(const list<T, Allocator>& x)
{
	if (this != &x)
		assign(x.begin(), x.end());
	return *this;
}

#ifndef MSIPL_MEMBER_TEMPLATE

	template <class T, class Allocator>
	void
	list<T, Allocator>::assign(const_iterator first, const_iterator last)
	{
		const_iterator f = first;
		for (size_type c = size(); c != 0 && f != last; --c)
			++f;
		list temp(f, last, alloc_);
		if (size() > max_size() - temp.size())
			#ifdef MSIPL_EXCEPT
				throw length_error("list::assign length error");
			#else
			{
				fprintf(stderr, "list::assign length error\n");
				abort();
			}
			#endif
		iterator i = copy(first, f, begin());
		if (temp.size() > 0)
			splice(i, temp);
		else
			erase(i, end());
	}

#endif

template <class T, class Allocator>
void
list<T, Allocator>::assign(size_type n, const T& t)
{
	if (n > max_size())
		#ifdef MSIPL_EXCEPT
			throw length_error("list::assign length error");
		#else
		{
			fprintf(stderr, "list::assign length error\n");
			abort();
		}
		#endif
	if (n > size())
	{
		list temp(n - size(), t, alloc_);
		iterator i;
		for (i = begin(); i != end(); ++i)
			*i = t;
		splice(i, temp);
	}
	else
	{
		iterator i;
		for (i = begin(); n != 0; --n, ++i)
			*i = t;
		erase(i, end());
	}
}

template <class T, class Allocator>
inline
list<T, Allocator>::allocator_type
list<T, Allocator>::get_allocator() const
{
	return alloc_;
}

template <class T, class Allocator>
inline
list<T, Allocator>::iterator
list<T, Allocator>::begin()
{
	return iterator(node_alloc_.m_.next_);
}

template <class T, class Allocator>
inline
list<T, Allocator>::const_iterator
list<T, Allocator>::begin() const
{
	return const_iterator(node_alloc_.m_.next_);
}

template <class T, class Allocator>
inline
list<T, Allocator>::iterator
list<T, Allocator>::end()
{
	return iterator((node*)&node_alloc_.m_);
}

template <class T, class Allocator>
inline
list<T, Allocator>::const_iterator
list<T, Allocator>::end() const
{
	return const_iterator((node*)&node_alloc_.m_);
}

template <class T, class Allocator>
inline
list<T, Allocator>::reverse_iterator
list<T, Allocator>::rbegin()
{
	return reverse_iterator(end());
}

template <class T, class Allocator>
inline
list<T, Allocator>::const_reverse_iterator
list<T, Allocator>::rbegin() const
{
	return const_reverse_iterator(end());
}

template <class T, class Allocator>
inline
list<T, Allocator>::reverse_iterator
list<T, Allocator>::rend()
{
	return reverse_iterator(begin());
}

template <class T, class Allocator>
inline
list<T, Allocator>::const_reverse_iterator
list<T, Allocator>::rend() const
{
	return const_reverse_iterator(begin());
}

template <class T, class Allocator>
inline
bool
list<T, Allocator>::empty() const
{
	return alloc_.m_ == 0;
}

template <class T, class Allocator>
inline
list<T, Allocator>::size_type
list<T, Allocator>::size() const
{
	return alloc_.m_;
}

template <class T, class Allocator>
inline
list<T, Allocator>::size_type
list<T, Allocator>::max_size() const
{
	return (size_type)numeric_limits<difference_type>::max();
}

template <class T, class Allocator>
void
list<T, Allocator>::resize(size_type sz, T c)
{
	if (sz > size())
		insert(end(), sz-size(), c);
	else if (sz < size())
	{
		iterator i;
		if (sz < size() / 2)
		{
			i = begin();
			advance(i, sz);
		}
		else
		{
			i = end();
			advance(i, difference_type(sz - size()));
		}
		erase(i, end());
	}
}

template <class T, class Allocator>
inline
list<T, Allocator>::reference
list<T, Allocator>::front()
{
	return node_alloc_.m_.next_->data_;
}

template <class T, class Allocator>
inline
list<T, Allocator>::const_reference
list<T, Allocator>::front() const
{
	return node_alloc_.m_.next_->data_;
}

template <class T, class Allocator>
inline
list<T, Allocator>::reference
list<T, Allocator>::back()
{
	return node_alloc_.m_.prev_->data_;
}

template <class T, class Allocator>
inline
list<T, Allocator>::const_reference
list<T, Allocator>::back() const
{
	return node_alloc_.m_.prev_->data_;
}

template <class T, class Allocator>
inline
void
list<T, Allocator>::push_front(const T& x)
{
	insert(begin(), x);
}

template <class T, class Allocator>
inline
void
list<T, Allocator>::pop_front()
{
	erase(begin());
}

template <class T, class Allocator>
inline
void
list<T, Allocator>::push_back(const T& x)
{
	insert(end(), x);
}

template <class T, class Allocator>
inline
void
list<T, Allocator>::pop_back()
{
	erase(node_alloc_.m_.prev_);
}

template <class T, class Allocator>
list<T, Allocator>::iterator
list<T, Allocator>::insert(iterator position, const T& x)
{
	if (size() > max_size() - 1)
		#ifdef MSIPL_EXCEPT
			throw length_error("list::insert length error");
		#else
		{
			fprintf(stderr, "list::insert length error\n");
			abort();
		}
		#endif
	node* newnode = node_alloc_.allocate(1);
	#ifdef MSIPL_EXCEPT
	try
	{
	#endif
		alloc_.construct(&newnode->data_, x);
	#ifdef MSIPL_EXCEPT
	}
	catch (...)
	{
		node_alloc_.deallocate(newnode, 1);
		throw;
	}
	#endif
	insert_nodes(position.node_, newnode, newnode);
	++alloc_.m_;
	return newnode;
}

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

#ifndef MSIPL_MEMBER_TEMPLATE

	template <class T, class Allocator>
	void
	list<T, Allocator>::insert(iterator position, const_iterator first, const_iterator last)
	{
		list temp(first, last, alloc_);
		splice(position, temp);
	}

#endif

template <class T, class Allocator>
list<T, Allocator>::iterator
list<T, Allocator>::erase(iterator position)
{
	node* oldnode = position.node_;
	node* result = oldnode->next_;
	remove_nodes(oldnode, oldnode);
	alloc_.destroy(&oldnode->data_);
	node_alloc_.deallocate(oldnode, 1);
	--alloc_.m_;
	return result;
}

template <class T, class Allocator>
list<T, Allocator>::iterator
list<T, Allocator>::erase(iterator position, iterator last)
{
	if (position == last)
		return last;
	remove_nodes(position.node_, last.node_->prev_);
	while (position != last)
	{
		alloc_.destroy(&*position);
		node* t = position.node_;
		++position;
		node_alloc_.deallocate(t, 1);
		--alloc_.m_;
	}
	return last;
}

template <class T, class Allocator>
void
list<T, Allocator>::swap(list<T,Allocator>& x)
{
	if (this != &x)  // hh 981208
	{
		_STD::swap(alloc_, x.alloc_);
		_STD::swap(node_alloc_, x.node_alloc_);
		node_base& tail = node_alloc_.m_;
		tail.next_->prev_ = tail.prev_->next_ = (node*)&tail;
		node_base& x_tail = x.node_alloc_.m_;
		x_tail.next_->prev_ = x_tail.prev_->next_ = (node*)&x_tail;
	}
}

template <class T, class Allocator>
void
list<T, Allocator>::clear()
{
	if (alloc_.m_ == 0)
		return;
	iterator e = end();
	for (iterator i = begin(); i != e;)
	{
		alloc_.destroy(&*i);
		node* t = i.node_;
		++i;
		node_alloc_.deallocate(t, 1);
	}
	alloc_.m_ = 0;
	node_base& tail = node_alloc_.m_;
	tail.prev_ = tail.next_ = (node*)&tail;
}

template <class T, class Allocator>
void
list<T, Allocator>::splice(iterator position, list<T,Allocator>& x)
{
	if (x.size() > 0)
	{
		if (size() > max_size() - x.size())
			#ifdef MSIPL_EXCEPT
				throw length_error("list::splice length error");
			#else
			{
				fprintf(stderr, "list::splice length error\n");
				abort();
			}
			#endif
		node_base& x_tail = x.node_alloc_.m_;
		node_base* s1 = x_tail.next_;
		node_base* s2 = x_tail.prev_;
		x_tail.prev_ = x_tail.next_ = (node*)&x_tail;
		alloc_.m_ += x.alloc_.m_;
		x.alloc_.m_ = 0;
		insert_nodes(position.node_, s1, s2);
	}
}

template <class T, class Allocator>
void
list<T, Allocator>::splice(iterator position, list<T,Allocator>& x, iterator i)
{
	if (size() > max_size() - 1)
		#ifdef MSIPL_EXCEPT
			throw length_error("list::splice length error");
		#else
		{
			fprintf(stderr, "list::splice length error\n");
			abort();
		}
		#endif
	node_base* p = position.node_;
	node_base* s1 = i.node_;
	if (s1 == p->prev_ || s1 == p)
		return;
	remove_nodes(s1, s1);
	--x.alloc_.m_;
	insert_nodes(p, s1, s1);
	++alloc_.m_;
}

template <class T, class Allocator>
void
list<T, Allocator>::splice(iterator position, list<T,Allocator>& x, iterator first, iterator last)
{
	if (first == last)
		return;
	if (this != &x)
	{
		size_type delta = (size_type)distance(first, last);
		if (size() > max_size() - delta)
			#ifdef MSIPL_EXCEPT
				throw length_error("list::splice length error");
			#else
			{
				fprintf(stderr, "list::splice length error\n");
				abort();
			}
			#endif
		x.alloc_.m_ -= delta;
		alloc_.m_ += delta;
	}
	node_base* s1 = first.node_;
	node_base* s2 = last.node_->prev_;
	remove_nodes(s1, s2);
	insert_nodes(position.node_, s1, s2);
}

template <class T, class Allocator>
void
list<T, Allocator>::remove(const T& value)
{
	iterator e = end();
	for (iterator i = begin(); i != e; ++i)
	{
		if (*i == value)
		{
			iterator j = i;
			for (++j; j != e; ++j)
				if (!(*j == value))
					break;
			i = erase(i, j);
			if (i == e)
				break;
		}
	}
}

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

template <class T, class Allocator>
void
list<T, Allocator>::merge(list<T, Allocator>& x)
{
	if (this == &x)
		return;
	if (size() > max_size() - x.size())
		#ifdef MSIPL_EXCEPT
			throw length_error("list::merge length error");
		#else
		{
			fprintf(stderr, "list::merge length error\n");
			abort();
		}
		#endif
	iterator first1 = begin();
	iterator last1 = end();
	iterator first2 = x.begin();
	iterator last2 = x.end();
	for (; first1 != last1 && first2 != last2; ++first1)
	{
		if (*first2 < *first1)
		{
			iterator j = first2;
			size_t count = 1;
			for (++j; j != last2; ++j, ++count)
				if (!(*j < *first1))
					break;
			node_base* k = j.node_->prev_;
			remove_nodes(first2.node_, k);
			insert_nodes(first1.node_, first2.node_, k);
			x.alloc_.m_ -= count;
			alloc_.m_ += count;
			first2 = j;
		}
	}
	if (first2 != last2)
		splice(first1, x);
}

template <class T, class Allocator>
void
list<T, Allocator>::sort()
{
	switch (size())
	{
	case 0:
	case 1:
		break;
	case 2:
	{
		iterator i = begin();
		iterator j = i;
		++j;
		if (*j < *i)
		{	// reverse()
			_STD::swap(i.node_->prev_, i.node_->next_);
			_STD::swap(j.node_->prev_, j.node_->next_);
			_STD::swap(node_alloc_.m_.prev_, node_alloc_.m_.next_);
		}
	}
		break;
	default:
	{
		iterator i = begin();
		size_type lower_size = size() / 2;
		advance(i, lower_size);
		list upper_half;
		// upper_half.splice(upper_half.begin(), *this, i, end());
		node_base* s1 = i.node_;
		node_base* s2 = node_alloc_.m_.prev_;
		remove_nodes(s1, s2);
		insert_nodes(&upper_half.node_alloc_.m_, s1, s2);
		upper_half.alloc_.m_ = alloc_.m_ - lower_size;
		alloc_.m_ = lower_size;
		sort();
		upper_half.sort();
		merge(upper_half);
		break;
	}
	}
}

template <class T, class Allocator>
void
list<T, Allocator>::reverse()
{
	if (size() < 2)
		return;
	iterator e = end();
	for (iterator i = begin(); i != e; --i)
		_STD::swap(i.node_->prev_, i.node_->next_);
	_STD::swap(node_alloc_.m_.prev_, node_alloc_.m_.next_);
}

// range is [first, last] NOT [first, last)
template <class T, class Allocator>
inline
void
list<T, Allocator>::remove_nodes(node_base* first, node_base* 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<T, Allocator>::insert_nodes(node_base* here, node_base* first, node_base* last)
{
	here->prev_->next_ = (node*)first;
	first->prev_ = here->prev_;
	here->prev_ = (node*)last;
	last->next_ = (node*)here;
}

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

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

#if defined(MSIPL_PARTIAL_SPECIALIZATION) && defined(MSIPL_MEMBER_TEMPLATE) && !defined(_Inhibit_Container_Optimization)

	// Specialize for T* to save on code bloat

	// void*

	template <class Allocator>
	class list<void*, Allocator>
	{
		template <bool b> struct chooser {};
	public:
		//  types:
		typedef typename Allocator::reference         reference;
		typedef typename Allocator::const_reference   const_reference;
		class                                         iterator;
		class                                         const_iterator;
		typedef typename Allocator::size_type         size_type;
		typedef typename Allocator::difference_type   difference_type;
		typedef void*                                 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;

	private:

		struct node;

		struct node_base
		{
			node* prev_;
			node* next_;
		};

		struct node
			: public node_base
		{
			value_type data_;
		};

		typedef ALLOC_BIND (node)                     node_allocator_type;

	public:

		friend class iterator;
		class iterator
			: public _STD::iterator<bidirectional_iterator_tag, value_type, difference_type, pointer, reference>
		{
		public:
			iterator() {}
			reference operator * () const {return node_->data_;}
			pointer operator -> () const {return &node_->data_;}
			iterator& operator ++ () {node_ = node_->next_; return *this;}
			iterator operator ++ (int) {iterator tmp(*this); node_ = node_->next_; return tmp;}
			iterator& operator -- () {node_ = node_->prev_; return *this;}
			iterator operator -- (int) {iterator tmp(*this); node_ = node_->prev_; return tmp;}
			bool operator ==(const iterator& rhs) const {return node_ == rhs.node_;}
			bool operator !=(const iterator& rhs) const {return node_ != rhs.node_;}
		private:
			node* node_;

			iterator(node* node) : node_(node) {}

			friend class list;
			friend class list::const_iterator;
		};

		friend class const_iterator;
		class const_iterator
			: public _STD::iterator<bidirectional_iterator_tag, value_type, difference_type, const_pointer, const_reference>
		{
		public:
			const_iterator() {}
			const_iterator(const list::iterator& x) : node_(x.node_) {}
			const_reference operator * () const {return node_->data_;}
			const_pointer operator -> () const {return &node_->data_;}
			const_iterator& operator ++ () {node_ = node_->next_; return *this;}
			const_iterator operator ++ (int) {const_iterator tmp(*this); node_ = node_->next_; return tmp;}
			const_iterator& operator -- () {node_ = node_->prev_; return *this;}
			const_iterator operator -- (int) {const_iterator tmp(*this); node_ = node_->prev_; return tmp;}
			bool operator ==(const const_iterator& rhs) const {return node_ == rhs.node_;}
			bool operator !=(const const_iterator& rhs) const {return node_ != rhs.node_;}
		private:
			const node* node_;

			const_iterator(const node* node) : node_(node) {}

			friend class list;
		};

		//  lib.list.cons construct/copy/destroy:
		explicit list(const Allocator& = Allocator());
		explicit list(size_type n, const value_type& value = 0, const Allocator& = Allocator());
		template <class InputIterator>
			list(InputIterator first, InputIterator last, const Allocator& a = Allocator())
				: alloc_(a, 0),
				  node_alloc_(node_allocator_type(a))
			{
				node_base& tail = node_alloc_.m_;
				tail.prev_ = tail.next_ = (node*)&tail;
				choose_init(first, last, chooser<numeric_limits<InputIterator>::is_integer>());
			}
		list(const list<void*,Allocator>& x);
		~list();
		list<void*,Allocator>& operator=(const list<void*,Allocator>& x);
		template <class InputIterator>
			inline
			void assign(InputIterator first, InputIterator last)
			{
				choose_assign(first, last, chooser<numeric_limits<InputIterator>::is_integer>());
			}
		void assign(size_type n, const value_type& t);
		allocator_type get_allocator() const;

		//  iterators:
		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;

		//  lib.list.capacity capacity:
		bool      empty() const;
		size_type size() const;
		size_type max_size() const;
		void      resize(size_type sz, value_type c = 0);

		//  element access:
		reference       front();
		const_reference front() const;
		reference       back();
		const_reference back() const;

		//  lib.list.modifiers modifiers:
		void push_front(const value_type& x);
		void pop_front();
		void push_back(const value_type& x);
		void pop_back();

		iterator insert(iterator position, const value_type& x);
		void     insert(iterator position, size_type n, const value_type& x);
		template <class InputIterator>
			void insert(iterator position, InputIterator first, InputIterator last)
			{
				list temp(first, last, alloc_);
				splice(position, temp);
			}

		iterator erase(iterator position);
		iterator erase(iterator position, iterator last);
		void     swap(list<void*,Allocator>& x);
		void     clear();

		//  lib.list.ops list operations:
		void splice(iterator position, list<void*,Allocator>& x);
		void splice(iterator position, list<void*,Allocator>& x, iterator i);
		void splice(iterator position, list<void*,Allocator>& x, iterator first, iterator last);

		void remove(const value_type& value);
		template <class Predicate>
			void remove_if(Predicate pred)
			{
				iterator e = end();
				for (iterator i = begin(); i != e; ++i)
				{
					if (pred(*i))
					{
						iterator j = i;
						for (++j; j != e; ++j)
							if (!pred(*j))
								break;
						i = erase(i, j);
						if (i == e)
							break;
					}
				}
			}

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

		void merge(list<void*,Allocator>& x);
		template <class Compare>
			void merge(list<void*,Allocator>& x, Compare comp)
			{
				if (this == &x)
					return;
				if (size() > max_size() - x.size())
					#ifdef MSIPL_EXCEPT
						throw length_error("list::merge length error");
					#else
					{
						fprintf(stderr, "list::merge length error\n");
						abort();
					}
					#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;
						node_base* k = j.node_->prev_;
						remove_nodes(first2.node_, k);
						insert_nodes(first1.node_, first2.node_, k);
						x.alloc_.m_ -= count;
						alloc_.m_ += count;
						first2 = j;
					}
				}
				if (first2 != last2)
					splice(first1, x);
			}

		void sort();
		template <class Compare>
			void sort(Compare comp)
			{
				switch (size())
				{
				case 0:
				case 1:
					break;
				case 2:
				{
					iterator i = begin();
					iterator j = i;
					++j;
					if (comp(*j, *i))
					{	// reverse()
						_STD::swap(i.node_->prev_, i.node_->next_);
						_STD::swap(j.node_->prev_, j.node_->next_);
						_STD::swap(node_alloc_.m_.prev_, node_alloc_.m_.next_);
					}
				}
					break;
				default:
				{
					iterator i = begin();
					size_type lower_size = size() / 2;
					advance(i, lower_size);
					list upper_half;
					// upper_half.splice(upper_half.begin(), *this, i, end());
					node_base* s1 = i.node_;
					node_base* s2 = node_alloc_.m_.prev_;
					remove_nodes(s1, s2);
					insert_nodes(&upper_half.node_alloc_.m_, s1, s2);
					upper_half.alloc_.m_ = alloc_.m_ - lower_size;
					alloc_.m_ = lower_size;
					sort(comp);
					upper_half.sort(comp);
					merge(upper_half, comp);
					break;
				}
				}
			}

		void reverse();
	private:
		_EmptyMemberOpt<Allocator, size_type> alloc_;  // alloc_.m_ is size_
		_EmptyMemberOpt<node_allocator_type, node_base> node_alloc_;  // node_alloc_.m_ is tail pseudo node
		                                                              // node_alloc_.m_.next_ is first node
		                                                              // node_alloc_.m_.prev_ is last node

		template <class InputIterator>
			void
			choose_init(InputIterator first, InputIterator last, chooser<true>)
			{
				size_type n = static_cast<size_type>(first);
				if (n > max_size())
					#ifdef MSIPL_EXCEPT
						throw length_error("list::construction length error");
					#else
					{
						fprintf(stderr, "list::construction length error\n");
						abort();
					}
					#endif
				#ifdef MSIPL_EXCEPT
				try
				{
				#endif
					for (; n > 0; --n)
						push_back(reinterpret_cast<value_type>(last));  // hh 981208
				#ifdef MSIPL_EXCEPT
				}
				catch (...)
				{
					clear();
					throw;
				}
				#endif
			}

		template <class InputIterator>
			void
			choose_init(InputIterator first, InputIterator last, chooser<false>)
			{
				#ifdef MSIPL_EXCEPT
				try
				{
				#endif
					for (; first != last; ++first)
						push_back(*first);
				#ifdef MSIPL_EXCEPT
				}
				catch (...)
				{
					clear();
					throw;
				}
				#endif
			}

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

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

		template <class InputIterator>
			void
			do_assign(InputIterator first, InputIterator last, input_iterator_tag)
			{
				list temp(first, last, alloc_);
				clear();
				splice(begin(), temp);
			}

		template <class ForwardIterator>
			void
			do_assign(ForwardIterator first, ForwardIterator last, forward_iterator_tag)
			{
				ForwardIterator f = first;
				for (size_type c = size(); c != 0 && f != last; --c)
					++f;
				list temp(f, last, alloc_);
				if (size() > max_size() - temp.size())
					#ifdef MSIPL_EXCEPT
						throw length_error("list::assign length error");
					#else
					{
						fprintf(stderr, "list::assign length error\n");
						abort();
					}
					#endif
				iterator i = copy(first, f, begin());
				if (temp.size() > 0)
					splice(i, temp);
				else
					erase(i, end());
			}

		template <class RandomAccessIterator>
			void
			do_assign(RandomAccessIterator first, RandomAccessIterator last, random_access_iterator_tag)
			{
				RandomAccessIterator f = first + min(size(), size_type(last - first));
				if (last - first > max_size())
					#ifdef MSIPL_EXCEPT
						throw length_error("list::assign length error");
					#else
					{
						fprintf(stderr, "list::assign length error\n");
						abort();
					}
					#endif
				list temp(f, last, alloc_);
				iterator i = copy(first, f, begin());
				if (temp.size() > 0)
					splice(i, temp);
				else
					erase(i, end());
			}

		static void remove_nodes(node_base* first, node_base* last);
		static void insert_nodes(node_base* here, node_base* first, node_base* last);

	};

	// Implementation list<void*>

	template <class Allocator>
	list<void*, Allocator>::list(const Allocator& a)
		: alloc_(a, 0),
		  node_alloc_(node_allocator_type(a))
	{
		node_base& tail = node_alloc_.m_;
		tail.prev_ = tail.next_ = (node*)&tail;
	}

	template <class Allocator>
	list<void*, Allocator>::list(size_type n, const value_type& value, const Allocator& a)
		: alloc_(a, 0),
		  node_alloc_(node_allocator_type(a))
	{
		if (n > max_size())
			#ifdef MSIPL_EXCEPT
				throw length_error("list::construction length error");
			#else
			{
				fprintf(stderr, "list::construction length error\n");
				abort();
			}
			#endif
		node_base& tail = node_alloc_.m_;
		tail.prev_ = tail.next_ = (node*)&tail;
		#ifdef MSIPL_EXCEPT
		try
		{
		#endif
			for (; n > 0; --n)
				push_back(value);
		#ifdef MSIPL_EXCEPT
		}
		catch (...)
		{
			clear();
			throw;
		}
		#endif
	}

	template <class Allocator>
	list<void*, Allocator>::list(const list<void*,Allocator>& x)
		: alloc_(x.alloc_, 0),
		  node_alloc_(x.node_alloc_)
	{
		node_base& tail = node_alloc_.m_;
		tail.prev_ = tail.next_ = (node*)&tail;
		const_iterator e = x.end();
		#ifdef MSIPL_EXCEPT
		try
		{
		#endif
			for (const_iterator i = x.begin(); i != e; ++i)
				push_back(*i);
		#ifdef MSIPL_EXCEPT
		}
		catch (...)
		{
			clear();
			throw;
		}
		#endif
	}

	template <class Allocator>
	inline
	list<void*, Allocator>::~list()
	{
		clear();
	}

	template <class Allocator>
	inline
	list<void*, Allocator>&
	list<void*, Allocator>::operator=(const list<void*, Allocator>& x)
	{
		if (this != &x)
			assign(x.begin(), x.end());
		return *this;
	}

	template <class Allocator>
	void
	list<void*, Allocator>::assign(size_type n, const value_type& t)
	{
		if (n > max_size())
			#ifdef MSIPL_EXCEPT
				throw length_error("list::assign length error");
			#else
			{
				fprintf(stderr, "list::assign length error\n");
				abort();
			}
			#endif
		if (n > size())
		{
			list temp(n - size(), t, alloc_);
			iterator i;
			for (i = begin(); i != end(); ++i)
				*i = t;
			splice(i, temp);
		}
		else
		{
			iterator i;
			for (i = begin(); n != 0; --n, ++i)
				*i = t;
			erase(i, end());
		}
	}

	template <class Allocator>
	inline
	list<void*, Allocator>::allocator_type
	list<void*, Allocator>::get_allocator() const
	{
		return alloc_;
	}

	template <class Allocator>
	inline
	list<void*, Allocator>::iterator
	list<void*, Allocator>::begin()
	{
		return iterator(node_alloc_.m_.next_);
	}

	template <class Allocator>
	inline
	list<void*, Allocator>::const_iterator
	list<void*, Allocator>::begin() const
	{
		return const_iterator(node_alloc_.m_.next_);
	}

	template <class Allocator>
	inline
	list<void*, Allocator>::iterator
	list<void*, Allocator>::end()
	{
		return iterator((node*)&node_alloc_.m_);
	}

	template <class Allocator>
	inline
	list<void*, Allocator>::const_iterator
	list<void*, Allocator>::end() const
	{
		return const_iterator((node*)&node_alloc_.m_);
	}

	template <class Allocator>
	inline
	list<void*, Allocator>::reverse_iterator
	list<void*, Allocator>::rbegin()
	{
		return reverse_iterator(end());
	}

	template <class Allocator>
	inline
	list<void*, Allocator>::const_reverse_iterator
	list<void*, Allocator>::rbegin() const
	{
		return const_reverse_iterator(end());
	}

	template <class Allocator>
	inline
	list<void*, Allocator>::reverse_iterator
	list<void*, Allocator>::rend()
	{
		return reverse_iterator(begin());
	}

	template <class Allocator>
	inline
	list<void*, Allocator>::const_reverse_iterator
	list<void*, Allocator>::rend() const
	{
		return const_reverse_iterator(begin());
	}

	template <class Allocator>
	inline
	bool
	list<void*, Allocator>::empty() const
	{
		return alloc_.m_ == 0;
	}

	template <class Allocator>
	inline
	list<void*, Allocator>::size_type
	list<void*, Allocator>::size() const
	{
		return alloc_.m_;
	}

	template <class Allocator>
	inline
	list<void*, Allocator>::size_type
	list<void*, Allocator>::max_size() const
	{
		return (size_type)numeric_limits<difference_type>::max();
	}

	template <class Allocator>
	void
	list<void*, Allocator>::resize(size_type sz, value_type c)
	{
		if (sz > size())
			insert(end(), sz-size(), c);
		else if (sz < size())
		{
			iterator i;
			if (sz < size() / 2)
			{
				i = begin();
				advance(i, sz);
			}
			else
			{
				i = end();
				advance(i, difference_type(sz - size()));
			}
			erase(i, end());
		}
	}

	template <class Allocator>
	inline
	list<void*, Allocator>::reference
	list<void*, Allocator>::front()
	{
		return node_alloc_.m_.next_->data_;
	}

	template <class Allocator>
	inline
	list<void*, Allocator>::const_reference
	list<void*, Allocator>::front() const
	{
		return node_alloc_.m_.next_->data_;
	}

	template <class Allocator>
	inline
	list<void*, Allocator>::reference
	list<void*, Allocator>::back()
	{
		return node_alloc_.m_.prev_->data_;
	}

	template <class Allocator>
	inline
	list<void*, Allocator>::const_reference
	list<void*, Allocator>::back() const
	{
		return node_alloc_.m_.prev_->data_;
	}

	template <class Allocator>
	inline
	void
	list<void*, Allocator>::push_front(const value_type& x)
	{
		insert(begin(), x);
	}

	template <class Allocator>
	inline
	void
	list<void*, Allocator>::pop_front()
	{
		erase(begin());
	}

	template <class Allocator>
	inline
	void
	list<void*, Allocator>::push_back(const value_type& x)
	{
		insert(end(), x);
	}

	template <class Allocator>
	inline
	void
	list<void*, Allocator>::pop_back()
	{
		erase(node_alloc_.m_.prev_);
	}

	template <class Allocator>
	list<void*, Allocator>::iterator
	list<void*, Allocator>::insert(iterator position, const value_type& x)
	{
		if (size() > max_size() - 1)
			#ifdef MSIPL_EXCEPT
				throw length_error("list::insert length error");
			#else
			{
				fprintf(stderr, "list::insert length error\n");
				abort();
			}
			#endif
		node* newnode = node_alloc_.allocate(1);
		newnode->data_ = x;
		insert_nodes(position.node_, newnode, newnode);
		++alloc_.m_;
		return newnode;
	}

	template <class Allocator>
	void
	list<void*, Allocator>::insert(iterator position, size_type n, const value_type& x)
	{
		list temp(n, x, alloc_);
		splice(position, temp);
	}

	template <class Allocator>
	list<void*, Allocator>::iterator
	list<void*, Allocator>::erase(iterator position)
	{
		node* oldnode = position.node_;
		node* result = oldnode->next_;
		remove_nodes(oldnode, oldnode);
		node_alloc_.deallocate(oldnode, 1);
		--alloc_.m_;
		return result;
	}

	template <class Allocator>
	list<void*, Allocator>::iterator
	list<void*, Allocator>::erase(iterator position, iterator last)
	{
		if (position == last)
			return last;
		remove_nodes(position.node_, last.node_->prev_);
		while (position != last)
		{
			node* t = position.node_;
			++position;
			node_alloc_.deallocate(t, 1);
			--alloc_.m_;
		}
		return last;
	}

	template <class Allocator>
	void
	list<void*, Allocator>::swap(list<void*,Allocator>& x)
	{
		if (this != &x)  // hh 981208
		{
			_STD::swap(alloc_, x.alloc_);
			_STD::swap(node_alloc_, x.node_alloc_);
			node_base& tail = node_alloc_.m_;
			tail.next_->prev_ = tail.prev_->next_ = (node*)&tail;
			node_base& x_tail = x.node_alloc_.m_;
			x_tail.next_->prev_ = x_tail.prev_->next_ = (node*)&x_tail;
		}
	}

	template <class Allocator>
	void
	list<void*, Allocator>::clear()
	{
		if (alloc_.m_ == 0)
			return;
		iterator e = end();
		for (iterator i = begin(); i != e;)
		{
			node* t = i.node_;
			++i;
			node_alloc_.deallocate(t, 1);
		}
		alloc_.m_ = 0;
		node_base& tail = node_alloc_.m_;
		tail.prev_ = tail.next_ = (node*)&tail;
	}

	template <class Allocator>
	void
	list<void*, Allocator>::splice(iterator position, list<void*,Allocator>& x)
	{
		if (x.size() > 0)
		{
			if (size() > max_size() - x.size())
				#ifdef MSIPL_EXCEPT
					throw length_error("list::splice length error");
				#else
				{
					fprintf(stderr, "list::splice length error\n");
					abort();
				}
				#endif
			node_base& x_tail = x.node_alloc_.m_;
			node_base* s1 = x_tail.next_;
			node_base* s2 = x_tail.prev_;
			x_tail.prev_ = x_tail.next_ = (node*)&x_tail;
			alloc_.m_ += x.alloc_.m_;
			x.alloc_.m_ = 0;
			insert_nodes(position.node_, s1, s2);
		}
	}

	template <class Allocator>
	void
	list<void*, Allocator>::splice(iterator position, list<void*,Allocator>& x, iterator i)
	{
		if (size() > max_size() - 1)
			#ifdef MSIPL_EXCEPT
				throw length_error("list::splice length error");
			#else
			{
				fprintf(stderr, "list::splice length error\n");
				abort();
			}
			#endif
		node_base* p = position.node_;
		node_base* s1 = i.node_;
		if (s1 == p->prev_ || s1 == p)
			return;
		remove_nodes(s1, s1);
		--x.alloc_.m_;
		insert_nodes(p, s1, s1);
		++alloc_.m_;
	}

	template <class Allocator>
	void
	list<void*, Allocator>::splice(iterator position, list<void*,Allocator>& x, iterator first, iterator last)
	{
		if (first == last)
			return;
		if (this != &x)
		{
			size_type delta = (size_type)distance(first, last);
			if (size() > max_size() - delta)
				#ifdef MSIPL_EXCEPT
					throw length_error("list::splice length error");
				#else
				{
					fprintf(stderr, "list::splice length error\n");
					abort();
				}
				#endif
			x.alloc_.m_ -= delta;
			alloc_.m_ += delta;
		}
		node_base* s1 = first.node_;
		node_base* s2 = last.node_->prev_;
		remove_nodes(s1, s2);
		insert_nodes(position.node_, s1, s2);
	}

	template <class Allocator>
	void
	list<void*, Allocator>::remove(const value_type& value)
	{
		iterator e = end();
		for (iterator i = begin(); i != e; ++i)
		{
			if (*i == value)
			{
				iterator j = i;
				for (++j; j != e; ++j)
					if (!(*j == value))
						break;
				i = erase(i, j);
				if (i == e)
					break;
			}
		}
	}

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

	template <class Allocator>
	void
	list<void*, Allocator>::merge(list<void*, Allocator>& x)
	{
		if (this == &x)
			return;
		if (size() > max_size() - x.size())
			#ifdef MSIPL_EXCEPT
				throw length_error("list::merge length error");
			#else
			{
				fprintf(stderr, "list::merge length error\n");
				abort();
			}
			#endif
		iterator first1 = begin();
		iterator last1 = end();
		iterator first2 = x.begin();
		iterator last2 = x.end();
		for (; first1 != last1 && first2 != last2; ++first1)
		{
			if (*first2 < *first1)
			{
				iterator j = first2;
				size_t count = 1;
				for (++j; j != last2; ++j, ++count)
					if (!(*j < *first1))
						break;
				node_base* k = j.node_->prev_;
				remove_nodes(first2.node_, k);
				insert_nodes(first1.node_, first2.node_, k);
				x.alloc_.m_ -= count;
				alloc_.m_ += count;
				first2 = j;
			}
		}
		if (first2 != last2)
			splice(first1, x);
	}

	template <class Allocator>
	void
	list<void*, Allocator>::sort()
	{
		switch (size())
		{
		case 0:
		case 1:
			break;
		case 2:
		{
			iterator i = begin();
			iterator j = i;
			++j;
			if (*j < *i)
			{	// reverse()
				_STD::swap(i.node_->prev_, i.node_->next_);
				_STD::swap(j.node_->prev_, j.node_->next_);
				_STD::swap(node_alloc_.m_.prev_, node_alloc_.m_.next_);
			}
		}
			break;
		default:
		{
			iterator i = begin();
			size_type lower_size = size() / 2;
			advance(i, lower_size);
			list upper_half;
			// upper_half.splice(upper_half.begin(), *this, i, end());
			node_base* s1 = i.node_;
			node_base* s2 = node_alloc_.m_.prev_;
			remove_nodes(s1, s2);
			insert_nodes(&upper_half.node_alloc_.m_, s1, s2);
			upper_half.alloc_.m_ = alloc_.m_ - lower_size;
			alloc_.m_ = lower_size;
			sort();
			upper_half.sort();
			merge(upper_half);
			break;
		}
		}
	}

	template <class Allocator>
	void
	list<void*, Allocator>::reverse()
	{
		if (size() < 2)
			return;
		iterator e = end();
		for (iterator i = begin(); i != e; --i)
			_STD::swap(i.node_->prev_, i.node_->next_);
		_STD::swap(node_alloc_.m_.prev_, node_alloc_.m_.next_);
	}

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

	// range is [first, last] NOT [first, last)
	template <class Allocator>
	inline
	void
	list<void*, Allocator>::insert_nodes(node_base* here, node_base* first, node_base* last)
	{
		here->prev_->next_ = (node*)first;
		first->prev_ = here->prev_;
		here->prev_ = (node*)last;
		last->next_ = (node*)here;
	}

	template <class Allocator>
	inline
	bool
	operator==(const list<void*,Allocator>& x, const list<void*,Allocator>& y)
	{
		return x.size() == y.size() && equal(x.begin(), x.end(), y.begin());
	}

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

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

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

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

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

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

	// T*

	template <class T, class Allocator>
	class list<T*, Allocator>
		: private list<void*, Allocator::rebind<void*>::other>
	{
		typedef list<void*, Allocator::rebind<void*>::other> base;
		typedef base::allocator_type base_allocator;
	public:
		//  types:
		typedef typename Allocator::reference         reference;
		typedef typename Allocator::const_reference   const_reference;
		class                                         iterator;
		class                                         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;

	public:

		class iterator
			: public _STD::iterator<bidirectional_iterator_tag, value_type, difference_type, pointer, reference>
		{
		public:
			iterator() {}
			explicit iterator(const base::iterator& i) : i_(i) {}
			operator base::iterator() const {return i_;}
			reference operator * () const {return reference(*i_);}
			pointer operator -> () const {return pointer(i_.operator->());}
			iterator& operator ++ () {++i_; return *this;}
			iterator operator ++ (int) {iterator tmp(*this); ++i_; return tmp;}
			iterator& operator -- () {--i_; return *this;}
			iterator operator -- (int) {iterator tmp(*this); --i_; return tmp;}
			bool operator ==(const iterator& rhs) const {return i_ == rhs.i_;}
			bool operator !=(const iterator& rhs) const {return i_ != rhs.i_;}
		private:
			base::iterator i_;

			friend class list::const_iterator;
		};

		class const_iterator
			: public _STD::iterator<bidirectional_iterator_tag, value_type, difference_type, const_pointer, const_reference>
		{
		public:
			const_iterator() {}
			const_iterator(const list::iterator& x) : i_(x.i_) {}
			explicit const_iterator(const base::const_iterator& i) : i_(i) {}
			operator base::const_iterator() const {return i_;}
			const_reference operator * () const {return const_reference(*i_);}
			const_pointer operator -> () const {return const_pointer(i_.operator->());}
			const_iterator& operator ++ () {++i_; return *this;}
			const_iterator operator ++ (int) {const_iterator tmp(*this); ++i_; return tmp;}
			const_iterator& operator -- () {--i_; return *this;}
			const_iterator operator -- (int) {const_iterator tmp(*this); --i_; return tmp;}
			bool operator ==(const const_iterator& rhs) const {return i_ == rhs.i_;}
			bool operator !=(const const_iterator& rhs) const {return i_ != rhs.i_;}
		private:
			base::const_iterator i_;
		};

		//  lib.list.cons construct/copy/destroy:
		explicit list(const Allocator& = Allocator());
		explicit list(size_type n, const value_type& value = 0, const Allocator& = Allocator());
		template <class InputIterator>
			inline
			list(InputIterator first, InputIterator last, const Allocator& a = Allocator())
				: base(first, last, base_allocator(a))
			{
			}
		template <class InputIterator>
			inline
			void assign(InputIterator first, InputIterator last)
			{
				base::assign(first, last);
			}
		void assign(size_type n, const value_type& t);
		allocator_type get_allocator() const;

		//  iterators:
		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;

		//  lib.list.capacity capacity:
		bool      empty() const;
		size_type size() const;
		size_type max_size() const;
		void      resize(size_type sz, value_type c = 0);

		//  element access:
		reference       front();
		const_reference front() const;
		reference       back();
		const_reference back() const;

		//  lib.list.modifiers modifiers:
		void push_front(const value_type& x);
		void pop_front();
		void push_back(const value_type& x);
		void pop_back();

		iterator insert(iterator position, const value_type& x);
		void     insert(iterator position, size_type n, const value_type& x);
		template <class InputIterator>
			inline
			void insert(iterator position, InputIterator first, InputIterator last)
			{
				base::insert(position, first, last);
			}

		iterator erase(iterator position);
		iterator erase(iterator position, iterator last);
		void     swap(list<T*,Allocator>& x);
		void     clear();

		//  lib.list.ops list operations:
		void splice(iterator position, list<T*,Allocator>& x);
		void splice(iterator position, list<T*,Allocator>& x, iterator i);
		void splice(iterator position, list<T*,Allocator>& x, iterator first, iterator last);

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

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

		void merge(list<T*,Allocator>& x);
		template <class Compare>
			inline
			void merge(list<T*,Allocator>& x, Compare comp)
			{
				base::merge((base&)x, binary_convert<Compare>(comp));
			}

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

		void reverse();

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

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

	// Implementation list<T*>

	template <class T, class Allocator>
	inline
	list<T*, Allocator>::list(const Allocator& a)
		: base(base_allocator(a))
	{
	}

	template <class T, class Allocator>
	inline
	list<T*, Allocator>::list(size_type n, const value_type& value, const Allocator& a)
		: base(n, value, base_allocator(a))
	{
	}

	template <class T, class Allocator>
	inline
	void
	list<T*, Allocator>::assign(size_type n, const value_type& t)
	{
		base::assign(n, t);
	}

	template <class T, class Allocator>
	inline
	list<T*, Allocator>::allocator_type
	list<T*, Allocator>::get_allocator() const
	{
		return base::get_allocator();
	}

	template <class T, class Allocator>
	inline
	list<T*, Allocator>::iterator
	list<T*, Allocator>::begin()
	{
		return iterator(base::begin());
	}

	template <class T, class Allocator>
	inline
	list<T*, Allocator>::const_iterator
	list<T*, Allocator>::begin() const
	{
		return const_iterator(base::begin());
	}

	template <class T, class Allocator>
	inline
	list<T*, Allocator>::iterator
	list<T*, Allocator>::end()
	{
		return iterator(base::end());
	}

	template <class T, class Allocator>
	inline
	list<T*, Allocator>::const_iterator
	list<T*, Allocator>::end() const
	{
		return const_iterator(base::end());
	}

	template <class T, class Allocator>
	inline
	list<T*, Allocator>::reverse_iterator
	list<T*, Allocator>::rbegin()
	{
		return reverse_iterator(end());
	}

	template <class T, class Allocator>
	inline
	list<T*, Allocator>::const_reverse_iterator
	list<T*, Allocator>::rbegin() const
	{
		return const_reverse_iterator(end());
	}

	template <class T, class Allocator>
	inline
	list<T*, Allocator>::reverse_iterator
	list<T*, Allocator>::rend()
	{
		return reverse_iterator(begin());
	}

	template <class T, class Allocator>
	inline
	list<T*, Allocator>::const_reverse_iterator
	list<T*, Allocator>::rend() const
	{
		return const_reverse_iterator(begin());
	}

	template <class T, class Allocator>
	inline
	bool
	list<T*, Allocator>::empty() const
	{
		return base::empty();
	}

	template <class T, class Allocator>
	inline
	list<T*, Allocator>::size_type
	list<T*, Allocator>::size() const
	{
		return base::size();
	}

	template <class T, class Allocator>
	inline
	list<T*, Allocator>::size_type
	list<T*, Allocator>::max_size() const
	{
		return base::max_size();
	}

	template <class T, class Allocator>
	void
	list<T*, Allocator>::resize(size_type sz, value_type c)
	{
		base::resize(sz, c);
	}

	template <class T, class Allocator>
	inline
	list<T*, Allocator>::reference
	list<T*, Allocator>::front()
	{
		return reference(base::front());
	}

	template <class T, class Allocator>
	inline
	list<T*, Allocator>::const_reference
	list<T*, Allocator>::front() const
	{
		return const_reference(base::front());
	}

	template <class T, class Allocator>
	inline
	list<T*, Allocator>::reference
	list<T*, Allocator>::back()
	{
		return reference(base::back());
	}

	template <class T, class Allocator>
	inline
	list<T*, Allocator>::const_reference
	list<T*, Allocator>::back() const
	{
		return const_reference(base::back());
	}

	template <class T, class Allocator>
	inline
	void
	list<T*, Allocator>::push_front(const value_type& x)
	{
		base::push_front(x);
	}

	template <class T, class Allocator>
	inline
	void
	list<T*, Allocator>::pop_front()
	{
		base::pop_front();
	}

	template <class T, class Allocator>
	inline
	void
	list<T*, Allocator>::push_back(const value_type& x)
	{
		base::push_back(x);
	}

	template <class T, class Allocator>
	inline
	void
	list<T*, Allocator>::pop_back()
	{
		base::pop_back();
	}

	template <class T, class Allocator>
	inline
	list<T*, Allocator>::iterator
	list<T*, Allocator>::insert(iterator position, const value_type& x)
	{
		return iterator(base::insert(position, x));
	}

	template <class T, class Allocator>
	inline
	void
	list<T*, Allocator>::insert(iterator position, size_type n, const value_type& x)
	{
		base::insert(position, n, x);
	}

	template <class T, class Allocator>
	inline
	list<T*, Allocator>::iterator
	list<T*, Allocator>::erase(iterator position)
	{
		return iterator(base::erase(position));
	}

	template <class T, class Allocator>
	inline
	list<T*, Allocator>::iterator
	list<T*, Allocator>::erase(iterator position, iterator last)
	{
		return iterator(base::erase(position, last));
	}

	template <class T, class Allocator>
	inline
	void
	list<T*, Allocator>::swap(list<T*,Allocator>& x)
	{
		base::swap((base&)x);
	}

	template <class T, class Allocator>
	inline
	void
	list<T*, Allocator>::clear()
	{
		base::clear();
	}

	template <class T, class Allocator>
	inline
	void
	list<T*, Allocator>::splice(iterator position, list<T*,Allocator>& x)
	{
		base::splice(position, (base&)x);
	}

	template <class T, class Allocator>
	inline
	void
	list<T*, Allocator>::splice(iterator position, list<T*,Allocator>& x, iterator i)
	{
		base::splice(position, (base&)x, i);
	}

	template <class T, class Allocator>
	inline
	void
	list<T*, Allocator>::splice(iterator position, list<T*,Allocator>& x, iterator first, iterator last)
	{
		base::splice(position, (base&)x, first, last);
	}

	template <class T, class Allocator>
	inline
	void
	list<T*, Allocator>::remove(const value_type& value)
	{
		base::remove(value);
	}

	template <class T, class Allocator>
	inline
	void
	list<T*, Allocator>::unique()
	{
		base::unique();
	}

	template <class T, class Allocator>
	inline
	void
	list<T*, Allocator>::merge(list<T*, Allocator>& x)
	{
		base::merge((base&)x);
	}

	template <class T, class Allocator>
	inline
	void
	list<T*, Allocator>::sort()
	{
		base::sort();
	}

	template <class T, class Allocator>
	inline
	void
	list<T*, Allocator>::reverse()
	{
		base::reverse();
	}

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

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

#endif // defined(MSIPL_PARTIAL_SPECIALIZATION) && defined(MSIPL_MEMBER_TEMPLATE) && !defined(_Inhibit_Container_Optimization)

#ifdef MSIPL_USING_NAMESPACE
	} // namespace std
#endif

#if defined(__CFM68K__) && !defined(__USING_STATIC_LIBS__)
	#pragma import reset
#endif
#pragma options align=reset

#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)
