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

// cdeque

#ifndef _CDEQUE
#define _CDEQUE

// WARNING
//
// cdeque is a non-standard, non-portable header and container.
//
// WARNING
//
// It's purpose here is to aid in the implementation of deque.
// cdeque is very similar to deque except that it has capacity
// and reserve methods like vector.  It guarantees amoritized
// constant time push_front and push_back, but it may invalidate
// references (when capacity is increased) during these operations.
//
// cdeque is short for "circular deque".  It is implemented with
// a contiguous chunk of memory like vector.  vector elements always
// start at the low memory address, and there is an uninitialized chunk
// of reserve memory at the high end to grow into.  In contrast, cdeque
// maps the memory into a circular path.  The first element can start
// anywhere on the circle, and the reserve memory extends from beyond
// the last element up to the first element.  That is:
// In use     : [first, last)
// In reserve : [last, first)
//

/*  cdeque synopsis

namespace Metrowerks
{

template <class T, class Allocator = std::allocator<T> >
class cdeque
{
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;        // random access
	class const_iterator;  // random access

	typedef std::reverse_iterator<iterator>       reverse_iterator;
	typedef std::reverse_iterator<const_iterator> const_reverse_iterator;

	explicit cdeque(const allocator_type& a = allocator_type());
	explitic cdeque(size_type n, const value_type& value = value_type(),
	                const allocator_type& a = allocator_type());
	template <class InputIterator>
		cdeque(InputIterator first, InputIterator last,
		       const Allocator& a = allocator_type());
	cdeque(const cdeque& x);
	cdeque& operator=(const cdeque& x);
	~cdeque();

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

	size_type size() const;
	bool      empty() const;
	size_type capacity() const;
	void reserve(size_type n);

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

	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;

	reference       operator[](size_type n);
	const_reference operator[](size_type n) const;

	reference       at(size_type n);
	const_reference at(size_type n) const;

	void resize(size_type sz);
	void resize(size_type sz, const value_type& x);

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

	void push_front(const value_type& x);
	void push_back(const value_type& x);
	void pop_front();
	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);

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

	void swap(cdeque& x);

	bool invariants() const;
};

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

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

}  // Metrowerks

*/

#include <mslconfig>

#include <msl_utility>
#include <algorithm>
#include <iterator>
#include <msl_int_limits>
#include <memory>
#include <new>
#include <stdexcept>

#ifndef RC_INVOKED

#ifdef __MWERKS__
#pragma options align=native
#endif

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

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

#ifdef min
#undef min
#endif

#ifdef max
#undef max
#endif

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

template <class T, class Allocator>
class __cdeque_deleter_common
{
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;

	template <bool is_const>
	class generic_iterator
	{
		typedef typename select<is_const, const __cdeque_deleter_common*,
		                                        __cdeque_deleter_common*>::type cdeque_pointer;
	public:
		typedef typename __cdeque_deleter_common::value_type       value_type;
		typedef typename __cdeque_deleter_common::difference_type  difference_type;
		typedef typename select<is_const, typename __cdeque_deleter_common::const_pointer,
		                                  typename __cdeque_deleter_common::pointer>::type pointer;
		typedef typename select<is_const, typename __cdeque_deleter_common::const_reference,
		                                  typename __cdeque_deleter_common::reference>::type reference;
		typedef _STD::random_access_iterator_tag iterator_category;

		generic_iterator() {}
		generic_iterator(const generic_iterator<false>& i)
			: ptr_(i.ptr_), beg_(i.beg_), start_(i.start_), end_(i.end_) {}
		reference operator * () const {return *ptr_;}
		pointer operator -> () const  {return ptr_;}
		generic_iterator& operator ++ ()
			{
				if (++ptr_ == end_)
					ptr_ = beg_;
				return *this;
			}
		generic_iterator operator ++ (int) {generic_iterator tmp(*this); ++(*this); return tmp;}
		generic_iterator& operator -- ()
			{
				if (ptr_ == beg_)
					ptr_ = end_;
				--ptr_;
				return *this;
			}
		generic_iterator operator -- (int) {generic_iterator tmp(*this); --(*this); return tmp;}
		generic_iterator& operator += (difference_type n)
			{
				difference_type c = (difference_type)(end_ - beg_);
				n += ptr_ - beg_;
				if (n < 0)
					n += c;
				else if (n >= c)
					n -= c;
				ptr_ = beg_ + n;
				return *this;
			}
		generic_iterator operator + (difference_type n) const {return generic_iterator(*this) += n;}
		friend generic_iterator operator + (difference_type n, const generic_iterator& rhs)
			{return generic_iterator(rhs) += n;}
		generic_iterator& operator -= (difference_type n) {return *this += -n;}
		generic_iterator operator - (difference_type n) const {return generic_iterator(*this) -= n;}
		friend difference_type operator - (const generic_iterator& x, const generic_iterator& y)
			{
				pointer s = x.start_;
				difference_type result = x.ptr_ - y.ptr_;
				if (x.ptr_ >= s)
				{
					if (y.ptr_ < s)
						result -= (difference_type)(x.end_ - x.beg_);
				}
				else
				{
					if (y.ptr_ >= s)
						result += (difference_type)(x.end_ - x.beg_);
				}
				return result;
			}
		reference operator [] (difference_type i) const {return *(generic_iterator(*this) += i);}
		friend bool operator ==(const generic_iterator& x, const generic_iterator& y) {return x.ptr_ == y.ptr_;}
		friend bool operator !=(const generic_iterator& x, const generic_iterator& y) {return x.ptr_ != y.ptr_;}
		friend bool operator < (const generic_iterator& x, const generic_iterator& y)
			{
				pointer s = x.start_;
				if (x.ptr_ >= s)
				{
					if (y.ptr_ < s)
						return true;
				}
				else if (y.ptr_ >= s)
					return false;
				return x.ptr_ < y.ptr_;
			}
		friend bool operator <=(const generic_iterator& x, const generic_iterator& y)
			{return !(y < x);}
		friend bool operator > (const generic_iterator& x, const generic_iterator& y)
			{return y < x;}
		friend bool operator >=(const generic_iterator& x, const generic_iterator& y)
			{return !(x < y);}

	private:

#ifdef __GNUC__
		typedef typename 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 __cdeque_deleter_common;

		pointer ptr_;
		pointer beg_;
		pointer start_;
		pointer end_;

		generic_iterator(cdeque_pointer cdeq, pointer ptr)
			: ptr_(ptr), beg_(cdeq->data_), start_(beg_ + cdeq->start_), end_(beg_ + cdeq->cap()) {}
	};

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

	__cdeque_deleter_common()
		: capacity_(0), size_(0), start_(0), data_(0) {}
	explicit __cdeque_deleter_common(const allocator_type& a)
		: capacity_(a, 0), size_(0), start_(0), data_(0) {}

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

	iterator               begin()       {return       iterator(this, data_ + start_);}
	const_iterator         begin() const {return const_iterator(this, data_ + start_);}
	iterator               end()         {return       iterator(this, data_ + (cap() ? (start_ + size_) % cap() : 0));}
	const_iterator         end() const   {return const_iterator(this, data_ + (cap() ? (start_ + size_) % cap() : 0));}

	reference       operator[](size_type n)       {return *(data_ + (start_ + n) % cap());}
	const_reference operator[](size_type n) const {return *(data_ + (start_ + n) % cap());}
	reference       at(size_type n);
	const_reference at(size_type n) const;

	size_type max_size() const;
	size_type size() const {return size_;}
	bool      empty() const {return size_ == 0;}
	size_type capacity() const {return cap() == 0 ? 0 : cap() - 1;}
	size_type suggest_new_cap(size_type n) const;
	void swap(__cdeque_deleter_common& x);

	reference       front()       {return *(data_ + start_);}
	const_reference front() const {return *(data_ + start_);}
	reference       back()        {return *(data_ + (start_ + size_ - 1) % cap());}
	const_reference back() const  {return *(data_ + (start_ + size_ - 1) % cap());}

	compressed_pair<allocator_type, size_type> capacity_;
	size_type size_;
	size_type start_;
	pointer data_;

	allocator_type&       alloc()       {return capacity_.first();}
	const allocator_type& alloc() const {return capacity_.first();}
	size_type&            cap()         {return capacity_.second();}
	const size_type&      cap() const   {return capacity_.second();}

	bool invariants() const;
private:
	__cdeque_deleter_common(const __cdeque_deleter_common&);             // not defined
	__cdeque_deleter_common& operator=(const __cdeque_deleter_common&);  // not defined
};

// ES: strong
// invalidates no iterators.
template <class T, class Allocator>
typename __cdeque_deleter_common<T, Allocator>::reference
__cdeque_deleter_common<T, Allocator>::at(size_type n)
{
	if (n >= size_)
		_MSL_ERROR(_STD::out_of_range, "cdeque::at index out of range");
	return (*this)[n];
}

// ES: strong
// invalidates no iterators.
template <class T, class Allocator>
typename __cdeque_deleter_common<T, Allocator>::const_reference
__cdeque_deleter_common<T, Allocator>::at(size_type n) const
{
	if (n >= size_)
		_MSL_ERROR(_STD::out_of_range, "cdeque::at index out of range");
	return (*this)[n];
}

// ES: no throw
// invalidates no iterators.
template <class T, class Allocator>
typename __cdeque_deleter_common<T, Allocator>::size_type
__cdeque_deleter_common<T, Allocator>::max_size() const
{
	static size_type const ms = _STD::min(alloc().max_size(), _STD::numeric_limits<size_type>::max() / 2) - 1;
	return ms;
}

// ES: strong
// invalidates no iterators.
template <class T, class Allocator>
typename __cdeque_deleter_common<T, Allocator>::size_type
__cdeque_deleter_common<T, Allocator>::suggest_new_cap(size_type n) const
{
	const size_type m = max_size();
	if (n > m)
		_MSL_ERROR(_STD::length_error, "cdeque max_size error");
	size_type newcap = cap() != 0 ? cap() - 1 : 1;
	while (n > newcap)
		if (newcap < m/2)
			newcap *= 2;
		else
			newcap = m;
	return newcap;
}

// ES: no throw
// swaps iterators.
template <class T, class Allocator>
void
__cdeque_deleter_common<T, Allocator>::swap(__cdeque_deleter_common& x)
{
	if (this != &x)
	{
		Metrowerks::swap(capacity_, x.capacity_);
		_STD::swap(size_, x.size_);
		_STD::swap(start_, x.start_);
		_STD::swap(data_, x.data_);
	}
}

template <class T, class Allocator>
bool
__cdeque_deleter_common<T, Allocator>::invariants() const
{
	if (cap() > 0 && data_ == 0)
		return false;
	if (cap() == 0 && data_ != 0)
		return false;
	if (size_ > cap())
		return false;
	if (cap() > 0)
	{
		if (start_ >= cap())
			return false;
	}
	else if (start_ != 0)
		return false;
	return true;
}

template <class T, class Allocator, bool IsPOD> class __cdeque_deleter;
template <class T, class Allocator, bool IsPOD> class __cdeque_imp;

// __cdeque_deleter for non-PODs

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

	__cdeque_deleter() {}
	explicit __cdeque_deleter(const allocator_type& a) : base(a) {}
	~__cdeque_deleter();
	__cdeque_deleter& operator=(const __cdeque_deleter& x)
		{
			if (this != &x)
				do_assign(x.begin(), x.end(), _STD::random_access_iterator_tag());
			return *this;
		}

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

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

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

	void reserve(size_type n);
	void push_front(const value_type& x);
	void push_back(const value_type& x);
	void pop_front();
	void pop_back();
	void clear();

	iterator insert(iterator position, const value_type& x);
	void insert(iterator position, size_type n, const value_type& x);
	template <class InputIterator>
		void choose_insert(iterator position, InputIterator first, InputIterator last, int2type<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, int2type<false>)
			{do_insert(position, first, last, typename _STD::iterator_traits<InputIterator>::iterator_category());}

	iterator erase(iterator position);
	iterator erase(iterator first, iterator last);

	void resize(size_type sz);
	void resize(size_type sz, const value_type& x);

private:

	__cdeque_deleter(const __cdeque_deleter&);  // not defined
	template <class InputIterator>
		void do_assign(InputIterator first, InputIterator last, _STD::input_iterator_tag);
	template <class ForwardIterator>
		void do_assign(ForwardIterator first, ForwardIterator last, _STD::forward_iterator_tag);

	template <class InputIterator>
		void do_insert(iterator position, InputIterator first, InputIterator last, _STD::input_iterator_tag);
	template <class BidirectionalIterator>
		void do_insert(iterator position, BidirectionalIterator first, BidirectionalIterator last, _STD::bidirectional_iterator_tag);
};

// ES: no throw
// invalidates all iterators.
template <class T, class Allocator>
void
__cdeque_deleter<T, Allocator, false>::clear()
{
	if (base::data_ != 0)
	{
		pointer p, e;
		size_type const c = base::cap();
		allocator_type& a = base::alloc();
		size_type t = base::start_ + base::size_;
		if (t > c)
		{
			p = base::data_;
			e = p + (t - c);
			for (; p != e; ++p)
				a.destroy(p);
			t = c;
		}
		p = base::data_ + base::start_;
		e = base::data_ + t;
		for (; p != e; ++p)
			a.destroy(p);
		base::size_ = 0;
		base::start_ = 0;
	}
}

// ES: no throw
// invalidates all iterators.
template <class T, class Allocator>
__cdeque_deleter<T, Allocator, false>::~__cdeque_deleter()
{
	if (base::data_ != 0)
	{
		clear();
		base::alloc().deallocate(base::data_, base::cap());
	}
}

// ES: basic.  If T doesn't throw and capacity is not exceeded, no throw
// invalidates all iterators.
template <class T, class Allocator>
template <class InputIterator>
void
__cdeque_deleter<T, Allocator, false>::do_assign(InputIterator first, InputIterator last, _STD::input_iterator_tag)
{
	clear();
	for (; first != last; ++first)
		push_back(*first);
}

// ES: basic.  If T doesn't throw and capacity is not exceeded, no throw
// invalidates iterators if capacity exceeded.  iterator values are not stable
template <class T, class Allocator>
template <class ForwardIterator>
void
__cdeque_deleter<T, Allocator, false>::do_assign(ForwardIterator first, ForwardIterator last, _STD::forward_iterator_tag)
{
	size_type n = (size_type)_STD::distance(first, last);
	if (n <= base::capacity())
	{
		difference_type n1 = (difference_type)_STD::min(n, base::size_);
		iterator i = base::begin();
		iterator e = i + n1;
		for (; i < e; ++i, ++first)
			*i = *first;
		allocator_type& a = base::alloc();
		if (n < base::size_)
		{
			e = base::end();
			for (; i != e; ++i)
				a.destroy(&*i);
			base::size_ = n;
		}
		else if (base::size_ < n)
		{
			for (; first != last; ++i, ++first, ++base::size_)
				a.construct(&*i, *first);
		}
	}
	else
	{
		size_type newcap = base::suggest_new_cap(n);
		clear();
		if (base::data_)
		{
			base::alloc().deallocate(base::data_, base::cap());
			base::data_ = 0;
			base::cap() = 0;
		}
		base::data_ = base::alloc().allocate(newcap+1);
		base::cap() = newcap+1;
		for (pointer i = base::data_; first != last; ++first, ++i, ++base::size_)
			base::alloc().construct(i, *first);
	}
}

// ES: basic.  If T doesn't throw and capacity is not exceeded, no throw
// invalidates iterators if capacity exceeded.  iterator values are not stable
template <class T, class Allocator>
void
__cdeque_deleter<T, Allocator, false>::assign(size_type n, const value_type& u)
{
	if (n <= base::capacity())
	{
		difference_type n1 = (difference_type)_STD::min(n, base::size_);
		iterator i = base::begin();
		iterator e = i + n1;
		for (; i < e; ++i)
			*i = u;
		allocator_type& a = base::alloc();
		if (n < base::size_)
		{
			e = base::end();
			for (; i != e; ++i)
				a.destroy(&*i);
			base::size_ = n;
		}
		else if (base::size_ < n)
		{
			for (n -= base::size_; n > 0; --n, ++i, ++base::size_)
				a.construct(&*i, u);
		}
	}
	else
	{
		clear();
		size_type newcap = base::suggest_new_cap(n);
		if (base::data_)
		{
			base::alloc().deallocate(base::data_, base::cap());
			base::data_ = 0;
			base::cap() = 0;
		}
		base::data_ = base::alloc().allocate(newcap+1);
		base::cap() = newcap+1;
		for (pointer i = base::data_; n > 0; --n, ++i, ++base::size_)
			base::alloc().construct(i, u);
	}
}

// ES: strong
// invalidates all iterators if n > capacity().
template <class T, class Allocator>
void
__cdeque_deleter<T, Allocator, false>::reserve(size_type n)
{
	if (n > base::capacity())
	{
		if (n > base::max_size())
			_MSL_ERROR(_STD::length_error, "cdeque::reserve length error");
		__cdeque_deleter tmp(base::alloc());
		tmp.data_ = tmp.alloc().allocate(n+1);
		tmp.cap() = n+1;
		pointer p = tmp.data_;
		const_iterator e = base::end();
		for (const_iterator i = base::begin(); i < e; ++i, ++tmp.size_, ++p)
			tmp.alloc().construct(p, *i);
		tmp.swap(*this);
	}
}

// ES: strong.  If T doesn't throw and capacity is not exceeded, no throw
// invalidates iterators only if capacity exceeded.
template <class T, class Allocator>
void
__cdeque_deleter<T, Allocator, false>::push_front(const value_type& x)
{
	if (base::size_ < base::capacity())
	{
		size_type newstart = base::start_ != 0 ? base::start_ - 1 : base::cap() - 1;
		base::alloc().construct(base::data_ + newstart, x);
		++base::size_;
		base::start_ = newstart;
	}
	else // size_ + 1 > capacity()
	{
		size_type newcap = base::suggest_new_cap(base::size_ + 1);
		__cdeque_deleter tmp(base::alloc());
		tmp.data_ = tmp.alloc().allocate(newcap+1);
		tmp.cap() = newcap+1;
		pointer p = tmp.data_;
		tmp.alloc().construct(p++, x);
		++tmp.size_;
		const_iterator e = base::end();
		for (const_iterator i = base::begin(); i < e; ++i, ++tmp.size_, ++p)
			tmp.alloc().construct(p, *i);
		tmp.swap(*this);
	}
}

// ES: strong.  If T doesn't throw and capacity is not exceeded, no throw
// invalidates iterators only if capacity exceeded.
template <class T, class Allocator>
void
__cdeque_deleter<T, Allocator, false>::push_back(const value_type& x)
{
	if (base::size_ < base::capacity())
	{
		base::alloc().construct(&(*this)[base::size_], x);
		++base::size_;
	}
	else // size_ + 1 > capacity()
	{
		size_type newcap = base::suggest_new_cap(base::size_ + 1);
		__cdeque_deleter tmp(base::alloc());
		tmp.data_ = tmp.alloc().allocate(newcap+1);
		tmp.cap() = newcap+1;
		pointer p = tmp.data_;
		const_iterator e = base::end();
		for (const_iterator i = base::begin(); i < e; ++i, ++tmp.size_, ++p)
			tmp.alloc().construct(p, *i);
		tmp.alloc().construct(p, x);
		++tmp.size_;
		tmp.swap(*this);
	}
}

// ES: no throw
// invalidates no iterators.
template <class T, class Allocator>
void
__cdeque_deleter<T, Allocator, false>::pop_front()
{
	base::alloc().destroy(base::data_ + base::start_);
	--base::size_;
	if (++base::start_ == base::cap())
		base::start_ = 0;
}

// ES: no throw
// invalidates no iterators.
template <class T, class Allocator>
void
__cdeque_deleter<T, Allocator, false>::pop_back()
{
	base::alloc().destroy(base::data_ + (base::start_ + base::size_ - 1) % base::cap());
	--base::size_;
}

// ES: basic.  If capacity is exceeded, strong.  If T doesn't throw and capacity is not exceeded, no throw.
// invalidates all iterators.
template <class T, class Allocator>
typename __cdeque_deleter<T, Allocator, false>::iterator
__cdeque_deleter<T, Allocator, false>::insert(iterator position, const value_type& x)
{
	if (base::size_ < base::capacity())
	{
		iterator b = base::begin();
		size_type pb = size_type(position - b);
		size_type pe = base::size_ - pb;
		if (pb < pe)
		{
			--b;
			if (pb == 0)
			{
				base::alloc().construct(&*b, x);
				base::start_ = size_type(&*b - base::data_);
				++base::size_;
				return b;
			}
			base::alloc().construct(&*b, *(base::data_ + base::start_));
			base::start_ = size_type(&*b - base::data_);
			++base::size_;
			const value_type& xr = (base::data_ <= &x && &x < base::data_ + base::cap()) ?
			                       value_type(x) : x;
			++b;
			if (pb > 1)
				b = _STD::copy(b + 1, b + (difference_type)pb, b);
			*b = xr;
			return b;
		}
		else // pos >= size_ / 2
		{
			b = base::end();
			if (pe == 0)
			{
				base::alloc().construct(&*b, x);
				++base::size_;
				return b;
			}
			base::alloc().construct(&*b, b[-1]);
			++base::size_;
			const value_type& xr = (base::data_ <= &x && &x < base::data_ + base::cap()) ?
			                       value_type(x) : x;
			if (pe > 1)
				b = _STD::copy_backward(b - difference_type(pe), b - 1, b);
			*--b = xr;
			return b;
		}
	}
	else // size_ + n > capacity()
	{
		difference_type pos = position - base::begin();
		size_type newcap = base::suggest_new_cap(base::size_ + 1);
		__cdeque_deleter tmp(base::alloc());
		tmp.data_ = tmp.alloc().allocate(newcap+1);
		tmp.cap() = newcap+1;
		pointer p = tmp.data_;
		const_iterator i = base::begin();
		for (; i < position; ++i, ++tmp.size_, ++p)
			tmp.alloc().construct(p, *i);
		tmp.alloc().construct(p, x);
		++tmp.size_;
		++p;
		const_iterator e = base::end();
		for (; i < e; ++i, ++tmp.size_, ++p)
			tmp.alloc().construct(p, *i);
		tmp.swap(*this);
		return base::begin() + pos;
	}
}

// ES: basic.  If capacity is exceeded, strong.  If T doesn't throw and capacity is not exceeded, no throw.
// invalidates all iterators.
template <class T, class Allocator>
void
__cdeque_deleter<T, Allocator, false>::insert(iterator position, size_type n, const value_type& x)
{
	if (n == 0)
		return;
	if (base::size_ + n <= base::capacity())
	{
		iterator b = base::begin();
		size_type pb = size_type(position - b);
		size_type pe = base::size_ - pb;
		const value_type& xr = (base::data_ <= &x && &x < base::data_ + base::cap()) ?
		                       value_type(x) : x;
		if (pb < pe)
		{
			{
			for (size_type i = pb; i < n; ++i)
			{
				--b;
				base::alloc().construct(&*b, xr);
				base::start_ = size_type(&*b - base::data_);
				++base::size_;
			}
			}
			size_type e = _STD::min(pb, n);
			{
			for (size_type i = 0; i < e; ++i)
			{
				--b;
				base::alloc().construct(&*b, b[(difference_type)n]);
				base::start_ = size_type(&*b - base::data_);
				++base::size_;
			}
			}
			b += (difference_type)n;
			if (pb > n)
				b = _STD::copy(b + (difference_type)n, b + (difference_type)pb, b);
			_STD::fill_n(b, e, xr);
		}
		else // pos >= size_ / 2
		{
			b = base::end();
			{
			for (size_type i = pe; i < n; ++i, ++b)
			{
				base::alloc().construct(&*b, xr);
				++base::size_;
			}
			}
			size_type e = _STD::min(pe, n);
			{
			for (size_type i = 0; i < e; ++i, ++b)
			{
				base::alloc().construct(&*b, b[-difference_type(n)]);
				++base::size_;
			}
			}
			b -= (difference_type)n;
			if (pe > n)
				b = _STD::copy_backward(b - difference_type(pe), b - difference_type(n), b);
			for (; e > 0; --e)
				*--b = xr;
		}
	}
	else // size_ + n > capacity()
	{
		size_type newcap = base::suggest_new_cap(base::size_ + n);
		__cdeque_deleter tmp(base::alloc());
		tmp.data_ = tmp.alloc().allocate(newcap+1);
		tmp.cap() = newcap+1;
		pointer p = tmp.data_;
		const_iterator i = base::begin();
		for (; i < position; ++i, ++tmp.size_, ++p)
			tmp.alloc().construct(p, *i);
		for (; n > 0; --n, ++tmp.size_, ++p)
			tmp.alloc().construct(p, x);
		const_iterator e = base::end();
		for (; i < e; ++i, ++tmp.size_, ++p)
			tmp.alloc().construct(p, *i);
		tmp.swap(*this);
	}
}

// ES: basic.  If capacity is exceeded, strong.  If T doesn't throw and capacity is not exceeded, no throw.
// invalidates all iterators.
template <class T, class Allocator>
template <class InputIterator>
void
__cdeque_deleter<T, Allocator, false>::do_insert(iterator position, InputIterator first, InputIterator last, _STD::input_iterator_tag)
{
	__cdeque_deleter tmp(base::get_allocator());
	tmp.assign(first, last);
	do_insert(position, tmp.begin(), tmp.end(), _STD::random_access_iterator_tag());
}

// ES: basic.  If capacity is exceeded, strong.  If T doesn't throw and capacity is not exceeded, no throw.
// invalidates all iterators.
template <class T, class Allocator>
template <class BidirectionalIterator>
void
__cdeque_deleter<T, Allocator, false>::do_insert(iterator position, BidirectionalIterator first, BidirectionalIterator last, _STD::bidirectional_iterator_tag)
{
	size_type n = (size_type)_STD::distance(first, last);
	if (n == 0)
		return;
	if (base::size_ + n <= base::capacity())
	{
		iterator b = base::begin();
		size_type pb = size_type(position - b);
		size_type pe = base::size_ - pb;
		if (pb < pe)
		{
			if (n > pb)
			{
				_STD::advance(first, difference_type(n-pb));
				BidirectionalIterator it = first;
				for (size_type i = pb; i < n; ++i)
				{
					--b;
					base::alloc().construct(&*b, *--it);
					base::start_ = size_type(&*b - base::data_);
					++base::size_;
				}
			}
			size_type e = _STD::min(pb, n);
			for (size_type i = 0; i < e; ++i)
			{
				--b;
				base::alloc().construct(&*b, b[(difference_type)n]);
				base::start_ = size_type(&*b - base::data_);
				++base::size_;
			}
			b += (difference_type)n;
			if (pb > n)
				b = _STD::copy(b + (difference_type)n, b + (difference_type)pb, b);
			_STD::copy(first, last, b);
		}
		else // pos >= size_ / 2
		{
			b = base::end();
			if (pe < n)
			{
				BidirectionalIterator it = first;
				_STD::advance(it, difference_type(pe));
				last = it;
				for (size_type i = pe; i < n; ++i, ++b, ++it)
				{
					base::alloc().construct(&*b, *it);
					++base::size_;
				}
			}
			size_type e = _STD::min(pe, n);
			for (size_type i = 0; i < e; ++i, ++b)
			{
				base::alloc().construct(&*b, b[-difference_type(n)]);
				++base::size_;
			}
			b -= (difference_type)n;
			if (pe > n)
				b = _STD::copy_backward(b - difference_type(pe), b - difference_type(n), b);
			_STD::copy_backward(first, last, b);
		}
	}
	else // size_ + n > capacity()
	{
		size_type newcap = base::suggest_new_cap(base::size_ + n);
		__cdeque_deleter tmp(base::alloc());
		tmp.data_ = tmp.alloc().allocate(newcap+1);
		tmp.cap() = newcap+1;
		pointer p = tmp.data_;
		const_iterator i = base::begin();
		for (; i < position; ++i, ++tmp.size_, ++p)
			tmp.alloc().construct(p, *i);
		for (; n > 0; --n, ++tmp.size_, ++p, ++first)
			tmp.alloc().construct(p, *first);
		const_iterator e = base::end();
		for (; i < e; ++i, ++tmp.size_, ++p)
			tmp.alloc().construct(p, *i);
		tmp.swap(*this);
	}
}

// ES: basic.  If T doesn't throw, no throw.
// invalidates all iterators.
template <class T, class Allocator>
typename __cdeque_deleter<T, Allocator, false>::iterator
__cdeque_deleter<T, Allocator, false>::erase(iterator position)
{
	iterator beg = base::begin();
	iterator e = base::end();
	size_type pb = size_type(position - beg);
	size_type pe = size_type(e - position) - 1;
	if (pb < pe)   // erase from begin
	{
		_STD::copy_backward(beg, position, position+1);
		base::alloc().destroy(base::data_ + base::start_);
		base::start_ = (base::start_ + 1) % base::cap();
	}
	else  // pb >= pe - erase from end
	{
		_STD::copy(position+1, e, position);
		base::alloc().destroy(base::data_ + (base::start_ + base::size_ - 1) % base::cap());
	}
	--base::size_;
	return base::begin() + difference_type(pb);
}

// ES: basic.  If T doesn't throw, no throw.
// invalidates all iterators.
template <class T, class Allocator>
typename __cdeque_deleter<T, Allocator, false>::iterator
__cdeque_deleter<T, Allocator, false>::erase(iterator first, iterator last)
{
	if (first == last)
		return first;
	iterator beg = base::begin();
	iterator e = base::end();
	size_type pb = size_type(first - beg);
	size_type pe = size_type(e - last);
	size_type diff = size_type(last - first);
	if (pb < pe)   // erase from begin
	{
		_STD::copy_backward(beg, first, last);
		e = beg + difference_type(diff);
		for (first = beg; first != e; ++first)
			base::alloc().destroy(&*first);
		base::start_ = (base::start_ + diff) % base::cap();
	}
	else  // pb >= pe - erase from end
	{
		_STD::copy(last, e, first);
		for (first += difference_type(pe); first != e; ++first)
			base::alloc().destroy(&*first);
	}
	base::size_ -= diff;
	return base::begin() + difference_type(pb);
}

// ES: basic.  If capacity is exceeded, strong.  If T doesn't throw, strong.  If T doesn't throw and size doesn't grow, no throw
// invalidates all iterators.
template <class T, class Allocator>
void
__cdeque_deleter<T, Allocator, false>::resize(size_type sz)
{
	if (sz > base::size_)
		insert(base::end(), sz-base::size_, value_type());
	else if (sz < base::size_)
	{
		if (sz)
			erase(base::begin() + difference_type(sz), base::end());
		else
			clear();
	}
}

// ES: basic.  If capacity is exceeded, strong.  If T doesn't throw, strong.  If T doesn't throw and size doesn't grow, no throw
// invalidates all iterators.
template <class T, class Allocator>
void
__cdeque_deleter<T, Allocator, false>::resize(size_type sz, const value_type& x)
{
	if (sz > base::size_)
		insert(base::end(), sz-base::size_, x);
	else if (sz < base::size_)
	{
		if (sz)
			erase(base::begin() + difference_type(sz), base::end());
		else
			clear();
	}
}

// __cdeque_imp for non-PODS

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

	__cdeque_imp() {}
	explicit __cdeque_imp(const allocator_type& a) : base(a) {}
	explicit __cdeque_imp(size_type n) {init(n, value_type());}
	__cdeque_imp(size_type n, const value_type& value) {init(n, value);}
	__cdeque_imp(size_type n, const value_type& value, const allocator_type& a)
		: base(a) {init(n, value);}
	__cdeque_imp(const __cdeque_imp& x) : base(x.alloc())
		{init(x.begin(), x.end(), _STD::random_access_iterator_tag());}

	template <class InputIterator>
		void choose_init(InputIterator first, InputIterator last, int2type<true>)
			{init(static_cast<size_type>(first), static_cast<value_type>(last));}

	template <class InputIterator>
		void choose_init(InputIterator first, InputIterator last, int2type<false>)
			{init(first, last, typename _STD::iterator_traits<InputIterator>::iterator_category());}

private:
	void init(size_type n, const value_type& value);
	template <class InputIterator>
		void init(InputIterator first, InputIterator last, _STD::input_iterator_tag);
	template <class ForwardIterator>
		void init(ForwardIterator first, ForwardIterator last, _STD::forward_iterator_tag);
};

// ES: strong
// invalidates all iterators.
template <class T, class Allocator>
void
__cdeque_imp<T, Allocator, false>::init(size_type n, const value_type& value)
{
	if (n > 0)
	{
		if (n > base::max_size())
			_MSL_ERROR(_STD::length_error, "cdeque::construction length error");
		base::data_ = base::alloc().allocate(n+1);
		base::cap() = n+1;
		for (pointer p = base::data_; n > 0; --n, ++p, ++base::size_)
			base::alloc().construct(p, value);
	}
}

// ES: strong
// invalidates all iterators.
template <class T, class Allocator>
template <class InputIterator>
void
__cdeque_imp<T, Allocator, false>::init(InputIterator first, InputIterator last, _STD::input_iterator_tag)
{
	for (; first != last; ++first)
		base::push_back(*first);
}

// ES: strong
// invalidates all iterators.
template <class T, class Allocator>
template <class ForwardIterator>
void
__cdeque_imp<T, Allocator, false>::init(ForwardIterator first, ForwardIterator last, _STD::forward_iterator_tag)
{
	size_type c = (size_type)_STD::distance(first, last);
	if (c > 0)
	{
		if (c > base::max_size())
			_MSL_ERROR(_STD::length_error, "cdeque::construction length error");
		pointer p = base::data_ = base::alloc().allocate(c+1);
		base::cap() = c+1;
		for (; first != last; ++first, ++base::size_, ++p)
			base::alloc().construct(p, *first);
	}
}

// __cdeque_deleter for PODs

#ifndef _Inhibit_Container_Optimization

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

	__cdeque_deleter() {}
	explicit __cdeque_deleter(const allocator_type& a) : base(a) {}
	~__cdeque_deleter();
	__cdeque_deleter& operator=(const __cdeque_deleter& x)
		{
			if (this != &x)
				do_assign(x.begin(), x.end(), _STD::random_access_iterator_tag());
			return *this;
		}

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

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

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

	void reserve(size_type n);
	void push_front(const value_type& x);
	void push_back(const value_type& x);
	void pop_front();
	void pop_back();
	void clear();

	iterator insert(iterator position, const value_type& x);
	void insert(iterator position, size_type n, const value_type& x);
	template <class InputIterator>
		void choose_insert(iterator position, InputIterator first, InputIterator last)
			{do_insert(position, first, last, typename _STD::iterator_traits<InputIterator>::iterator_category());}

	iterator erase(iterator position);
	iterator erase(iterator first, iterator last);

	void resize(size_type sz);
	void resize(size_type sz, const value_type& x);

private:

	__cdeque_deleter(const __cdeque_deleter&);  // not defined
	template <class InputIterator>
		void do_assign(InputIterator first, InputIterator last, _STD::input_iterator_tag);
	template <class ForwardIterator>
		void do_assign(ForwardIterator first, ForwardIterator last, _STD::forward_iterator_tag);

	template <class InputIterator>
		void do_insert(iterator position, InputIterator first, InputIterator last, _STD::input_iterator_tag);
	template <class ForwardIterator>
		void do_insert(iterator position, ForwardIterator first, ForwardIterator last, _STD::forward_iterator_tag);
};

// ES: strong
// invalidates all iterators.
template <class T, class Allocator>
void
__cdeque_deleter<T, Allocator, true>::init(size_type n, const value_type& value)
{
	if (n > 0)
	{
		if (n > base::max_size())
			_MSL_ERROR(_STD::length_error, "cdeque::construction length error");
		base::data_ = base::alloc().allocate(n+1);
		base::cap() = n+1;
		base::size_ = n;
		_STD::fill_n(base::data_, n, value);
	}
}

// ES: strong
// invalidates all iterators.
template <class T, class Allocator>
template <class ForwardIterator>
void
__cdeque_deleter<T, Allocator, true>::init(ForwardIterator first, ForwardIterator last)
{
	base::size_ = (size_type)_STD::distance(first, last);
	if (base::size_ > 0)
	{
		if (base::size_ > base::max_size())
			_MSL_ERROR(_STD::length_error, "cdeque::construction length error");
		base::cap() = base::size_ + 1;
		base::data_ = base::alloc().allocate(base::cap());
		_STD::copy(first, last, base::data_);
	}
}

// ES: no throw
// invalidates all iterators.
template <class T, class Allocator>
inline
void
__cdeque_deleter<T, Allocator, true>::clear()
{
	base::size_ = 0;
	base::start_ = 0;
}

// ES: no throw
// invalidates all iterators.
template <class T, class Allocator>
inline
__cdeque_deleter<T, Allocator, true>::~__cdeque_deleter()
{
	if (base::data_ != 0)
		base::alloc().deallocate(base::data_, base::cap());
}

// ES: basic.
// invalidates all iterators.
template <class T, class Allocator>
template <class InputIterator>
void
__cdeque_deleter<T, Allocator, true>::do_assign(InputIterator first, InputIterator last, _STD::input_iterator_tag)
{
	clear();
	for (; first != last; ++first)
		push_back(*first);
}

// ES: basic.
// invalidates all iterators.
template <class T, class Allocator>
template <class ForwardIterator>
void
__cdeque_deleter<T, Allocator, true>::do_assign(ForwardIterator first, ForwardIterator last, _STD::forward_iterator_tag)
{
	size_type n = (size_type)_STD::distance(first, last);
	clear();
	if (n > base::capacity())
	{
		size_type newcap = base::suggest_new_cap(n);
		if (base::data_)
		{
			base::alloc().deallocate(base::data_, base::cap());
			base::data_ = 0;
			base::cap() = 0;
		}
		base::data_ = base::alloc().allocate(newcap+1);
		base::cap() = newcap+1;
	}
	_STD::copy(first, last, base::data_);
	base::size_ = n;
}

// ES: basic.  No throw if capacity not exceeded.
// invalidates all iterators.
template <class T, class Allocator>
void
__cdeque_deleter<T, Allocator, true>::assign(size_type n, const value_type& u)
{
	clear();
	if (n > base::capacity())
	{
		size_type newcap = base::suggest_new_cap(n);
		if (base::data_)
		{
			base::alloc().deallocate(base::data_, base::cap());
			base::data_ = 0;
			base::cap() = 0;
		}
		base::data_ = base::alloc().allocate(newcap+1);
		base::cap() = newcap+1;
	}
	_STD::fill_n(base::data_, n, u);
	base::size_ = n;
}

// ES: strong
// invalidates all iterators.
template <class T, class Allocator>
void
__cdeque_deleter<T, Allocator, true>::reserve(size_type n)
{
	if (n > base::capacity())
	{
		if (n > base::max_size())
			_MSL_ERROR(_STD::length_error, "cdeque::reserve length error");
		pointer newdata = base::alloc().allocate(n+1);
		if (base::data_)
		{
			_STD::copy(base::begin(), base::end(), newdata);
			base::alloc().deallocate(base::data_, base::cap());
		}
		base::data_ = newdata;
		base::cap() = n+1;
		base::start_ = 0;
	}
}

// ES: strong.  If capacity is not exceeded, no throw
// invalidates iterators only if capacity exceeded.
template <class T, class Allocator>
void
__cdeque_deleter<T, Allocator, true>::push_front(const value_type& x)
{
	if (base::size_ < base::capacity())
	{
		base::start_ = base::start_ != 0 ? base::start_ - 1 : base::cap() - 1;
		*(base::data_ + base::start_) = x;
		++base::size_;
	}
	else // size_ + 1 > capacity()
	{
		size_type newcap = base::suggest_new_cap(base::size_ + 1);
		pointer newdata = base::alloc().allocate(newcap+1);
		*newdata = x;
		if (base::data_)
		{
			_STD::copy(base::begin(), base::end(), newdata+1);
			base::alloc().deallocate(base::data_, base::cap());
		}
		base::data_ = newdata;
		base::cap() = newcap+1;
		base::start_ = 0;
		++base::size_;
	}
}

// ES: strong.  If capacity is not exceeded, no throw
// invalidates iterators only if capacity exceeded.
template <class T, class Allocator>
void
__cdeque_deleter<T, Allocator, true>::push_back(const value_type& x)
{
	if (base::size_ < base::capacity())
	{
		(*this)[base::size_++] = x;
	}
	else // size_ + 1 > capacity()
	{
		size_type newcap = base::suggest_new_cap(base::size_ + 1);
		pointer newdata = base::alloc().allocate(newcap+1);
		*_STD::copy(base::begin(), base::end(), newdata) = x;
		if (base::data_)
			base::alloc().deallocate(base::data_, base::cap());
		base::data_ = newdata;
		base::cap() = newcap+1;
		base::start_ = 0;
		++base::size_;
	}
}

// ES: no throw
// invalidates no iterators.
template <class T, class Allocator>
void
__cdeque_deleter<T, Allocator, true>::pop_front()
{
	--base::size_;
	if (++base::start_ == base::cap())
		base::start_ = 0;
}

// ES: no throw
// invalidates no iterators.
template <class T, class Allocator>
inline
void
__cdeque_deleter<T, Allocator, true>::pop_back()
{
	--base::size_;
}

// ES: strong.  If capacity is not exceeded, no throw.
// invalidates all iterators.
template <class T, class Allocator>
inline
typename __cdeque_deleter<T, Allocator, true>::iterator
__cdeque_deleter<T, Allocator, true>::insert(iterator position, const value_type& x)
{
	difference_type pos = position - base::begin();
	insert(position, 1, x);
	return base::begin() + pos;
}

// ES: strong.  If capacity is not exceeded, no throw.
// invalidates all iterators.
template <class T, class Allocator>
void
__cdeque_deleter<T, Allocator, true>::insert(iterator position, size_type n, const value_type& x)
{
	if (n == 0)
		return;
	if (base::size_ + n <= base::capacity())
	{
		iterator b = base::begin();
		size_type pb = size_type(position - b);
		size_type pe = base::size_ - pb;
		const value_type& xr = (base::data_ <= &x && &x < base::data_ + base::cap()) ?
		                       value_type(x) : x;
		if (pb < pe)
		{
			iterator first = b;
			b -= difference_type(n);
			base::start_ = size_type(&*b - base::data_);
			base::size_ += n;
			if (pb > 0)
				b = _STD::copy(first, first + (difference_type)pb, b);
			_STD::fill_n(b, n, xr);
		}
		else // pos >= size_ / 2
		{
			base::size_ += n;
			b = base::end();
			if (pe > 0)
				b = _STD::copy_backward(b - difference_type(n+pe), b - difference_type(n), b);
			for (; n > 0; --n)
				*--b = xr;
		}
	}
	else // size_ + n > capacity()
	{
		size_type newcap = base::suggest_new_cap(base::size_ + n);
		pointer newdata = base::alloc().allocate(newcap+1);
		pointer p = _STD::copy(base::begin(), position, newdata);
		_STD::fill_n(p, n, x);
		p += n;
		if (base::data_)
		{
			_STD::copy(position, base::end(), p);
			base::alloc().deallocate(base::data_, base::cap());
		}
		base::data_ = newdata;
		base::cap() = newcap+1;
		base::start_ = 0;
		base::size_ += n;
	}
}

// ES: strong.  If capacity is not exceeded, no throw.
// invalidates all iterators.
template <class T, class Allocator>
template <class InputIterator>
void
__cdeque_deleter<T, Allocator, true>::do_insert(iterator position, InputIterator first, InputIterator last, _STD::input_iterator_tag)
{
	__cdeque_deleter tmp(base::get_allocator());
	tmp.choose_assign(first, last);
	do_insert(position, tmp.begin(), tmp.end(), _STD::random_access_iterator_tag());
}

// ES: strong.  If capacity is not exceeded, no throw.
// invalidates all iterators.
template <class T, class Allocator>
template <class ForwardIterator>
void
__cdeque_deleter<T, Allocator, true>::do_insert(iterator position, ForwardIterator first, ForwardIterator last, _STD::forward_iterator_tag)
{
	size_type n = (size_type)_STD::distance(first, last);
	if (n == 0)
		return;
	if (base::size_ + n <= base::capacity())
	{
		iterator b = base::begin();
		size_type pb = size_type(position - b);
		size_type pe = base::size_ - pb;
		if (pb < pe)
		{
			iterator b1 = b;
			b -= difference_type(n);
			base::start_ = size_type(&*b - base::data_);
			base::size_ += n;
			if (pb > 0)
				b = _STD::copy(b1, b1 + difference_type(pb), b);
		}
		else // pos >= size_ / 2
		{
			base::size_ += n;
			b = base::end();
			if (pe > 0)
				b = _STD::copy_backward(b - difference_type(n+pe), b - difference_type(n), b);
			b -= difference_type(n);
		}
		_STD::copy(first, last, b);
	}
	else // size_ + n > capacity()
	{
		size_type newcap = base::suggest_new_cap(base::size_ + n);
		pointer newdata = base::alloc().allocate(newcap+1);
		pointer p = _STD::copy(base::begin(), position, newdata);
		p = _STD::copy(first, last, p);
		if (base::data_)
		{
			_STD::copy(position, base::end(), p);
			base::alloc().deallocate(base::data_, base::cap());
		}
		base::data_ = newdata;
		base::cap() = newcap+1;
		base::start_ = 0;
		base::size_ += n;
	}
}

// ES: no throw
// invalidates all iterators.
template <class T, class Allocator>
inline
typename __cdeque_deleter<T, Allocator, true>::iterator
__cdeque_deleter<T, Allocator, true>::erase(iterator position)
{
	return erase(position, position+1);
}

// ES: no throw
// invalidates all iterators.
template <class T, class Allocator>
typename __cdeque_deleter<T, Allocator, true>::iterator
__cdeque_deleter<T, Allocator, true>::erase(iterator first, iterator last)
{
	if (first == last)
		return first;
	iterator beg = base::begin();
	iterator e = base::end();
	size_type pb = size_type(first - beg);
	size_type pe = size_type(e - last);
	size_type diff = size_type(last - first);
	if (pb < pe)   // erase from begin
	{
		_STD::copy_backward(beg, first, last);
		base::start_ = (base::start_ + diff) % base::cap();
	}
	else  // pb >= pe - erase from end
		_STD::copy(last, e, first);
	base::size_ -= diff;
	return base::begin() + difference_type(pb);
}

// ES: strong.  If size doesn't grow, no throw
// invalidates all iterators.
template <class T, class Allocator>
void
__cdeque_deleter<T, Allocator, true>::resize(size_type sz)
{
	if (sz > base::size_)
		insert(base::end(), sz-base::size_, value_type());
	else if (sz < base::size_)
	{
		if (sz)
			erase(base::begin() + difference_type(sz), base::end());
		else
			clear();
	}
}

// ES: strong.  If size doesn't grow, no throw
// invalidates all iterators.
template <class T, class Allocator>
void
__cdeque_deleter<T, Allocator, true>::resize(size_type sz, const value_type& x)
{
	if (sz > base::size_)
		insert(base::end(), sz-base::size_, x);
	else if (sz < base::size_)
	{
		if (sz)
			erase(base::begin() + difference_type(sz), base::end());
		else
			clear();
	}
}

// __cdeque_imp for PODS

template <class T, class Allocator>
class __cdeque_imp<T, Allocator, true>
	: public __cdeque_deleter<typename store_as<T>::type,
	                          typename Allocator::rebind<typename store_as<T>::type>::other, true>,
	  private compile_assert<bool(sizeof(T) == sizeof(typename store_as<T>::type))>
{
	typedef __cdeque_deleter<typename store_as<T>::type,
	                         typename Allocator::rebind<typename store_as<T>::type>::other, true> base;
	typedef typename base::allocator_type base_allocator;
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;

	template <bool is_const>
	class generic_iterator
	{
		typedef typename select<is_const, typename __cdeque_imp::base::const_iterator,
		                                  typename __cdeque_imp::base::iterator>::type base_iterator;
	public:
		typedef typename __cdeque_imp::value_type       value_type;
		typedef typename __cdeque_imp::difference_type  difference_type;
		typedef typename select<is_const, typename __cdeque_imp::const_pointer,
		                                  typename __cdeque_imp::pointer>::type pointer;
		typedef typename select<is_const, typename __cdeque_imp::const_reference,
		                                  typename __cdeque_imp::reference>::type reference;
		typedef _STD::random_access_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); ++(*this); return tmp;}
		generic_iterator& operator -- () {--i_; return *this;}
		generic_iterator operator -- (int) {generic_iterator tmp(*this); --(*this); return tmp;}
		generic_iterator& operator += (difference_type n) {i_ += n; return *this;}
		generic_iterator operator + (difference_type n) const {return generic_iterator(*this) += n;}
		friend generic_iterator operator + (difference_type n, const generic_iterator& rhs)
			{return generic_iterator(rhs) += n;}
		generic_iterator& operator -= (difference_type n) {return *this += -n;}
		generic_iterator operator - (difference_type n) const {return generic_iterator(*this) -= n;}
		friend difference_type operator - (const generic_iterator& x, const generic_iterator& y) {return difference_type(x.i_ - y.i_);}
		reference operator [] (difference_type i) const {return reference(i_[i]);}
		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_;}
		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_;}
		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_;}

	private:

		friend class generic_iterator<true>;
		friend class __cdeque_imp;

		base_iterator i_;

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

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

	__cdeque_imp() {}
	explicit __cdeque_imp(const allocator_type& a) : base(a) {}
	explicit __cdeque_imp(size_type n) {init(n, value_type());}
	__cdeque_imp(size_type n, const value_type& value) {init(n, value);}
	__cdeque_imp(size_type n, const value_type& value, const allocator_type& a)
		: base(a) {init(n, value);}
	__cdeque_imp(const __cdeque_imp& x) : base(x.alloc())
		{init(x.begin(), x.end(), _STD::random_access_iterator_tag());}

	template <class Integral>
		void choose_init(Integral first, Integral last, int2type<true>)
			{init(static_cast<size_type>(first), (value_type)(last));}

	template <class InputIterator>
		void choose_init(InputIterator first, InputIterator last, int2type<false>)
			{init(first, last, typename _STD::iterator_traits<InputIterator>::iterator_category());}

	template <class InputIterator>
		void choose_assign(InputIterator first, InputIterator last, int2type<true>)
			{assign(static_cast<size_type>(first), (value_type)last);}
	template <class InputIterator>
		void choose_assign(InputIterator first, InputIterator last, int2type<false>)
			{
				typedef typename _STD::iterator_traits<InputIterator>::value_type outside_value;
				choose_assign(first, last, int2type<is_same<outside_value, value_type>::value>(),
				                           int2type<is_same<value_type, typename base::value_type>::value>());
			}
	void assign(size_type n, const value_type& u) {base::assign(n, (const typename base::value_type&)u);}

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

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

	reference       operator[](size_type n)       {return       reference(base::operator[](n));}
	const_reference operator[](size_type n) const {return const_reference(base::operator[](n));}
	reference       at(size_type n)               {return       reference(base::at(n));}
	const_reference at(size_type n) const         {return const_reference(base::at(n));}

	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());}

	void push_front(const value_type& value) {base::push_front((const typename base::value_type&)value);}
	void push_back( const value_type& value) {base::push_back( (const typename base::value_type&)value);}

	iterator insert(iterator position, const value_type& x)
		{return base::insert(position, (const typename base::value_type&)x);}
	void insert(iterator position, size_type n, const value_type& x)
		{base::insert(position, n, (const typename base::value_type&)x);}
	template <class InputIterator>
		void choose_insert(iterator position, InputIterator first, InputIterator last, int2type<true>)
			{insert(position, static_cast<size_type>(first), (value_type)last);}
	template <class InputIterator>
		void choose_insert(iterator position, InputIterator first, InputIterator last, int2type<false>)
			{
				typedef typename _STD::iterator_traits<InputIterator>::value_type outside_value;
				choose_insert(position, first, last, int2type<is_same<outside_value, value_type>::value>(),
				                                     int2type<is_same<value_type, typename base::value_type>::value>());
			}

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

	void resize(size_type sz)                      {base::resize(sz);}
	void resize(size_type sz, const value_type& x) {base::resize(sz, (const typename base::value_type&)x);}

private:
	template <class ForwardIterator>
		void choose_init(ForwardIterator first, ForwardIterator last, int2type<true>, int2type<true>)
			{base::init(first, last);}
	template <class ForwardIterator>
		void choose_init(ForwardIterator first, ForwardIterator last, int2type<false>, int2type<true>)
			{
				typedef _STD::__convert_iterator<_STD::__implicit_convert<pointer, ForwardIterator> > first_convert;
				base::init(first_convert(first), first_convert(last));
			}
	template <class ForwardIterator>
		void choose_init(ForwardIterator first, ForwardIterator last, int2type<true>, int2type<false>)
			{
				typedef _STD::__convert_iterator<_STD::__reinterpret_convert<typename base::pointer, ForwardIterator> > second_convert;
				base::init(second_convert(first), second_convert(last));
			}
	template <class ForwardIterator>
		void choose_init(ForwardIterator first, ForwardIterator last, int2type<false>, int2type<false>)
			{
				typedef _STD::__convert_iterator<_STD::__implicit_convert<pointer, ForwardIterator> > first_convert;
				typedef _STD::__convert_iterator<_STD::__reinterpret_convert<typename base::pointer, first_convert> > second_convert;
				base::init(second_convert(first_convert(first)), second_convert(first_convert(last)));
			}

	void init(size_type n, const value_type& value) {base::init(n, (const typename base::value_type&)value);}
	template <class InputIterator>
		void init(InputIterator first, InputIterator last, _STD::input_iterator_tag);
	template <class ForwardIterator>
		void init(ForwardIterator first, ForwardIterator last, _STD::forward_iterator_tag)
			{
				typedef typename _STD::iterator_traits<ForwardIterator>::value_type outside_value;
				choose_init(first, last, int2type<is_same<outside_value, value_type>::value>(),
				                         int2type<is_same<value_type, typename base::value_type>::value>());
			}

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

	template <class InputIterator>
		void choose_insert(iterator position, InputIterator first, InputIterator last, int2type<true>, int2type<true>)
			{base::choose_insert(position, first, last);}
	template <class InputIterator>
		void choose_insert(iterator position, InputIterator first, InputIterator last, int2type<false>, int2type<true>)
			{
				typedef _STD::__convert_iterator<_STD::__implicit_convert<pointer, InputIterator> > first_convert;
				base::choose_insert(position, first_convert(first), first_convert(last));
			}
	template <class InputIterator>
		void choose_insert(iterator position, InputIterator first, InputIterator last, int2type<true>, int2type<false>)
			{
				typedef _STD::__convert_iterator<_STD::__reinterpret_convert<typename base::pointer, InputIterator> > second_convert;
				base::choose_insert(position, second_convert(first), second_convert(last));
			}
	template <class InputIterator>
		void choose_insert(iterator position, InputIterator first, InputIterator last, int2type<false>, int2type<false>)
			{
				typedef _STD::__convert_iterator<_STD::__implicit_convert<pointer, InputIterator> > first_convert;
				typedef _STD::__convert_iterator<_STD::__reinterpret_convert<typename base::pointer, first_convert> > second_convert;
				base::choose_insert(position, second_convert(first_convert(first)), second_convert(first_convert(last)));
			}
};

// ES: basic
// invalidates all iterators.
template <class T, class Allocator>
template <class InputIterator>
void
__cdeque_imp<T, Allocator, true>::init(InputIterator first, InputIterator last, _STD::input_iterator_tag)
{
	for (; first != last; ++first)
		push_back(*first);
}

#endif  // _Inhibit_Container_Optimization

#ifdef _MSL_DEBUG

	template <class Pointer>
	struct __test_past_end
	{
		__test_past_end(Pointer start, Pointer end) : start_(start), end_(end) {}

		Pointer start_;
		Pointer end_;

		template <class Iter>
		bool operator()(const Iter& x) const
		{
			if (start_ < end_)
				return &*x < start_ || &*x > end_;
			return end_ < &*x && &*x < start_;
		}
	};

#endif  // _MSL_DEBUG

// cdeque

template <class T, class Allocator = _STD::allocator<T> >
class cdeque
#ifndef _Inhibit_Container_Optimization
	: private __cdeque_imp<T, Allocator, is_POD<T>::value>
#else
	: private __cdeque_imp<T, Allocator, false>
#endif
{
#ifndef _Inhibit_Container_Optimization
	typedef __cdeque_imp<T, Allocator, is_POD<T>::value> base;
#else
	typedef __cdeque_imp<T, Allocator, false>            base;
#endif
public:
	// types:
	typedef cdeque                                 __self;
	typedef typename base::reference               reference;
	typedef typename base::const_reference         const_reference;
	typedef typename base::size_type               size_type;
	typedef typename base::difference_type         difference_type;
	typedef typename base::value_type              value_type;
	typedef typename base::allocator_type          allocator_type;
	typedef typename base::pointer                 pointer;
	typedef typename base::const_pointer           const_pointer;

#ifdef _MSL_DEBUG
	typedef typename base::iterator                   __uncheck_iterator;
	typedef typename base::const_iterator             __uncheck_const_iterator;
	typedef _STD::__debug_iterator<cdeque, __uncheck_iterator>        iterator;
	typedef _STD::__debug_iterator<cdeque, __uncheck_const_iterator>  const_iterator;
private:
	__uncheck_iterator __iterator2base(const iterator& i)
		{
			if (i.owner_ != this)
				_MSL_DEBUG_ERROR(_STD::logic_error, "MSL DEBUG: invalid iterator given to cdeque");
			return i.base();
		}
	__uncheck_const_iterator __iterator2base(const const_iterator& i) const
		{
			if (i.owner_ != this)
				_MSL_DEBUG_ERROR(_STD::logic_error, "MSL DEBUG: invalid iterator given to cdeque");
			return i.base();
		}
	iterator       __base2iterator(const __uncheck_iterator& p)             {return iterator(this, p);}
	const_iterator __base2iterator(const __uncheck_const_iterator& p) const {return const_iterator(this, p);}
public:
#else  // _MSL_DEBUG
	typedef typename base::iterator                iterator;
	typedef typename base::const_iterator          const_iterator;
#endif  // _MSL_DEBUG

	typedef _STD::reverse_iterator<iterator>       reverse_iterator;
	typedef _STD::reverse_iterator<const_iterator> const_reverse_iterator;

#ifdef _MSL_DEBUG
private:
	void __invalidate_all_iterators()
	{
		if (iterator_list<iterator>())
			iterator_list<iterator>()->remove(_STD::__unary_true_value<__uncheck_iterator>());
		if (iterator_list<const_iterator>())
			iterator_list<const_iterator>()->remove(_STD::__unary_true_value<__uncheck_const_iterator>());
	}

	class __invalidate_on_reallocate
	{
	public:
		__invalidate_on_reallocate(cdeque& v) : vec_(v), old_cap_(v.capacity()) {}
		~__invalidate_on_reallocate()
		{
			if (old_cap_ != vec_.capacity())
				vec_.__invalidate_all_iterators();
		}
	private:
		cdeque& vec_;
		size_type old_cap_;

		__invalidate_on_reallocate(const __invalidate_on_reallocate&);
		__invalidate_on_reallocate& operator=(const __invalidate_on_reallocate&);
	};
	friend class __invalidate_on_reallocate;

	class __invalidate_on_mid_insert
	{
	public:
		__invalidate_on_mid_insert(cdeque& v, cdeque::iterator p) : vec_(v), old_size_(v.size()),
			on_end_(p == vec_.begin() || p == vec_.end()) {}
		~__invalidate_on_mid_insert()
		{
			if (old_size_ != vec_.size() && !on_end_)
				vec_.__invalidate_all_iterators();
		}
	private:
		cdeque& vec_;
		size_type old_size_;
		bool on_end_;

		__invalidate_on_mid_insert(const __invalidate_on_mid_insert&);
		__invalidate_on_mid_insert& operator=(const __invalidate_on_mid_insert&);
	};
	friend class __invalidate_on_mid_insert;

	class __invalidate_on_mid_erase
	{
	public:
		__invalidate_on_mid_erase(cdeque& v, cdeque::iterator p) : vec_(v), old_size_(v.size()),
			on_end_(p == vec_.begin() || p == vec_.end()-1) {}
		__invalidate_on_mid_erase(cdeque& v, cdeque::iterator f, cdeque::iterator l)
			: vec_(v), old_size_(v.size()),
			on_end_(f == vec_.begin() || l == vec_.end()) {}
		~__invalidate_on_mid_erase()
		{
			if (old_size_ != vec_.size() && !on_end_)
				vec_.__invalidate_all_iterators();
		}
	private:
		cdeque& vec_;
		size_type old_size_;
		bool on_end_;

		__invalidate_on_mid_erase(const __invalidate_on_mid_erase&);
		__invalidate_on_mid_erase& operator=(const __invalidate_on_mid_erase&);
	};
	friend class __invalidate_on_mid_erase;

	void __invalidate_past_end_iterators()
	{
		if (base::capacity() > 0)
		{
			if (iterator_list<iterator>())
				iterator_list<iterator>()->remove(__test_past_end<pointer>(&*base::begin(), &*base::end()));
			if (iterator_list<const_iterator>())
				iterator_list<const_iterator>()->remove(__test_past_end<const_pointer>(&*base::begin(), &*base::end()));
		}
	}

	class __invalidate_on_shrink
	{
	public:
		__invalidate_on_shrink(cdeque& v) : vec_(v), old_size_(v.size()) {}
		~__invalidate_on_shrink()
		{
			if (old_size_ < vec_.size())
				vec_.__invalidate_past_end_iterators();
		}
	private:
		cdeque& vec_;
		size_type old_size_;

		__invalidate_on_shrink(const __invalidate_on_shrink&);
		__invalidate_on_shrink& operator=(const __invalidate_on_shrink&);
	};
	friend class __invalidate_on_shrink;
public:
#endif  // _MSL_DEBUG

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

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

	~cdeque()
		{
			__invalidate_all_iterators();
		}
#endif  // _MSL_DEBUG

	using base::get_allocator;
//	allocator_type get_allocator() const;

	using base::max_size;
//	size_type max_size() const;
	using base::size;
//	size_type size() const;

	using base::capacity;
//	size_type capacity() const;
	using base::empty;
//	bool      empty() const;
	using base::at;
//	reference       at(size_type n);
//	const_reference at(size_type n) const;

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

	using base::invariants;
//	bool invariants() const;

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

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

	using base::resize;
//	void resize(size_type sz);
//	void resize(size_type sz, const value_type& x);
	using base::reserve;
//	void reserve(size_type n);

	reference       operator[](size_type n)       {return base::operator[](n);}
	const_reference operator[](size_type n) const {return base::operator[](n);}

	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();

	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, int2type<is_integral<InputIterator>::value>());}
	using base::erase;
//	iterator erase(iterator position);
//	iterator erase(iterator first, iterator last);
	using base::clear;
//	void clear();
	void swap(cdeque& x) {base::swap(x);}
#else  // _MSL_DEBUG
	void assign(size_type n, const value_type& u)
		{
			__invalidate_all_iterators();
			base::assign(n, u);
		}
	template <class InputIterator>
		void assign(InputIterator first, InputIterator last)
			{__invalidate_all_iterators();
			base::choose_assign(first, last, int2type<is_integral<InputIterator>::value>());}

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

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

	void resize(size_type sz)
		{
			__invalidate_on_shrink __s(*this);
			__invalidate_on_reallocate __c(*this);
			base::resize(sz);
		}

	void resize(size_type sz, const value_type& x)
		{
			__invalidate_on_shrink __s(*this);
			__invalidate_on_reallocate __c(*this);
			base::resize(sz, (const typename base::value_type&)x);
		}

	void reserve(size_type n)
		{
			__invalidate_on_reallocate __c(*this);
			base::reserve(n);
		}

	reference       operator[](size_type n)       {return at(n);}
	const_reference operator[](size_type n) const {return at(n);}

	void push_front(const value_type& x)
		{
			__invalidate_on_reallocate __c(*this);
			base::push_front(x);
		}

	void push_back(const value_type& x)
		{
			__invalidate_on_reallocate __c(*this);
			base::push_back(x);
		}

	void pop_front()
		{
			if (empty())
				_MSL_DEBUG_ERROR(_STD::logic_error, "MSL DEBUG: pop_front called on empty cdeque");
			base::pop_front();
			__invalidate_past_end_iterators();
		}

	void pop_back()
		{
			if (empty())
				_MSL_DEBUG_ERROR(_STD::logic_error, "MSL DEBUG: pop_back called on empty cdeque");
			base::pop_back();
			__invalidate_past_end_iterators();
		}

	iterator insert(iterator position, const value_type& x)
		{
			typename base::iterator result;
			{
			__invalidate_on_mid_insert __s(*this, position);
			__invalidate_on_reallocate __c(*this);
			result = base::insert(__iterator2base(position), x);
			}
			return __base2iterator(result);
		}
	void insert(iterator position, size_type n, const value_type& x)
		{
			__invalidate_on_mid_insert __s(*this, position);
			__invalidate_on_reallocate __c(*this);
			base::insert(__iterator2base(position), n, x);
		}
	template <class InputIterator>
		void insert(iterator position, InputIterator first, InputIterator last)
			{
				__invalidate_on_mid_insert __s(*this, position);
				__invalidate_on_reallocate __c(*this);
				base::choose_insert(__iterator2base(position), first, last, int2type<is_integral<InputIterator>::value>());
			}

	iterator erase(iterator position)
		{
			position.deref();
			typename base::iterator result;
			{
			__invalidate_on_shrink __c(*this);
			__invalidate_on_mid_erase __s(*this, position);
			result = base::erase(__iterator2base(position));
			}
			return __base2iterator(result);
		}
	iterator erase(iterator first, iterator last)
		{
			if (first > last)
				_MSL_DEBUG_ERROR(_STD::logic_error, "MSL DEBUG: invalid iterator range given to cdeque::erase");
			typename base::iterator result;
			{
			__invalidate_on_shrink __c(*this);
			__invalidate_on_mid_erase __s(*this, first, last);
			result = base::erase(__iterator2base(first), __iterator2base(last));
			}
			return __base2iterator(result);
		}

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

	void swap(cdeque& x)
		{
			base::swap(x);
			iterator::swap(this, &x);
			const_iterator::swap(this, &x);
		}
#endif  // _MSL_DEBUG

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

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

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

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

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

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

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

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

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

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

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

#ifndef _MSL_DEBUG

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

template<class T, class Allocator>
struct has_trivial_move_ctor<cdeque<T, Allocator> >
{
	static const bool value = has_trivial_copy_ctor<Allocator>::value;
};

#endif  // _MSL_DEBUG

template<class T, class Allocator>
struct move_with_swap<cdeque<T, Allocator> >
{
	static const bool value = has_trivial_copy_ctor<Allocator>::value &&
	                          has_trivial_assignment<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 // _CDEQUE

// hh 981005 rewrote
// hh 981208 changed static_cast to reinterpret_cast on the value_type (pointer specialization only)
// hh 981220 Rewrote iterators to gain higher performance
// hh 981220 Added typename to appropriate return types
// hh 981220 Modifed some method signitures to simplified syntax
// hh 981220 Added class modifier to several friend declarations
// hh 990120 changed names of MSIPL flags.
// 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 000129 Moved into namespace Metrowerks
// hh 000129 Renamed to cdeque.
// hh 001011 Fixed several typename bugs
// hh 001011 Disabled friends of iterators for gcc
// hh 001116 Fixed wrapping bug in operator-= of iterator and const_iterator
// hh 010125 Removed dependence on <string>
// hh 010301 Protected min and max from macro abuse.
// hh 010402 Removed 68K CMF support
// hh 010509 Made iterator difference a global friend
// hh 011210 Rewrote.
// 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 031022 Removed some extraneous typenames
