// vector stl/clr header
// Copyright (c) Microsoft Corporation. All rights reserved.
#ifndef _CLI_VECTOR_
 #define _CLI_VECTOR_
#include <cliext/iterator>

namespace cliext {
	namespace impl {
//
// TEMPLATE CLASS vector_impl
//
template<typename _Value_t,
	bool _Is_ref>
	ref class vector_impl
	:	public _STLCLR IVector<_Value_t>
	{	// varying size array of elements
public:
	// types
	typedef vector_impl<_Value_t, _Is_ref> _Mytype_t;
	typedef _STLCLR IVector<_Value_t> _Mycont_it;
	typedef cli::array<_Value_t> _Myarray_t;
	typedef System::Collections::Generic::IEnumerable<_Value_t> _Myenum_it;
	typedef _Cont_make_value<_Value_t, _Is_ref> _Mymake_t;

	typedef RandomAccessIterator<_Mytype_t>
		iterator;
	typedef ConstRandomAccessIterator<_Mytype_t>
		const_iterator;
	typedef ReverseRandomAccessIterator<_Mytype_t>
		reverse_iterator;
	typedef ReverseRandomAccessIterator<_Mytype_t>
		const_reverse_iterator;

	typedef int size_type;
	typedef int difference_type;
	typedef _Value_t value_type;
	typedef value_type% reference;
	typedef value_type% const_reference;

	typedef _Mycont_it generic_container;
	typedef value_type generic_value;
	typedef _STLCLR Generic::ContainerRandomAccessIterator<_Value_t>
		generic_iterator;
	typedef _STLCLR Generic::ReverseRandomAccessIterator<_Value_t>
		generic_reverse_iterator;

	// constants
	static const int _Maxsize = MAX_CONTAINER_SIZE;

	// basics
	vector_impl()
		{	// construct empty vector
		_Buy(0);
		}

	vector_impl% operator=(vector_impl% _Right)
		{	// assign
		if ((Object^)this != %_Right)
			{	// worth doing, do it
			clear();
			reserve(_Right.size());

			for (size_type _Idx = 0; _Idx < _Right.size(); ++_Idx)
				insert_n(size(), 1, _Right.at(_Idx));
			}
		return (*this);
		}

	// constructors
	vector_impl(_Mytype_t% _Right)
		{	// construct by copying _Right
		for (size_type _Idx = _Buy(_Right.size()); 0 <= --_Idx; )
			_Myarray[_Idx] = _Mymake_t::make_value(_Right.at(_Idx));
		_Mysize = _Right.size();
		}

	explicit vector_impl(size_type _Count)
		{	// construct from _Count * value_type()
		_Mysize = _Fill_n(0, _Buy(_Count), value_type());
		}

	vector_impl(size_type _Count, value_type _Val)
		{	// construct from _Count * _Val
		_Mysize = _Fill_n(0, _Buy(_Count), _Val);
		}

	template<typename _InIt_t>
		vector_impl(_InIt_t _First, _InIt_t _Last)
		{	// construct from [_First, _Last)
		_Construct(_First, _Last, _Iter_category(_First));
		}

	template<typename _InIt_t>
		void _Construct(_InIt_t _Count, _InIt_t _Val,
			_Int_iterator_tag%)
		{	// initialize with _Count * _Val
		_Mysize = _Fill_n(0, _Buy((size_type)_Count), (value_type)_Val);
		}

	template<typename _InIt_t>
		void _Construct(_InIt_t _First, _InIt_t _Last,
			input_iterator_tag%)
		{	// initialize with [_First, _Last), input iterators
		_Buy(_First != _Last ? 1 : 0);	// buy at least one if non-empty
		for (; _First != _Last; ++_First)
			insert_n(size(), 1, (value_type)*_First);
		}

	template<typename _InIt_t>
		void _Construct(_InIt_t _First, _InIt_t _Last,
			forward_iterator_tag%)
		{	// initialize with [_First, _Last), forward iterators
		size_type _Size = cliext::distance(_First, _Last);

		_Buy(_Size);
		for (size_type _Idx = 0; _Idx < _Size; ++_Idx, ++_First)
			_Myarray[_Idx] = _Mymake_t::make_value(value_type(*_First));
		_Mysize = _Size;
		}

	vector_impl(_Myenum_it^ _Right)
		{	// initialize with enumeration
		_Buy(0);
		for each (value_type _Val in _Right)
			push_back(_Val);
		}

	// destructor
	~vector_impl()
		{	// destroy the object
		clear();
		_Myarray = nullptr;
		_Mysize = 0;
		++_Mygen;
		}

	// accessors
	unsigned long get_generation()
		{	// get underlying container generation
		return (_Mygen);
		}

	size_type get_bias(iterator _Where)
		{	// get offset from valid iterator
		if (_Where.container() != this)
			throw gcnew System::ArgumentException();
		return (_Where.get_bias());
		}

	bool valid_bias(size_type _Bias)
		{	// test if _Bias is currently a valid bias
		return (0 <= _Bias && _Bias <= size());
		}

	reference at(size_type _Pos)
		{	// subscript mutable sequence with checking
		if (_Pos < 0 || size() <= _Pos)
			throw gcnew System::ArgumentOutOfRangeException();

		return (_Myarray[_Pos]);
		}

	reference at_bias(size_type _Bias)
		{	// subscript mutable sequence with checking, biased
		return (at(_Bias));
		}

	property value_type default[size_type]
		{	// get or set subscripted element
		virtual value_type get(size_type _Pos)
			{	// get _Pos element
			return (at(_Pos));
			}

		virtual void set(size_type _Pos, value_type _Val)
			{	// set _Pos element
			at(_Pos) = _Val;
			}
		};

	property value_type front_item
		{	// get or set first element
		virtual value_type get()
			{	// get first element
			return (front());
			}

		virtual void set(value_type _Val)
			{	// set first element
			front() = _Val;
			}
		};

	property value_type back_item
		{	// get or set last element
		virtual value_type get()
			{	// get last element
			return (back());
			}

		virtual void set(value_type _Val)
			{	// set last element
			back() = _Val;
			}
		};

	reference front()
		{	// get first element of mutable sequence
		if (empty())
			throw gcnew System::NullReferenceException();
		return (at(0));
		}

	reference back()
		{	// get last element of mutable sequence
		if (empty())
			throw gcnew System::NullReferenceException();
		return (at(size() - 1));
		}

	// converters
	_Myarray_t^ to_array()
		{	// convert to array
		_Myarray_t^ _Ans = gcnew _Myarray_t(size());

		for (int _Idx = size(); 0 <= --_Idx; )
			_Ans[_Idx] = _Mymake_t::make_value(_Myarray[_Idx]);
		return (_Ans);
		}

	// iterator generators
	iterator make_iterator(size_type _Bias)
		{	// return iterator for offset
		return (iterator(this, _Bias));
		}

	iterator begin()
		{	// return iterator for beginning of mutable sequence
		return (make_iterator(0));
		}
	iterator end()
		{	// return iterator for end of mutable sequence
		return (make_iterator(size()));
		}

	reverse_iterator rbegin()
		{	// return reverse iterator for beginning of mutable sequence
		return (reverse_iterator(end()));
		}

	reverse_iterator rend()
		{	// return reverse iterator for end of mutable sequence
		return (reverse_iterator(begin()));
		}

	// size controllers
	void reserve(size_type _Capacity)
		{	// determine new minimum length of allocated storage
		if (_Capacity < 0)
			throw gcnew System::ArgumentOutOfRangeException();

		if (capacity() < _Capacity)
			{	// not enough room, reallocate
			_Myarray_t^ _Oldarray = _Myarray;

			_Myarray = gcnew _Myarray_t(_Capacity);
			for (size_type _Idx = size(); 0 <= --_Idx; )
				_Myarray[_Idx] = _Oldarray[_Idx];
			}
		}

	size_type capacity()
		{	// return current length of allocated storage
		return (_Myarray == nullptr ? 0 : _Myarray->Length);
		}

	virtual void resize(size_type _Newsize)
		{	// determine new length, padding with value_type elements
		resize(_Newsize, value_type());
		}

	void resize(size_type _Newsize, value_type _Val)
		{	// determine new length, padding with _Val elements
		if (_Newsize < 0)
			throw gcnew System::ArgumentOutOfRangeException();

		if (size() < _Newsize)
			insert_n(size(), _Newsize - size(), _Val);
		else if (_Newsize < size())
			erase_n(_Newsize, size());
		}

	size_type size()
		{	// return length of sequence
		return (_Mysize);
		}

	bool empty()
		{	// test if sequence is empty
		return (size() == 0);
		}

	// mutators
//	void push_front(value_type _Val);
//	void pop_front();

	void push_back(value_type _Val)
		{	// insert element at end
		insert_n(size(), 1, _Val);
		}

	void pop_back()
		{	// erase element at end
		erase_n(size() - 1, size());	// discard from end
		}

	void assign(size_type _Count, value_type _Val)
		{	// assign _Count * _Val
		clear();
		insert_n(0, _Count, _Val);
		}

	void assign(_STLCLR Generic::IInputIterator<_Value_t>^ _First,
		_STLCLR Generic::IInputIterator<_Value_t>^ _Last)
		{	// initialize with [_First, _Last), input iterators
		if (_Iter_container(_First) != this)
			clear();

		size_type _Oldsize = size();

		for (; !_First->equal_to(_Last); _First->next())
			insert_n(size(),
				1, (value_type)_First->get_cref());	// append new stuff
		erase_n(0, _Oldsize);	// erase any leftover old stuff
		}

	void assign(_Myenum_it^ _Right)
		{	// initialize with enumeration
		size_type _Oldsize = size();

		for each (value_type _Val in _Right)
			insert_n(size(), 1, _Val);	// append new stuff
		erase_n(0, _Oldsize);	// erase any leftover old stuff
		}

	void assign(System::Collections::IEnumerable^ _Right)
		{	// initialize with enumeration
		size_type _Oldsize = size();

		for each (value_type _Val in _Right)
			insert_n(size(), 1, _Val);	// append new stuff
		erase_n(0, _Oldsize);	// erase any leftover old stuff
		}

	iterator insert(iterator _Where, value_type _Val)
		{	// insert _Val at _Where
		return (make_iterator(
			insert_n(get_bias(_Where), 1, _Val)));
		}

	void insert(iterator _Where,
		size_type _Count, value_type _Val)
		{	// insert _Count * _Val at _Where
		insert_n(get_bias(_Where), _Count, _Val);
		}

	void insert(iterator _Where_iter,
		_STLCLR Generic::IInputIterator<_Value_t>^ _First,
		_STLCLR Generic::IInputIterator<_Value_t>^ _Last)
		{	// insert [_First, _Last) at _Where, input iterators
		size_type _Where = get_bias(_Where_iter);
		size_type _Oldsize = size();

		if (!valid_bias(_Where))
			throw gcnew System::InvalidOperationException();

		for (; !_First->equal_to(_Last); _First->next())
			insert_n(size(), 1, (value_type)_First->get_cref());
		reverse_n(_Where, _Oldsize);
		reverse_n(_Oldsize, size());
		reverse_n(_Where, size());
		}

	void insert(iterator _Where_iter,
		_Myenum_it^ _Right)
		{	// insert enumeration at _Where, possibly from this container
		size_type _Where = get_bias(_Where_iter);
		size_type _Oldsize = size();

		if (!valid_bias(_Where))
			throw gcnew System::InvalidOperationException();

		for each (value_type _Val in _Right)
			insert_n(size(), 1, _Val);
		reverse_n(_Where, _Oldsize);
		reverse_n(_Oldsize, size());
		reverse_n(_Where, size());
		}

	void insert(iterator _Where_iter,
		System::Collections::IEnumerable^ _Right)
		{	// insert enumeration at _Where, possibly from this container
		size_type _Where = get_bias(_Where_iter);
		size_type _Oldsize = size();

		if (!valid_bias(_Where))
			throw gcnew System::InvalidOperationException();

		for each (value_type _Val in _Right)
			insert_n(size(), 1, _Val);
		reverse_n(_Where, _Oldsize);
		reverse_n(_Oldsize, size());
		reverse_n(_Where, size());
		}

	template<typename _InIt_t>
		void _Insert_self(size_type _Where, _InIt_t _First, _InIt_t _Last)
		{	// insert [_First, _Last] at _Where, from this container
		size_type _Oldsize = size();

		if (!valid_bias(_Where))
			throw gcnew System::InvalidOperationException();

		for (; _First != _Last; ++_First)
			insert_n(size(), 1, (value_type)*_First);
		reverse_n(_Where, _Oldsize);
		reverse_n(_Oldsize, size());
		reverse_n(_Where, size());
		}

	size_type insert_n(size_type _Where,
		size_type _Count, value_type _Val)
		{	// insert _Count * _Val at _Where
		if (_Count < 0)
			throw gcnew System::ArgumentOutOfRangeException();

		if (_Count == 0)
			return (_Where);
		else
			{	// insert finite sequence
			_Insert_space(_Where, _Count);
			_Fill_n(_Where, _Count, _Val);
			++_Mygen;
			return (_Where + _Count - 1);
			}
		}

	iterator erase(iterator _Where)
		{	// erase element at _Where
		size_type _Bias = get_bias(_Where);

		return (make_iterator(erase_n(_Bias, _Bias + 1)));
		}

	iterator erase(iterator _First, iterator _Last)
		{	// erase [_First, _Last)
		return (make_iterator(
			erase_n(get_bias(_First), get_bias(_Last))));
		}

	size_type erase_n(size_type _First, size_type _Last)
		{	// erase [_First, _Last)
		if (_First < 0 || _Last < _First || size() < _Last)
			throw gcnew System::InvalidOperationException();

		if (_First != _Last)
			{	// worth doing, copy down over hole
			for (size_type _Next = _First; _Next != _Last; ++_Next)
				_Mymake_t::unmake_value(at(_Next));

			_Mysize = _Copy(_Myarray, _Last, size(), _First);
			++_Mygen;
			}
		return (_First);
		}

	void reverse_n(size_type _First, size_type _Last)
		{	// reverse a subrange
		bool _Changed = false;

		for (; _First != _Last && _First != --_Last; ++_First)
			{	// swap distinct _First and _Last
			value_type _Temp = _Myarray[_First];

			_Myarray[_First] = _Myarray[_Last];
			_Myarray[_Last] = _Temp;
			_Changed = true;
			}
		if (_Changed)
			++_Mygen;
		}

	void clear()
		{	// erase all
		erase_n(0, size());
		}

	void swap(_Mytype_t% _Right)
		{	// exchange contents with _Right
		if ((Object^)this != %_Right)
			{	// worth doing, swap
			_Myarray_t^ _Tarray = _Myarray;
			size_type _Tsize = _Mysize;

			_Myarray = _Right._Myarray;
			_Right._Myarray = _Tarray;

			_Mysize = _Right._Mysize;
			_Right._Mysize = _Tsize;

			++_Mygen;
			++_Right._Mygen;
			}
		}

_STLCLR_FIELD_ACCESS:
	size_type _Buy(size_type _Capacity)
		{	// allocate array with _Capacity elements
		_Mygen = 0;
		if (_Capacity < 0)
			throw gcnew System::ArgumentOutOfRangeException();

		if (0 < _Capacity)
			_Myarray = gcnew _Myarray_t(_Capacity);
		return (_Capacity);
		}

	size_type _Copy(_Myarray_t^ _Source,
		size_type _First, size_type _Last, size_type _Dest)
		{	// copy [_First, _Last) in _Source to _Dest
		for (; _First != _Last; ++_First, ++_Dest)
			_Myarray[_Dest] = _Source[_First];
		return (_Dest);
		}

	void _Copyback(size_type _First, size_type _Last, size_type _Dest)
		{	// copy [_First, _Last) to [..., _Dest)
		for (; _First != _Last; )
			_Myarray[--_Dest] = _Myarray[--_Last];
		}

	size_type _Fill_n(size_type _First, size_type _Count, value_type _Val)
		{	// copy initializing _Count * _Val
		for (; 0 < _Count; --_Count, ++_First)
			_Myarray[_First] = _Mymake_t::make_value(_Val);
		return (_First);
		}

	size_type _Insert_space(size_type _Where, size_type _Count)
		{	// dig a hole for _Count elements at _Where
		size_type _Capacity = capacity();

		if (_Where < 0 || size() < _Where
			|| _Count < 0 || _Maxsize - size() < _Count)
			throw gcnew System::ArgumentOutOfRangeException();
		else if (_Capacity < size() + _Count)
			{	// not enough room, reallocate
			_Myarray_t^ _Oldarray = _Myarray;

			_Capacity = _Maxsize - _Capacity < _Capacity
				? 0 : 2 * _Capacity;	// try to double capacity
			if (_Capacity < size() + _Count)
				_Capacity = size() + _Count;
			_Myarray = gcnew _Myarray_t(_Capacity);

			_Copy(_Oldarray, 0, _Where, 0);
			_Mysize = _Copy(_Oldarray, _Where, _Mysize, _Where + _Count);
			}
		else if (size() - _Where < _Count)
			_Mysize = _Copy(_Myarray, _Where, size(),
				_Where + _Count);	// new stuff spills off end
		else
			{	// new stuff can all be assigned
			size_type _Oldend = size();

			_Mysize = _Copy(_Myarray, _Oldend - _Count, _Oldend, _Oldend);
			_Copyback(_Where, _Oldend - _Count, _Oldend);
			}
		return (_Where);
		}

	// data members
	_Myarray_t^ _Myarray;	// managed array of _Value_t
	size_type _Mysize;		// number of active elements
	unsigned long _Mygen;	// current change generation

	// interfaces
public:
	virtual System::Object^ Clone()
		{	// clone the vector
		return (gcnew vector_impl(*this));
		}

private:
	property size_type Count
		{	// element count
		virtual size_type get() sealed
			= System::Collections::ICollection::Count::get
			{	// get element count
			return (size());
			}
		};

	property bool IsSynchronized
		{	// synchronized status
		virtual bool get() sealed
			= System::Collections::ICollection::IsSynchronized::get
			{	// test if synchronized
			return (false);
			}
		};

	property System::Object^ SyncRoot
		{	// synchronizer
		virtual System::Object^ get() sealed
			= System::Collections::ICollection::SyncRoot::get
			{	// get synchronizer
			return (this);
			}
		};

	virtual void CopyTo(System::Array^ _Dest_arg, int _First) sealed
		= System::Collections::ICollection::CopyTo
		{	// copy to _Dest_arg, beginning at _First
		cli::array<System::Object^>^ _Dest =
			(cli::array<System::Object ^>^)_Dest_arg;
		for (int _Idx = size(); 0 <= --_Idx; )
			{	// copy back to front
			_Dest[_First + _Idx] = at(_Idx);
			}
		}

	virtual System::Collections::IEnumerator^ GetEnumerator() sealed
		= System::Collections::IEnumerable::GetEnumerator
		{	// get enumerator for the container
		return (gcnew _STLCLR VectorEnumerator<_Value_t>(this, 0));
		}

	virtual unsigned long get_generation_virtual() sealed
		= _Mycont_it::get_generation
		{	// get underlying container generation
		return (get_generation());
		}

	virtual bool valid_bias_virtual(size_type _Bias) sealed
		= _Mycont_it::valid_bias
		{	// test if _Bias is currently a valid bias
		return (valid_bias(_Bias));
		}

	virtual reference at_virtual(size_type _Pos) sealed
		= _Mycont_it::at
		{	// subscript mutable sequence with checking
		return (at(_Pos));
		}

	virtual reference at_bias_virtual(size_type _Bias) sealed
		= _Mycont_it::at_bias
		{	// subscript mutable sequence with checking, biased
		return (at_bias(_Bias));
		}

	virtual reference front_virtual() sealed
		= _Mycont_it::front
		{	// get first element of mutable sequence
		return (front());
		}

	virtual reference back_virtual() sealed
		= _Mycont_it::back
		{	// get last element of mutable sequence
		return (back());
		}

	// iterator generators
	virtual generic_iterator begin_virtual() sealed
		= _Mycont_it::begin
		{	// return iterator for beginning of mutable sequence
		return (begin());
		}
	virtual generic_iterator end_virtual() sealed
		= _Mycont_it::end
		{	// return iterator for end of mutable sequence
		return (end());
		}

	virtual generic_reverse_iterator rbegin_virtual() sealed
		= _Mycont_it::rbegin
		{	// return reverse iterator for beginning of mutable sequence
		return (generic_reverse_iterator(end()));
		}

	virtual generic_reverse_iterator rend_virtual() sealed
		= _Mycont_it::rend
		{	// return reverse iterator for end of mutable sequence
		return (generic_reverse_iterator(begin()));
		}

	// size controllers
	virtual void reserve_virtual(size_type _Capacity) sealed
		= _Mycont_it::reserve
		{	// determine new minimum length of allocated storage
		reserve(_Capacity);
		}

	virtual size_type capacity_virtual() sealed
		= _Mycont_it::capacity
		{	// return current length of allocated storage
		return (capacity());
		}

	virtual void resize_virtual(size_type _Newsize) sealed
		= _Mycont_it::resize
		{	// determine new length, padding with value_type elements
		resize(_Newsize);
		}

	virtual void resize_virtual(size_type _Newsize, value_type _Val) sealed
		= _Mycont_it::resize
		{	// determine new length, padding with _Val elements
		resize(_Newsize, _Val);
		}

	virtual size_type size_virtual() sealed
		= _Mycont_it::size
		{	// return length of sequence
		return (size());
		}

	virtual bool empty_virtual() sealed
		= _Mycont_it::empty
		{	// test if sequence is empty
		return (empty());
		}

	// mutators
//	void push_front(value_type _Val);
//	void pop_front();

	virtual void push_back_virtual(value_type _Val) sealed
		= _Mycont_it::push_back
		{	// insert element at end
		push_back(_Val);
		}

	virtual void pop_back_virtual() sealed
		= _Mycont_it::pop_back
		{	// erase element at end
		pop_back();
		}

	virtual void assign_virtual(size_type _Count, value_type _Val) sealed
		= _Mycont_it::assign
		{	// assign _Count * _Val
		assign(_Count, _Val);
		}

	virtual void assign_virtual(
		_STLCLR Generic::IInputIterator<_Value_t>^ _First,
		_STLCLR Generic::IInputIterator<_Value_t>^ _Last) sealed
		= _Mycont_it::assign
		{	// initialize with [_First, _Last), input iterators
		assign(_First, _Last);
		}

	virtual void assign_virtual(
		System::Collections::IEnumerable^ _Right) sealed
		= _Mycont_it::assign
		{	// initialize with enumeration
		assign(_Right);
		}

	virtual generic_iterator insert_virtual(generic_iterator _Where,
		value_type _Val) sealed
		= _Mycont_it::insert
		{	// insert _Val at _Where
		return (insert(iterator(_Where), _Val));
		}

	virtual void insert_virtual(generic_iterator _Where,
		size_type _Count, value_type _Val) sealed
			= _Mycont_it::insert
		{	// insert _Count * _Val at _Where
		return (insert(iterator(_Where), _Count, _Val));
		}

	virtual void insert_virtual(generic_iterator _Where_iter,
		_STLCLR Generic::IInputIterator<_Value_t>^ _First,
		_STLCLR Generic::IInputIterator<_Value_t>^ _Last) sealed
			= _Mycont_it::insert
		{	// insert [_First, _Last) at _Where, input iterators
		insert(iterator(_Where_iter), _First, _Last);
		}

	virtual void insert_virtual(generic_iterator _Where_iter,
		System::Collections::IEnumerable^ _Right) sealed
			= _Mycont_it::insert
		{	// insert enumeration at _Where, possibly from this container
		insert(iterator(_Where_iter), _Right);
		}

	virtual generic_iterator erase_virtual(generic_iterator _Where) sealed
		= _Mycont_it::erase
		{	// erase element at _Where
		return (erase(iterator(_Where)));
		}

	virtual generic_iterator erase_virtual(generic_iterator _First,
		generic_iterator _Last) sealed
		= _Mycont_it::erase
		{	// erase [_First, _Last)
		return (erase(iterator(_First), iterator(_Last)));
		}

	virtual void clear_virtual() sealed
		= _Mycont_it::clear
		{	// erase all
		clear();
		}

	virtual void swap_virtual(_Mycont_it^ _Right) sealed
		= _Mycont_it::swap
		{	// exchange contents with _Right
		swap(*(_Mytype_t^)_Right);
		}
	};

//
// TEMPLATE REF CLASS vector_base
//
template<typename _Value_t,
	bool _Is_ref>
	ref class vector_base
	:	public vector_impl<_Value_t, _Is_ref>,
			System::Collections::Generic::ICollection<_Value_t>,
			System::Collections::Generic::IEnumerable<_Value_t>,
			System::Collections::Generic::IList<_Value_t>
	{	// varying size array of elements
public:
	// types
	typedef vector_base<_Value_t, _Is_ref> _Mytype_t;
	typedef vector_impl<_Value_t, _Is_ref> _Mybase_t;
//	typedef _STLCLR IVector<_Value_t> _Mycont_it;
	typedef _Cont_make_value<_Value_t, _Is_ref> _Mymake_t;

//	typedef int size_type;
//	typedef int difference_type;
//	typedef _Value_t value_type;
//	typedef value_type% reference;
//	typedef value_type% const_reference;

//	typedef _Mycont_it generic_container;
//	typedef value_type generic_value;

	// basics
	vector_base()
		:	_Mybase_t()
		{	// construct default
		}

	vector_base(vector_base% _Right)
		:	_Mybase_t(_Right)
		{	// construct by copying a vector
		}

	vector_base% operator=(vector_base% _Right)
		{	// assign
		_Mybase_t::operator=(_Right);
		return (*this);
		}

	operator _Mycont_it^()
		{	// convert to interface
		return (this);
		}

	// constructors
	explicit vector_base(size_type _Count)
		:	_Mybase_t(_Count)
		{	// construct from _Count * value_type()
		}

	vector_base(size_type _Count, value_type _Val)
		:	_Mybase_t(_Count, _Val)
		{	// construct from _Count * _Val
		}

	template<typename _InIt_t>
		vector_base(_InIt_t _First, _InIt_t _Last)
		:	_Mybase_t(_First, _Last)
		{	// construct from [_First, _Last)
		}

	vector_base(_Myenum_it^ _Right)
		:	_Mybase_t(_Right)
		{	// initialize with enumeration
		}

	// mutators
	template<typename _InIt_t>
		void assign(_InIt_t _First, _InIt_t _Last)
		{	// assign [_First, _Last)
		_Assign(_First, _Last, _Iter_category(_First));
		}

	template<typename _InIt_t>
		void _Assign(_InIt_t _Count, _InIt_t _Val,
			_Int_iterator_tag%)
		{	// assign _Count * _Val
		clear();
		insert_n(0, (size_type)_Count, (value_type)_Val);
		}

	template<typename _InIt_t>
		void _Assign(_InIt_t _First, _InIt_t _Last,
			input_iterator_tag%)
		{	// initialize with [_First, _Last), input iterators
		if (_Iter_container(_First) != this)
			clear();

		size_type _Oldsize = size();

		for (; _First != _Last; ++_First)
			insert_n(size(), 1, (value_type)*_First);	// append new stuff
		erase_n(0, _Oldsize);	// erase any leftover old stuff
		}

	template<typename _InIt_t>
		void _Assign(_InIt_t _First, _InIt_t _Last,
			random_access_iterator_tag%)
		{	// initialize with [_First, _Last), input iterators
		if (_Last < _First)
			throw gcnew System::ArgumentOutOfRangeException();

		if (_Iter_container(_First) != this)
			clear();

		size_type _Oldsize = size();

		for (; _First != _Last; ++_First)
			insert_n(size(), 1, (value_type)*_First);	// append new stuff
		erase_n(0, _Oldsize);	// erase any leftover old stuff
		}

	template<typename _InIt_t>
		void insert(iterator _Where, _InIt_t _First, _InIt_t _Last)
		{	// insert [_First, _Last) at _Where
		_Insert(get_bias(_Where), _First, _Last,
			_Iter_category(_First));
		}

	template<typename _InIt_t>
		void _Insert(size_type _Where, _InIt_t _First, _InIt_t _Last,
			_Int_iterator_tag%)
		{	// insert _Count * _Val at _Where
		insert_n(_Where, (size_type)_First, (value_type)_Last);
		}

	template<typename _InIt_t>
		void _Insert(size_type _Where, _InIt_t _First, _InIt_t _Last,
			input_iterator_tag%)
		{	// insert [_First, _Last) at _Where, input iterators
		if (_Iter_container(_First) == this)
			_Insert_self(_Where, _First, _Last);
		else
			for (; _First != _Last; ++_First, ++_Where)
				_Where = insert_n(_Where, 1, (value_type)*_First);
		}

	template<typename _InIt_t>
		void _Insert(size_type _Where, _InIt_t _First, _InIt_t _Last,
			forward_iterator_tag%)
		{	// insert [_First, _Last) at _Where, forward iterators
		if (_Iter_container(_First) == this)
			_Insert_self(_Where, _First, _Last);
		else
			{	// not inserting from this container, dig a hole and fill it
			size_type _Size = cliext::distance(_First, _Last);

			if (_Size < 0)
				throw gcnew System::ArgumentOutOfRangeException();
			_Insert_space(_Where, _Size);
			for (size_type _Idx = 0; _Idx < _Size; ++_Idx, ++_First)
				_Myarray[_Where + _Idx] =
					_Mymake_t::make_value(value_type(*_First));
			}
		}

	// interfaces
private:
	property size_type Count_generic
		{	// element count
		virtual size_type get() sealed
			= System::Collections::Generic::ICollection<_Value_t>::Count::get
			{	// get element count
			return (size());
			}
		};

	property bool IsReadOnly
		{	// test if read only
		virtual bool get() sealed
			= System::Collections::Generic::ICollection<_Value_t>
				::IsReadOnly::get
			{	// test if read only
			return (false);
			}
		};

	virtual void CopyTo(_Myarray_t^ _Dest, int _First) sealed
		= System::Collections::Generic::ICollection<_Value_t>::CopyTo
		{	// copy to _Dest, beginning at _First
		for (int _Idx = size(); 0 <= --_Idx; )
			{	// copy back to front
			_Dest[_First + _Idx] = _Mymake_t::make_value(at(_Idx));
			}
		}

	virtual System::Collections::Generic::IEnumerator<_Value_t>^
		GetEnumerator() sealed
		= System::Collections::Generic::IEnumerable<_Value_t>::GetEnumerator
		{	// get enumerator for the container
		return (gcnew _STLCLR VectorEnumerator<_Value_t>(this, 0));
		}

	virtual void Add(value_type _Val) sealed
		= System::Collections::Generic::ICollection<_Value_t>::Add
		{	// add element with value _Val
		insert_n(size(), 1, _Val);
		}

	virtual void Clear() sealed
		= System::Collections::Generic::ICollection<_Value_t>::Clear
		{	// erase all elements
		clear();
		}

	virtual bool Contains(value_type _Val) sealed
		= System::Collections::Generic::ICollection<_Value_t>::Contains
		{	// search for element matching value _Val
		for (size_type _Idx = 0; _Idx != size(); ++_Idx)
			if (((System::Object^)_Val)->Equals(
				(System::Object^)at(_Idx)))
				return (true);
		return (false);
		}

	virtual bool Remove(value_type _Val) sealed
		= System::Collections::Generic::ICollection<_Value_t>::Remove
		{	// remove first element matching value _Val
		for (size_type _Idx = 0; _Idx != size(); ++_Idx)
			if (((System::Object^)_Val)->Equals(
				(System::Object^)at(_Idx)))
				{	// found a match, remove it
				erase_n(_Idx, _Idx + 1);
				return (true);
				}
		return (false);
		}

	virtual int IndexOf(value_type _Val) sealed
		= System::Collections::Generic::IList<_Value_t>::IndexOf
		{	// find index of element that matches _Val
		int _Idx = 0;

		for (; _Idx < size(); ++_Idx)
			if (at(_Idx) == _Val)
				return (_Idx);
		return (-1);
		}

	virtual void Insert(int _Idx, value_type _Val) sealed
		= System::Collections::Generic::IList<_Value_t>::Insert
		{	// insert _Val before _Idx
		insert_n(_Idx, 1, _Val);
		}

	virtual void RemoveAt(int _Idx) sealed
		= System::Collections::Generic::IList<_Value_t>::RemoveAt
		{	// erase element at _Idx
		erase_n(_Idx, _Idx + 1);
		}
	};

//
// TEMPLATE CLASS vector_select
//
template<typename _Value_t,
	bool _Is_ref>
	ref class vector_select
	:	public vector_base<_Value_t, _Is_ref>
	{	// varying size array of elements
public:
	// types
	typedef _Value_t _Gvalue_t;

	typedef vector_select<_Value_t, _Is_ref> _Mytype_t;
	typedef vector_base<_Gvalue_t, _Is_ref> _Mybase_t;
//	typedef _STLCLR IVector<_Gvalue_t> _Mycont_it;
//	typedef System::Collections::Generic::IEnumerable<_Gvalue_t> _Myenum_it;

//	typedef int size_type;
//	typedef int difference_type;
	typedef _Value_t value_type;
	typedef value_type% reference;
	typedef value_type% const_reference;

//	typedef _Mycont_it generic_container;
//	typedef value_type generic_value;

	// basics
	vector_select()
		:	_Mybase_t()
		{	// construct default
		}

	vector_select(vector_select% _Right)
		:	_Mybase_t(_Right)
		{	// construct by copying a vector
		}

	vector_select% operator=(vector_select% _Right)
		{	// assign
		_Mybase_t::operator=(_Right);
		return (*this);
		}

	// constructors
	explicit vector_select(size_type _Count)
		:	_Mybase_t(_Count)
		{	// construct from _Count * value_type()
		}

	vector_select(size_type _Count, value_type _Val)
		:	_Mybase_t(_Count, _Val)
		{	// construct from _Count * _Val
		}

	template<typename _InIt_t>
		vector_select(_InIt_t _First, _InIt_t _Last)
		:	_Mybase_t(_First, _Last)
		{	// construct from [_First, _Last)
		}

	vector_select(_Myenum_it^ _Right)
		:	_Mybase_t(_Right)
		{	// initialize with enumeration
		}
	};

//
// TEMPLATE CLASS vector_select: _Value_t REF SPECIALIZATION
//
template<typename _Value_t>
	ref class vector_select<_Value_t, true>
	:	public vector_base<_Value_t^, true>
	{	// varying size array of elements
public:
	// types
	typedef _Value_t^ _Gvalue_t;

	typedef vector_select<_Value_t, true> _Mytype_t;
	typedef vector_base<_Gvalue_t, true> _Mybase_t;
//	typedef _STLCLR IVector<_Gvalue_t> _Mycont_it;
//	typedef System::Collections::Generic::IEnumerable<_Gvalue_t> _Myenum_it;

//	typedef int size_type;
//	typedef int difference_type;
	typedef _Value_t value_type;
	typedef value_type% reference;
	typedef value_type% const_reference;

//	typedef _Mycont_it generic_container;
//	typedef value_type generic_value;

	// basics
	vector_select()
		:	_Mybase_t()
		{	// construct default
		}

	vector_select(vector_select% _Right)
		:	_Mybase_t(_Right)
		{	// construct by copying a vector
		}

	vector_select% operator=(vector_select% _Right)
		{	// assign
		_Mybase_t::operator=(_Right);
		return (*this);
		}

	// constructors
	explicit vector_select(size_type _Count)
		{	// construct from _Count * value_type()
		resize(_Count);
		}

	vector_select(size_type _Count, value_type _Val)
		{	// construct from _Count * _Val
		resize(_Count, _Val);
		}

	template<typename _InIt_t>
		vector_select(_InIt_t _First, _InIt_t _Last)
		:	_Mybase_t(_First, _Last)
		{	// construct from [_First, _Last)
		}

	vector_select(_Myenum_it^ _Right)
		:	_Mybase_t(_Right)
		{	// initialize with enumeration
		}

	// size controllers
	virtual void resize(size_type _Newsize) override
		{	// determine new length, padding with value_type elements
		value_type _Val;

		_Mybase_t::resize(_Newsize, %_Val);
		}

	void resize(size_type _Newsize, value_type _Val)
		{	// determine new length, padding with _Val elements
		_Mybase_t::resize(_Newsize, %_Val);
		}

	// accessors
	reference at(size_type _Pos) new
		{	// subscript mutable sequence with checking
		return (*_Mybase_t::at(_Pos));
		}

	property value_type default[size_type]
		{	// get or set subscripted element
		value_type get(size_type _Pos)
			{	// get _Pos element
			return (*_Mybase_t::at(_Pos));
			}

		void set(size_type _Pos, value_type _Val)
			{	// set _Pos element
			_Mybase_t::at(_Pos) = gcnew value_type(_Val);
			}
		};

	property value_type front_item
		{	// get or set first element
		value_type get()
			{	// get first element
			return (*_Mybase_t::front_item);
			}

		void set(value_type _Val)
			{	// set first element
			_Mybase_t::front_item = gcnew value_type(_Val);
			}
		};

	property value_type back_item
		{	// get or set last element
		value_type get()
			{	// get last element
			return (*_Mybase_t::back_item);
			}

		void set(value_type _Val)
			{	// set last element
			_Mybase_t::back_item = gcnew value_type(_Val);
			}
		};

	reference front() new
		{	// get first element of mutable sequence
		return (*_Mybase_t::front());
		}

	reference back() new
		{	// get last element of mutable sequence
		return (*_Mybase_t::back());
		}

	// mutators
//	void push_front(value_type _Val)

	void push_back(value_type _Val)
		{	// insert element at end
		_Mybase_t::push_back(%_Val);
		}

	void assign(size_type _Count, value_type _Val)
		{	// assign _Count * _Val
		_Mybase_t::assign(_Count, %_Val);
		}

	iterator insert(iterator _Where, value_type _Val)
		{	// insert _Val at _Where
		return (_Mybase_t::insert(_Where, %_Val));
		}

	void insert(iterator _Where,
		size_type _Count, value_type _Val)
		{	// insert _Count * _Val at _Where
		return (_Mybase_t::insert(_Where, _Count, %_Val));
		}
	};
	}	// namespace cliext::impl

//
// TEMPLATE CLASS vector
//
template<typename _Value_t>
	ref class vector
	:	public impl::vector_select<_Value_t,
		__is_ref_class(typename _Dehandle<_Value_t>::type)
			&& !is_handle<_Value_t>::value>
	{	// varying size array of elements
public:
	// types
	typedef vector<_Value_t> _Mytype_t;
	typedef impl::vector_select<_Value_t,
		__is_ref_class(typename _Dehandle<_Value_t>::type)
			&& !is_handle<_Value_t>::value> _Mybase_t;

//	typedef int size_type;
//	typedef int difference_type;
//	typedef _Value_t value_type;
//	typedef value_type% reference;
//	typedef value_type% const_reference;

//	typedef _Mycont_it generic_container;
//	typedef value_type generic_value;

	// basics
	vector()
		:	_Mybase_t()
		{	// construct default
		}

	vector(vector% _Right)
		:	_Mybase_t((_Mybase_t%)_Right)
		{	// construct by copying a vector
		}

	vector(vector^ _Right)
		:	_Mybase_t((_Mybase_t%)*_Right)
		{	// construct by copying a vector
		}

	vector% operator=(vector% _Right)
		{	// assign
		_Mybase_t::operator=(_Right);
		return (*this);
		}

	vector% operator=(vector^ _Right)
		{	// assign
		_Mybase_t::operator=(*_Right);
		return (*this);
		}

	// constructors
	explicit vector(size_type _Count)
		:	_Mybase_t(_Count)
		{	// construct from _Count * value_type()
		}

	vector(size_type _Count, value_type _Val)
		:	_Mybase_t(_Count, _Val)
		{	// construct from _Count * _Val
		}

	template<typename _InIt_t>
		vector(_InIt_t _First, _InIt_t _Last)
		:	_Mybase_t(_First, _Last)
		{	// construct from [_First, _Last)
		}

	vector(_Myenum_it^ _Right)
		:	_Mybase_t(_Right)
		{	// initialize with enumeration
		}

	// converters
	virtual System::Object^ Clone() override
		{	// clone the vector
		return (gcnew _Mytype_t(*this));
		}

	// mutators
	void swap(vector% _Right)
		{	// exchange contents with _Right
		_Mybase_t::swap(_Right);
		}
	};

//
// TEMPLATE COMPARISONS
//
template<typename _Value_t> inline
	bool operator==(vector<_Value_t>% _Left,
		vector<_Value_t>% _Right)
	{	// test if _Left == _Right
	vector<_Value_t>::size_type _Size = _Left.size();

	if (_Size != _Right.size())
		return (false);
	else
		{	// same length, compare elements
		for (int _Idx = 0; _Idx != _Size; ++_Idx)
			if (_Left.at(_Idx) != _Right.at(_Idx))
				return (false);
		return (true);
		}
	}

template<typename _Value_t> inline
	bool operator!=(vector<_Value_t>% _Left,
		vector<_Value_t>% _Right)
	{	// test if _Left != _Right
	return (!(_Left == _Right));
	}

template<typename _Value_t> inline
	bool operator<(vector<_Value_t>% _Left,
		vector<_Value_t>% _Right)
	{	// test if _Left < _Right
	vector<_Value_t>::size_type _Idx = 0;

	for (; _Idx != _Left.size() && _Idx != _Right.size(); ++_Idx)
		if (_Left.at(_Idx) < _Right.at(_Idx))
			return (true);
		else if (_Right.at(_Idx) < _Left.at(_Idx))
			return (false);
	return (_Idx == _Left.size() && _Idx != _Right.size());
	}

template<typename _Value_t> inline
	bool operator>=(vector<_Value_t>% _Left,
		vector<_Value_t>% _Right)
	{	// test if _Left >= _Right
	return (!(_Left < _Right));
	}

template<typename _Value_t> inline
	bool operator>(vector<_Value_t>% _Left,
		vector<_Value_t>% _Right)
	{	// test if _Left > _Right
	return (_Right < _Left);
	}

template<typename _Value_t> inline
	bool operator<=(vector<_Value_t>% _Left,
		vector<_Value_t>% _Right)
	{	// test if _Left <= _Right
	return (!(_Right < _Left));
	}

//
// TEMPLATE FUNCTION std::swap
//
template<typename _Value_t> inline
	void swap(vector<_Value_t>% _Left,
		vector<_Value_t>% _Right)
	{	// swap two vectors
	_Left.swap(_Right);
	}
}	// namespace cliext
#endif // _CLI_VECTOR_
