/*
===========================================================================
Copyright (C) 2000 - 2013, Raven Software, Inc.
Copyright (C) 2001 - 2013, Activision, Inc.
Copyright (C) 2013 - 2015, OpenJK contributors

This file is part of the OpenJK source code.

OpenJK is free software; you can redistribute it and/or modify it
under the terms of the GNU General Public License version 2 as
published by the Free Software Foundation.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program; if not, see <http://www.gnu.org/licenses/>.
===========================================================================
*/

////////////////////////////////////////////////////////////////////////////////////////
// RAVEN STANDARD TEMPLATE LIBRARY
//  (c) 2002 Activision
//
//
// Map
// ---
// This map is based on a red black tree, which guarentees balanced data, no mater what
// order elements are added.  The map uses a memory pool for storage of node data.
//
//
////////////////////////////////////////////////////////////////////////////////////////
#if !defined(RATL_MAP_VS_INC)
#define RATL_MAP_VS_INC


////////////////////////////////////////////////////////////////////////////////////////
// Includes
////////////////////////////////////////////////////////////////////////////////////////
#if defined(RA_DEBUG_LINKING)
	#pragma message("...including map_vs.h")
#endif
#if !defined(RATL_COMMON_INC)
	#include "ratl_common.h"
#endif
#if !defined(RATL_POOL_VS_INC)
	#include "pool_vs.h"
#endif
namespace ratl
{


// this is private to the set, but you have no access to it, soooo..

class tree_node
{
	int		mParent;
	int		mLeft;
	int		mRight;
public:
 	enum
	{
		RED_BIT			= 0x40000000, // to save space we are putting the red bool in a high bit
										// this is in the parent only
		NULL_NODE		= 0x3fffffff, // this must not have the red bit set
	};
	void	init()
	{
		mLeft	= NULL_NODE;
		mRight	= NULL_NODE;
		mParent	= NULL_NODE | RED_BIT;
	}
	int left() const
	{
		return mLeft;
	}
	int right() const
	{
		return mRight;
	}
	int parent() const
	{
		return mParent & (~RED_BIT);
	}
	bool red() const
	{
		return !!(mParent & RED_BIT);
	}
	void set_left(int l)
	{
		mLeft = l;
	}
	void set_right(int r)
	{
		mRight = r;
	}
	void set_parent(int p)
	{
		mParent &= RED_BIT;
		mParent	|= p;
	}
	void set_red(bool isRed)
	{
		if (isRed)
		{
			mParent |= RED_BIT;
		}
		else
		{
			mParent &= ~RED_BIT;
		}
	}
};

//fixme void *, comparison function pointer-ize this for code bloat.

template<class T, int IS_MULTI>
class tree_base
{
public:
    typedef T TStorageTraits;
	typedef typename T::TValue TTValue;
    ////////////////////////////////////////////////////////////////////////////////////
	// Capacity Enum
    ////////////////////////////////////////////////////////////////////////////////////
 	static const int CAPACITY = T::CAPACITY;

private:
	pool_base<TStorageTraits>		mPool;				// The Allocation Data Pool
	int								mRoot;
	int								mLastAdd;


	void link_left(int node,int left)
	{
		T::node(mPool[node]).set_left(left);
		if (left!=tree_node::NULL_NODE)
		{
			T::node(mPool[left]).set_parent(node);
		}
	}

	void link_right(int node,int right)
	{
		T::node(mPool[node]).set_right(right);
		if (right!=tree_node::NULL_NODE)
		{
			T::node(mPool[right]).set_parent(node);
		}
	}

    ////////////////////////////////////////////////////////////////////////////////////
	// This is the map internal recursive find function - do not use externally
    ////////////////////////////////////////////////////////////////////////////////////
	int			find_internal(const TTValue &key, int at) const
	{

		// FAIL TO FIND?
		//---------------
		if (at==tree_node::NULL_NODE)
		{
			return tree_node::NULL_NODE;
		}

		// Should We Search Left?
		//------------------------
		if      (key<mPool[at])
		{
			return find_internal(key, T::node(mPool[at]).left());
		}

		// Should We Search Right?
		//------------------------
		else if (mPool[at]<key)
		{
			return find_internal(key, T::node(mPool[at]).right());
		}

		// FOUND!
		//--------
		return at;
	}


    ////////////////////////////////////////////////////////////////////////////////////
	// This is the map internal recursive find function - do not use externally
    ////////////////////////////////////////////////////////////////////////////////////
	int			find_internal(const TTValue &key, int target, int at, int& parent) const
	{
		// FAIL TO FIND?
		//---------------
		if (at==tree_node::NULL_NODE)
		{
			parent = tree_node::NULL_NODE;
			return tree_node::NULL_NODE;
		}

		// FOUND!
		//--------
		if (at==target)
		{
			if (at==mRoot)
			{
				parent = tree_node::NULL_NODE;
			}
			return at;
		}

		// Should We Search Left?
		//------------------------
		if      (key<mPool[at])
		{
			parent = at;
			return find_internal(key, target, T::node(mPool[at]).left(), parent);
		}

		parent = at;
		return find_internal(key, target, T::node(mPool[at]).right(), parent);
	}


    ////////////////////////////////////////////////////////////////////////////////////
	// This is the map internal recursive insertion - do not use externally
    ////////////////////////////////////////////////////////////////////////////////////
	int			insert_internal(const TTValue &key, int &at)
	{
		// If At Is A NULL_NODE, We Have Found A Leaf.
		//----------------------------------------------
		if (at==tree_node::NULL_NODE)
		{
			if (mRoot==tree_node::NULL_NODE)
			{
				mRoot = mLastAdd;
			}
			return tree_node::NULL_NODE;					// There Are No Excess Red Children (No Childeren At All, Actually)
		}


		int		nxtChild;						// The Child We Will Eventually Add Underneath
		//int		altChild;						// The "other" Child
		bool	nxtRotateLeft;
		int		excessRedChild;					// If The Insert Results In An Excess Red Child, This Will Be It


		// Choose Which Side To Add The New Node Under
		//---------------------------------------------
		if (key < mPool[at])						// The Key Classes Must Support A < Operator
		{
			int tmp=T::node(mPool[at]).left();
			excessRedChild = insert_internal(key,tmp);
			link_left(at,tmp);//T::node(mPool[at]).set_left(tmp);

			if (tmp==tree_node::NULL_NODE)
			{

				link_left(at,mLastAdd);//T::node(mPool[at]).set_left(mLastAdd);			// If mLeft Of The Current Node Is NULL, We Must Have Added DIRECTLY Below nAt
			}
			nxtChild = T::node(mPool[at]).left();
			//altChild = T::node(mPool[at]).right();
			nxtRotateLeft = false;
		}
		else if (mPool[at] < key)
		{
			int tmp=T::node(mPool[at]).right();
			excessRedChild = insert_internal(key,tmp);
			link_right(at,tmp); // T::node(mPool[at]).set_right(tmp);

			if (tmp==tree_node::NULL_NODE)
			{
				link_right(at,mLastAdd); // T::node(mPool[at]).set_right(mLastAdd);			// If mRight Of The Current Node Is NULL, We Must Have Added DIRECTLY Below nAt
			}
			nxtChild = T::node(mPool[at]).right();
			//altChild = T::node(mPool[at]).left();
			nxtRotateLeft = true;
		}

		// Exact Match
		//-------------
		else
		{
			// the node of interest is at
			return tree_node::NULL_NODE;
		}


		// If The Add Resulted In An Excess Red Child, We Need To Change Colors And Rotate
		//---------------------------------------------------------------------------------
		if (excessRedChild!=tree_node::NULL_NODE)
		{
			// If Both Childeren Are Red, Just Switch And Be Done
			//----------------------------------------------------
			if (T::node(mPool[at]).right()!=tree_node::NULL_NODE &&
				T::node(mPool[at]).left()!=tree_node::NULL_NODE &&
				T::node(mPool[T::node(mPool[at]).right()]).red() &&
				T::node(mPool[T::node(mPool[at]).left()]).red())
			{
				set_colors(T::node(mPool[at]), true, false);
			}
			else
			{
				int	excessRedChildCompare =
					(nxtRotateLeft)?(T::node(mPool[nxtChild]).right()):(T::node(mPool[nxtChild]).left());
				if (excessRedChild==excessRedChildCompare)
				{
					// Single Rotation
					//-----------------
					rotate(at,   nxtRotateLeft);
				}
				else
				{
					if (nxtRotateLeft)
					{
						int nxt=T::node(mPool[at]).right();
						rotate(nxt, false);
						link_right(at,nxt); // T::node(mPool[at]).set_right(nxt);
					}
					else
					{
						int nxt=T::node(mPool[at]).left();
						rotate(nxt,true);
						link_left(at,nxt); // T::node(mPool[at]).set_left(nxt);
					}
					rotate(at,   nxtRotateLeft);
				}

				set_colors(T::node(mPool[at]), false, true);
			}
		}

		if (T::node(mPool[at]).red())
		{
			if (T::node(mPool[at]).left()!=tree_node::NULL_NODE &&
				T::node(mPool[T::node(mPool[at]).left()]).red())
			{
				return T::node(mPool[at]).left();
			}
			if (T::node(mPool[at]).right()!=tree_node::NULL_NODE &&
				T::node(mPool[T::node(mPool[at]).right()]).red())
			{
				return T::node(mPool[at]).right();
			}
		}
		return tree_node::NULL_NODE;
	}

    ////////////////////////////////////////////////////////////////////////////////////
	// This is the map internal recursive erase - do not use externally
    ////////////////////////////////////////////////////////////////////////////////////
	bool	erase_internal(const TTValue &key, int& at)
	{
		// If At Is A NULL_NODE, We Have Found A Leaf.
		//---------------------------------------------
		if (at==tree_node::NULL_NODE)
		{
			return true;
		}

		//==============================================================================
		// Now The Question Is, Do We Need To Continue Searching?
		//==============================================================================


		// Recurse To The Left?
		//----------------------
		if (key < mPool[at])
		{
			int a=T::node(mPool[at]).left();
			bool r=erase_internal(key, a);
			link_left(at,a); // T::node(mPool[at]).set_left(a);
			if (!r)		// If It Was Not Red, We Need To Rebalance
			{
				return rebalance(at, true);
			}
			return true;
		}

		// Recurse To The Right?
		//-----------------------
		if (mPool[at] < key)
		{
			int a=T::node(mPool[at]).right();
			bool r=erase_internal(key, a);
			link_right(at,a); // T::node(mPool[at]).set_right(a);
			if (!r)		// If It Was Not Red, We Need To Rebalance
			{
				return rebalance(at, false);
			}
			return true;
		}

		//==============================================================================
		// At This Point, We Must Have Discovered An Exact Match For Our Key
		//==============================================================================


		// Are There Any Open Childeren Slots?
		//-------------------------------------
		if (T::node(mPool[at]).left()==tree_node::NULL_NODE || T::node(mPool[at]).right()==tree_node::NULL_NODE)
		{
			bool	atWasRed	= T::node(mPool[at]).red();
			int		oldAt		= at;

			at = (T::node(mPool[at]).left()==tree_node::NULL_NODE)?(T::node(mPool[at]).right()):(T::node(mPool[at]).left());	// If Left Is Null, At Goes Right

			// Actually Free It!
			//-------------------
			mPool.free(oldAt);

			// If We Are Now At A Null Node, Just Return
			//-------------------------------------------
			if (at==tree_node::NULL_NODE)
			{
				return atWasRed;
			}

			// Otherwise, Mark The New Child As Red, And Return That Fact Up
			//---------------------------------------------------------------
			T::node(mPool[at]).set_red(false);
			return true;
		}


		//==============================================================================
		// There Are No Childeren To Link With, We Are In The Middle Of The Tree.
		// We Need To Find An Open Leaf, Swap Data With That Leaf, and Then Go Find It
		//==============================================================================

		// Find A Successor Leaf
		//-----------------------
		int at_parent = T::node(mPool[at]).parent();
		int	successor = T::node(mPool[at]).right();

		int parent_successor=-1;
		while(T::node(mPool[successor]).left()!=tree_node::NULL_NODE)
		{
			parent_successor=successor;
			successor = T::node(mPool[successor]).left();
		}

		int	successor_right = T::node(mPool[successor]).right();


		link_left(successor,T::node(mPool[at]).left());

		bool red=T::node(mPool[successor]).red();
		T::node(mPool[successor]).set_red(T::node(mPool[at]).red());
		T::node(mPool[at]).set_red(red);

		if (parent_successor!=-1)
		{

			link_right(successor,T::node(mPool[at]).right());
			link_left(parent_successor,at);
		}
		else
		{
			link_right(successor,at);
		}

		if (at_parent!=tree_node::NULL_NODE)
		{
			if (T::node(mPool[at_parent]).left()==at)
			{
				//my parents left child
				link_left(at_parent,successor);
			}
			else
			{
				assert(T::node(mPool[at_parent]).right()==at); // better be my parents right child then
				link_right(at_parent,successor);
			}
		}

		link_left(at,tree_node::NULL_NODE);
		link_right(at,successor_right);

		at=successor;
		int a=T::node(mPool[at]).right();
		bool r=erase_internal(key, a);
		link_right(at,a); // T::node(mPool[at]).set_right(a);
		// And Keep Going
		//----------------
		if (!r)		// If It Was Not Red, We Need To Rebalance
		{
			return rebalance(at, false);
		}
		return true;
	}

    ////////////////////////////////////////////////////////////////////////////////////
	// HELPER: Change the color of a node and children
    ////////////////////////////////////////////////////////////////////////////////////
	void		set_colors(tree_node& at, bool red, bool childRed)
	{
		at.set_red(red);
		if (at.left()!=tree_node::NULL_NODE)
		{
			T::node(mPool[at.left()]).set_red(childRed);
		}
		if (at.right()!=tree_node::NULL_NODE)
		{
			T::node(mPool[at.right()]).set_red(childRed);
		}
	}

    ////////////////////////////////////////////////////////////////////////////////////
	// HELPER: Rotate node located at (at) either left or right
    ////////////////////////////////////////////////////////////////////////////////////
	void		rotate(int& at, bool left)
	{
		int	t;
		if (left)
		{
			assert(T::node(mPool[at]).right()!=tree_node::NULL_NODE);

			t					= T::node(mPool[at]).right();
			link_right(at,T::node(mPool[t]).left()); // T::node(mPool[at]).set_right(T::node(mPool[t]).left());
			link_left(t,at);	// T::node(mPool[t]).set_left(at);
			at					= t;
		}
		else
		{
			assert(T::node(mPool[at]).left()!=tree_node::NULL_NODE);

			t					= T::node(mPool[at]).left();
			link_left(at,T::node(mPool[t]).right()); // T::node(mPool[at]).set_left(T::node(mPool[t]).right());
			link_right(t,at);	//T::node(mPool[t]).set_right(at);
			at					= t;
		}
	}

    ////////////////////////////////////////////////////////////////////////////////////
	// HELPER: Localally rebalance the tree here
    ////////////////////////////////////////////////////////////////////////////////////
	bool		rebalance(int& at, bool left)
	{
		// Decide Which Child, Left Or Right?
		//------------------------------------
		int	w = (left)?(T::node(mPool[at]).right()):(T::node(mPool[at]).left());	// w is the child of at
		if (w==tree_node::NULL_NODE)
		{
			bool	atWasRed = T::node(mPool[at]).red();			// Remember what mPool[at] WAS
			T::node(mPool[at]).set_red(false);						// Mark mPool[at] as BLACK
			return  atWasRed;						// Return what it used to be
		}


		// Get A Reference To The Child W, And Record It's Children x And y
		//------------------------------------------------------------------
		tree_node&	wAt = T::node(mPool[w]);
		int		x = (left)?(wAt.left()):(wAt.right());// x and y are the grand children of at
		int		y = (left)?(wAt.right()):(wAt.left());


		// Is The Child Black?
		//---------------------
		if (!wAt.red())
		{
			// If Both X and Y are Empty, Or Both Are Red
			//--------------------------------------------
			if ((x==tree_node::NULL_NODE || !T::node(mPool[x]).red()) &&
				(y==tree_node::NULL_NODE || !T::node(mPool[y]).red()))
			{
				bool	atWasRed = T::node(mPool[at]).red();		// Remember what mPool[at] WAS
				T::node(mPool[at]).set_red(false);		// Mark mPool[at] as BLACK
				wAt.set_red(true);					// Mark The Child As RED
				return  atWasRed;					// Return what it used to be
			}

			// If Y Is Valid
			//---------------
			if (y!=tree_node::NULL_NODE && T::node(mPool[y]).red())
			{
				wAt.set_red(T::node(mPool[at]).red());
				rotate(at, left);
				T::node(mPool[T::node(mPool[at]).left()]).set_red(false);
				T::node(mPool[T::node(mPool[at]).right()]).set_red(false);
				return true;
			}

			// X Must Be Valid
			//-----------------
			T::node(mPool[x]).set_red(T::node(mPool[at]).red());
			T::node(mPool[at]).set_red(false);

			if (left)
			{
				int r=T::node(mPool[at]).right();
				rotate(r,false);
				link_right(at,r); // T::node(mPool[at]).set_right(r);
			}
			else
			{
				int r=T::node(mPool[at]).left();
				rotate(r,true);
				link_left(at,r); // T::node(mPool[at]).set_left(r);
			}
			rotate(at, left);

			return true;
		}

		// The Child Must Have Been Red
		//------------------------------
		wAt.set_red(T::node(mPool[at]).red());				// Switch Child Color
		T::node(mPool[at]).set_red(true);
		rotate(at, left);					// Rotate At

		// Select The Next Rebalance Child And Recurse
		//----------------------------------------------
		if (left)
		{
			int r=T::node(mPool[at]).left();
			rebalance(r,true);
			link_left(at,r); // T::node(mPool[at]).set_left(r);
		}
		else
		{
			int r=T::node(mPool[at]).right();
			rebalance(r,false);
			link_right(at,r); //T::node(mPool[at]).set_right(r);
		}
		return true;
	}
    ////////////////////////////////////////////////////////////////////////////////////
	// This is the map internal recursive front function - do not use externally
    ////////////////////////////////////////////////////////////////////////////////////
	int			front(int at) const
	{
		if (at!=tree_node::NULL_NODE &&
			T::node(mPool[at]).left()!=tree_node::NULL_NODE)
		{
			return front(T::node(mPool[at]).left());
		}
		return at;
	}

    ////////////////////////////////////////////////////////////////////////////////////
	// This is the map internal recursive back function - do not use externally
    ////////////////////////////////////////////////////////////////////////////////////
	int			back(int at) const
	{
		if (at!=tree_node::NULL_NODE && T::node(mPool[at]).right()!=tree_node::NULL_NODE)
		{
			return back(T::node(mPool[at]).right());
		}
		return at;
	}
protected:
	int			front() const
	{
		return front(mRoot);
	}

	int			back() const
	{
		return back(mRoot);
	}

    ////////////////////////////////////////////////////////////////////////////////////
	// This is the map internal recursive next function - do not use externally
    ////////////////////////////////////////////////////////////////////////////////////
	int			next(int at) const
	{
		assert(at!=tree_node::NULL_NODE);
		const TTValue&	kAt = mPool[at];
		const tree_node&	nAt = T::node(kAt);
		if (nAt.right()!=tree_node::NULL_NODE)
		{
			return front(nAt.right());
		}

		int		child	= at;
		int		parent	= tree_node::NULL_NODE;
		find_internal(kAt, at, mRoot, parent);

		while(parent!=tree_node::NULL_NODE && (child==T::node(mPool[parent]).right()))
		{
			child = parent;
			find_internal(mPool[parent], parent, mRoot, parent);
		}
		return parent;
	}

    ////////////////////////////////////////////////////////////////////////////////////
	// This is the map internal recursive previous function - do not use externally
    ////////////////////////////////////////////////////////////////////////////////////
	int			previous(int at) const
	{
		assert(at!=tree_node::NULL_NODE);
		const TTValue&	kAt = mPool[at];
		const tree_node&		nAt = T::node(mPool[at]);
		if (kAt.left()!=tree_node::NULL_NODE)
		{
			return back(kAt.left());
		}

		int		child	= at;
		int		parent	= tree_node::NULL_NODE;
		find_internal(nAt, at, mRoot, parent);

		while(parent!=tree_node::NULL_NODE && (child==T::node(mPool[parent]).left()))
		{
			child = parent;
			find_internal(mPool[parent], parent, mRoot, parent);
		}
		return parent;
	}



public:

    ////////////////////////////////////////////////////////////////////////////////////
	// Constructor
    ////////////////////////////////////////////////////////////////////////////////////
    tree_base() : mRoot(tree_node::NULL_NODE), mLastAdd(-1)
	{
	}


	////////////////////////////////////////////////////////////////////////////////////
	// How Many Objects Are In This Map
    ////////////////////////////////////////////////////////////////////////////////////
	int			size() const
	{
		return (mPool.size());
	}

	////////////////////////////////////////////////////////////////////////////////////
	// Are There Any Objects In This Map?
    ////////////////////////////////////////////////////////////////////////////////////
	bool		empty() const
	{
		return (mPool.empty());
	}

	////////////////////////////////////////////////////////////////////////////////////
	// Is This Map Filled?
    ////////////////////////////////////////////////////////////////////////////////////
	bool		full() const
	{
		return (mPool.full());
	}

	////////////////////////////////////////////////////////////////////////////////////
	// Clear All Data From The Map
    ////////////////////////////////////////////////////////////////////////////////////
	void		clear()
	{
		mRoot = tree_node::NULL_NODE;
		mPool.clear();
	}

    ////////////////////////////////////////////////////////////////////////////////////
	// Adds Element Value At Location Key  - O(log n)
    ////////////////////////////////////////////////////////////////////////////////////
	void alloc_key(const TTValue &key)
	{

		//fixme handle duplicates more sensibly?
		assert(!full());
		mLastAdd = mPool.alloc(key);			// Grab A New One
		T::node(mPool[mLastAdd]).init();	// Initialize Our Data And Color
	}

    ////////////////////////////////////////////////////////////////////////////////////
	// Allocs an item, when filled, call insert_alloced
    ////////////////////////////////////////////////////////////////////////////////////
	TTValue & alloc_key()
	{
		assert(!full());
		mLastAdd = mPool.alloc();			// Grab A New One
		T::node(mPool[mLastAdd]).init();	// Initialize Our Data And Color
		return mPool[mLastAdd];
	}

    ////////////////////////////////////////////////////////////////////////////////////
	// Allocs an item (raw), when constucted, call insert_alloced
    ////////////////////////////////////////////////////////////////////////////////////
	TRatlNew *alloc_key_raw()
	{
		assert(!full());
		TRatlNew *ret=mPool.alloc_raw();			// Grab A New One
		mLastAdd = mPool.pointer_to_index(ret);
		T::node(mPool[mLastAdd]).init();	// Initialize Our Data And Color
		return ret;
	}
	template<class CAST_TO>
	CAST_TO *verify_alloc_key(CAST_TO *p) const
	{
		return mPool.verify_alloc(p);
	}

	void insert_alloced_key()
	{
		assert(mLastAdd>=0&&mLastAdd<CAPACITY);
		assert(!IS_MULTI || find_index(mPool[mLastAdd])!=tree_node::NULL_NODE); //fixme handle duplicates more sensibly?

		insert_internal(mPool[mLastAdd],mRoot);
		assert(mRoot!=tree_node::NULL_NODE);
		T::node(mPool[mRoot]).set_red(false);
		T::node(mPool[mRoot]).set_parent(tree_node::NULL_NODE);
	}

	int index_of_alloced_key() const
	{
		assert(mLastAdd>=0&&mLastAdd<CAPACITY);
		return mLastAdd;
	}
    ////////////////////////////////////////////////////////////////////////////////////
	// Removes The Element Pointed To At (it) And Decrements (it)  - O((log n)^2)
    ////////////////////////////////////////////////////////////////////////////////////
	void erase_index(int i)
	{
		assert(i>=0&&i<CAPACITY);
		assert(mRoot!=tree_node::NULL_NODE);

		//fixme this is lame to have to look by key to erase
		erase_internal(mPool[i],mRoot);
		if (mRoot!=tree_node::NULL_NODE)
		{
			T::node(mPool[mRoot]).set_red(false);
			T::node(mPool[mRoot]).set_parent(tree_node::NULL_NODE);
		}
	}
    ////////////////////////////////////////////////////////////////////////////////////
	// Seach For A Given Key.  Will Return -1 if Failed  - O(log n)
    ////////////////////////////////////////////////////////////////////////////////////
	int	find_index(const TTValue &key) const
	{
		return find_internal(key, mRoot);
	}
	const TTValue &index_to_key(int i) const
	{
		assert(i>=0&&i<CAPACITY);
		return mPool[i];
	}

	//fixme lower bound, upper bound, equal range


};



template<class T,int IS_MULTI>
class set_base : public tree_base<T,IS_MULTI>
{

public:
    typedef T TStorageTraits;
	typedef typename T::TValue TTValue;
    ////////////////////////////////////////////////////////////////////////////////////
	// Capacity Enum
    ////////////////////////////////////////////////////////////////////////////////////
	static const int CAPACITY = T::CAPACITY;

    ////////////////////////////////////////////////////////////////////////////////////
	// Adds Element Value At Location Key  - O(log n)
    ////////////////////////////////////////////////////////////////////////////////////
	void insert(const TTValue &key)
	{

		assert(!IS_MULTI || find_index(key)==tree_node::NULL_NODE); //fixme handle duplicates more sensibly?

		alloc_key(key);
		tree_base<T, IS_MULTI>::insert_alloced_key();

	}

    ////////////////////////////////////////////////////////////////////////////////////
	// Allocs an item, when filled, call insert_alloced
    ////////////////////////////////////////////////////////////////////////////////////
	TTValue & alloc()
	{
		return tree_base<T, IS_MULTI>::alloc_key();
	}

    ////////////////////////////////////////////////////////////////////////////////////
	// Allocs an item (raw), when constucted, call insert_alloced
    ////////////////////////////////////////////////////////////////////////////////////
	TRatlNew *alloc_raw()
	{
		return tree_base<T, IS_MULTI>::alloc_key_raw();
	}
	template<class CAST_TO>
	CAST_TO *verify_alloc(CAST_TO *p) const
	{
		return verify_alloc_key(p);
	}

	void insert_alloced()
	{
		tree_base<T, IS_MULTI>::insert_alloced_key();
	}

	////////////////////////////////////////////////////////////////////////////////////
	// Removes The First Element With Key (key)  - O(log n)
    ////////////////////////////////////////////////////////////////////////////////////
	void		erase(const TTValue &key)
	{
		//fixme this is a double search currently
		int i=find_index(key);
		if (i!=tree_node::NULL_NODE)
		{
			tree_base<T, IS_MULTI>::erase_index(i);
		}
	}

	////////////////////////////////////////////////////////////////////////////////////
	// Iterator
	//
	// A map is sorted in ascending order on the KEY type.  ++ and -- are both
	// O((log n)^2) operations
	//
    ////////////////////////////////////////////////////////////////////////////////////
	class iterator
	{
		friend class set_base<TStorageTraits,IS_MULTI>;
		friend class const_iterator;

		int			mLoc;
		set_base<TStorageTraits,IS_MULTI>*	mOwner;

	public:
		iterator(set_base<TStorageTraits,IS_MULTI> *owner=0, int loc=tree_node::NULL_NODE) :
			mOwner(owner),
			mLoc(loc)
		{
		}
		iterator(const iterator &o) :
			mOwner(o.mOwner),
			mLoc(o.mLoc)
		{
		}

		void operator=(const iterator &o)
		{
			mOwner=o.mOwner;
			mLoc=o.mLoc;
		}

		iterator	operator++()		//prefix
		{
			assert(mOwner);
			mLoc=mOwner->next(mLoc);
			return *this;
		}
		iterator	operator++(int)		//postfix
		{
			assert(mOwner);
			iterator old(*this);
			mLoc=mOwner->next(mLoc);
			return old;
		}

		iterator	operator--()		//prefix
		{
			assert(mOwner);
			mLoc=mOwner->previous(mLoc);
			return *this;
		}
		iterator	operator--(int)		//postfix
		{
			assert(mOwner);
			iterator old(*this);
			mLoc=mOwner->previous(mLoc);
			return old;
		}

		bool	operator!=(const iterator p) const	{return (mLoc!=p.mLoc || mOwner!=p.mOwner);}
		bool	operator==(const iterator p) const 	{return (mLoc==p.mLoc && mOwner==p.mOwner);}

		const TTValue &	operator*() const
		{
			assert(mOwner);
			assert(mLoc>=0&&mLoc<CAPACITY); // deferencing end()?
			return mOwner->index_to_key(mLoc);
		}
		const TTValue *	operator->() const
		{
			assert(mOwner);
			assert(mLoc>=0&&mLoc<CAPACITY); // deferencing end()?
			return &mOwner->index_to_key(mLoc);
		}
	};
	class const_iterator
	{
		friend class set_base<TStorageTraits,IS_MULTI>;

		int		mLoc;

		const set_base<TStorageTraits,IS_MULTI>*		mOwner;

	public:
		const_iterator(const set_base<TStorageTraits,IS_MULTI> *owner=0, int loc=tree_node::NULL_NODE) :
			mOwner(owner),
			mLoc(loc)
		{
		}
		const_iterator(const const_iterator &o) :
			mOwner(o.mOwner),
			mLoc(o.mLoc)
		{
		}
		const_iterator(const iterator &o) :
			mOwner(o.mOwner),
			mLoc(o.mLoc)
		{
		}
		void operator=(const const_iterator &o)
		{
			mOwner=o.mOwner;
			mLoc=o.mLoc;
		}
		void operator=(const iterator &o)
		{
			mOwner=o.mOwner;
			mLoc=o.mLoc;
		}


		const_iterator	operator++()		//prefix
		{
			assert(mOwner);
			mLoc=mOwner->next(mLoc);
			return *this;
		}
		const_iterator	operator++(int)		//postfix
		{
			assert(mOwner);
			const_iterator old(*this);
			mLoc=mOwner->next(mLoc);
			return old;
		}

		const_iterator	operator--()		//prefix
		{
			assert(mOwner);
			mLoc=mOwner->previous(mLoc);
			return *this;
		}
		const_iterator	operator--(int)		//postfix
		{
			assert(mOwner);
			const_iterator old(*this);
			mLoc=mOwner->previous(mLoc);
			return old;
		}

		bool	operator!=(const const_iterator p) const	{return (mLoc!=p.mLoc || mOwner!=p.mOwner);}
		bool	operator==(const const_iterator p) const 	{return (mLoc==p.mLoc && mOwner==p.mOwner);}
		bool	operator!=(const iterator p) const	{return (mLoc!=p.mLoc || mOwner!=p.mOwner);}
		bool	operator==(const iterator p) const 	{return (mLoc==p.mLoc && mOwner==p.mOwner);}

		const TTValue &	operator*() const
		{
			assert(mOwner);
			assert(mLoc>=0&&mLoc<CAPACITY); // deferencing end()?
			return mOwner->index_to_key(mLoc);
		}
		const TTValue *	operator->() const
		{
			assert(mOwner);
			assert(mLoc>=0&&mLoc<CAPACITY); // deferencing end()?
			return &mOwner->index_to_key(mLoc);
		}
	};
	friend class iterator;
	friend class const_iterator;

    ////////////////////////////////////////////////////////////////////////////////////
	// Seach For A Given Key.  Will Return end() if Failed  - O(log n)
    ////////////////////////////////////////////////////////////////////////////////////
	iterator	find(const TTValue &key)
	{
		return iterator(this,find_index(key));
	}

    ////////////////////////////////////////////////////////////////////////////////////
	// Get An Iterator To The Smallest Element  - O(log n)
    ////////////////////////////////////////////////////////////////////////////////////
	iterator	begin()
	{
		return iterator(this, tree_base<T, IS_MULTI>::front());
	}

	////////////////////////////////////////////////////////////////////////////////////
	// Get An Iterator To The Largest Element  - O(log n)
    ////////////////////////////////////////////////////////////////////////////////////
	iterator	rbegin()
	{
		return iterator(this, tree_base<T, IS_MULTI>::back());
	}

    ////////////////////////////////////////////////////////////////////////////////////
	// The Invalid Iterator, Use As A Stop Condition In Your For Loops  - O(1)
    ////////////////////////////////////////////////////////////////////////////////////
	iterator	end()
	{
		return iterator(this);
	}

    ////////////////////////////////////////////////////////////////////////////////////
	// Seach For A Given Key.  Will Return end() if Failed  - O(log n)
    ////////////////////////////////////////////////////////////////////////////////////
	const_iterator	find(const TTValue &key) const
	{
		return const_iterator(this, find_index(key));
	}

    ////////////////////////////////////////////////////////////////////////////////////
	// Get An const_iterator To The Smallest Element  - O(log n)
    ////////////////////////////////////////////////////////////////////////////////////
	const_iterator	begin() const
	{
		return const_iterator(this, tree_base<T, IS_MULTI>::front());
	}

	////////////////////////////////////////////////////////////////////////////////////
	// Get An const_iterator To The Largest Element  - O(log n)
    ////////////////////////////////////////////////////////////////////////////////////
	const_iterator	rbegin() const
	{
		return const_iterator(this, tree_base<T, IS_MULTI>::back());
	}

    ////////////////////////////////////////////////////////////////////////////////////
	// The Invalid const_iterator, Use As A Stop Condition In Your For Loops  - O(1)
    ////////////////////////////////////////////////////////////////////////////////////
	const_iterator	end() const
	{
		return const_iterator(this);
	}
    ////////////////////////////////////////////////////////////////////////////////////
	// Removes The Element Pointed To At (it) And Decrements (it)  - O((log n)^2)
    ////////////////////////////////////////////////////////////////////////////////////
	void		erase(const iterator &it)
	{
		assert(it.mOwner==this && it.mLoc>=0&&it.mLoc<CAPACITY);
		erase_index(it.mLoc);
	}


    ////////////////////////////////////////////////////////////////////////////////////
	//
    ////////////////////////////////////////////////////////////////////////////////////
	iterator	lower_bound(const TTValue &key)
	{
		return iterator(this, find_index(key));
	}

    ////////////////////////////////////////////////////////////////////////////////////
	//
    ////////////////////////////////////////////////////////////////////////////////////
	iterator	upper_bound(const TTValue &key)
	{
		// fixme, this don't work
		iterator ubound(this, find_index(key));
		++ubound;
		return ubound;
	}

};


template<class T, int ARG_CAPACITY>
class set_vs : public set_base<storage::value_semantics_node<T,ARG_CAPACITY,tree_node>,0 >
{
public:
	typedef typename storage::value_semantics_node<T,ARG_CAPACITY,tree_node> TStorageTraits;
	typedef typename TStorageTraits::TValue TTValue;
	static const int CAPACITY = ARG_CAPACITY;
	set_vs() {}
};

template<class T, int ARG_CAPACITY>
class set_os : public set_base<storage::object_semantics_node<T,ARG_CAPACITY,tree_node>,0 >
{
public:
	typedef typename storage::object_semantics_node<T,ARG_CAPACITY,tree_node> TStorageTraits;
	typedef typename TStorageTraits::TValue TTValue;
	static const int CAPACITY = ARG_CAPACITY;
	set_os() {}
};

template<class T, int ARG_CAPACITY, int ARG_MAX_CLASS_SIZE>
class set_is : public set_base<storage::virtual_semantics_node<T,ARG_CAPACITY,ARG_MAX_CLASS_SIZE,tree_node>,0 >
{
public:
	typedef typename storage::virtual_semantics_node<T,ARG_CAPACITY,ARG_MAX_CLASS_SIZE,tree_node> TStorageTraits;
	typedef typename TStorageTraits::TValue TTValue;
	static const int CAPACITY = ARG_CAPACITY;
	static const int MAX_CLASS_SIZE	= ARG_MAX_CLASS_SIZE;
	set_is() {}
};


template<class K,class V,int IS_MULTI>
class map_base : public tree_base<K,IS_MULTI>
{
public:
    typedef K TKeyStorageTraits;
	typedef typename K::TValue TKTValue;

    typedef V TValueStorageTraits;
	typedef typename V::TValue TVTValue;
    ////////////////////////////////////////////////////////////////////////////////////
	// Capacity Enum
    ////////////////////////////////////////////////////////////////////////////////////
	static const int CAPACITY = K::CAPACITY;
private:
	array_base<TValueStorageTraits>	mValues;
public:
	map_base()
	{
		compile_assert<K::CAPACITY==V::CAPACITY>();
	}

	void clear()
	{
		tree_base<K,IS_MULTI>::clear();
		mValues.clear();
	}
    ////////////////////////////////////////////////////////////////////////////////////
	// Adds Element Value At Location Key  - O(log n)
    ////////////////////////////////////////////////////////////////////////////////////
	void insert(const TKTValue &key,const TVTValue &value)
	{
		assert(!IS_MULTI || (tree_base<K,IS_MULTI>::find_index(key)==tree_node::NULL_NODE)); //fixme handle duplicates more sensibly?

		tree_base<K,IS_MULTI>::alloc_key(key);
		tree_base<K,IS_MULTI>::insert_alloced_key();
		assert(check_validity());
		mValues.construct(tree_base<K,IS_MULTI>::index_of_alloced_key(),value);
	}

    ////////////////////////////////////////////////////////////////////////////////////
	// Adds Element Value At Location Key  returns a reference
    ////////////////////////////////////////////////////////////////////////////////////
	TVTValue &insert(const TKTValue &key)
	{

		assert(!IS_MULTI || (tree_base<K,IS_MULTI>::find_index(key)==tree_node::NULL_NODE)); //fixme handle duplicates more sensibly?

		tree_base<K,IS_MULTI>::alloc_key(key);
		tree_base<K,IS_MULTI>::insert_alloced_key();

		int idx=tree_base<K,IS_MULTI>::index_of_alloced_key();
		assert(check_validity());
		mValues.construct(idx);
		return mValues[idx];
	}
    ////////////////////////////////////////////////////////////////////////////////////
	// Adds Element Value At Location Key  returns a rew pointer for placement new
    ////////////////////////////////////////////////////////////////////////////////////
	TRatlNew *insert_raw(const TKTValue &key)
	{

		assert(!IS_MULTI || (tree_base<K,IS_MULTI>::find_index(key)==tree_node::NULL_NODE)); //fixme handle duplicates more sensibly?

		tree_base<K,IS_MULTI>::alloc_key(key);
		tree_base<K,IS_MULTI>::insert_alloced_key();
		assert(check_validity());
		return mValues.alloc_raw(tree_base<K,IS_MULTI>::index_of_alloced_key());
	}

    ////////////////////////////////////////////////////////////////////////////////////
	// After calling alloc_key*, you may call this to alloc the value
    ////////////////////////////////////////////////////////////////////////////////////
	TVTValue &alloc_value()
	{
		mValues.construct(tree_base<K,IS_MULTI>::index_of_alloced_key());
		return mValues[tree_base<K,IS_MULTI>::index_of_alloced_key()];
	}

    ////////////////////////////////////////////////////////////////////////////////////
	// After calling alloc_key*, you may call this to alloc_raw the value
    ////////////////////////////////////////////////////////////////////////////////////
	TRatlNew *alloc_value_raw()
	{
		return mValues.alloc_raw(tree_base<K,IS_MULTI>::index_of_alloced_key());
	}

	template<class CAST_TO>
	CAST_TO *verify_alloc(CAST_TO *p) const
	{
		return mValues.verify_alloc(p);
	}

	////////////////////////////////////////////////////////////////////////////////////
	// Removes The First Element With Key (key)  - O(log n)
    ////////////////////////////////////////////////////////////////////////////////////
	void		erase(const TKTValue &key)
	{
		//fixme this is a double search currently
		int i=tree_base<K,IS_MULTI>::find_index(key);
		if (i!=tree_node::NULL_NODE)
		{
			tree_base<K,IS_MULTI>::erase_index(i);
			mValues.destruct(i);
		}
	}

	////////////////////////////////////////////////////////////////////////////////////
	// Iterator
	//
	// A map is sorted in ascending order on the KEY type.  ++ and -- are both
	// O((log n)^2) operations
	//
    ////////////////////////////////////////////////////////////////////////////////////
	class const_iterator;
	class iterator
	{
		friend class map_base<K,V, IS_MULTI>;
		friend class const_iterator;

		int							mLoc;
		map_base<K,V, IS_MULTI>*	mOwner;

	public:
		iterator(map_base<K,V, IS_MULTI> *owner=0, int loc=tree_node::NULL_NODE) :
			mLoc(loc),
			mOwner(owner)
		{
		}
		iterator(const iterator &o) :
			mLoc(o.mLoc),
			mOwner(o.mOwner)
		{
		}

		void operator=(const iterator &o)
		{
			mOwner=o.mOwner;
			mLoc=o.mLoc;
		}

		iterator	operator++()		//prefix
		{
			assert(mOwner);
			mLoc=mOwner->next(mLoc);
			return *this;
		}
		iterator	operator++(int)		//postfix
		{
			assert(mOwner);
			iterator old(*this);
			mLoc=mOwner->next(mLoc);
			return old;
		}

		iterator	operator--()		//prefix
		{
			assert(mOwner);
			mLoc=mOwner->previous(mLoc);
			return *this;
		}
		iterator	operator--(int)		//postfix
		{
			assert(mOwner);
			iterator old(*this);
			mLoc=mOwner->previous(mLoc);
			return old;
		}

		bool	operator!=(const iterator &p) const	{return (mLoc!=p.mLoc || mOwner!=p.mOwner);}
		bool	operator==(const iterator &p) const 	{return (mLoc==p.mLoc && mOwner==p.mOwner);}

		TVTValue &	operator*() const
		{
			assert(mOwner);
			assert(mLoc>=0&&mLoc<CAPACITY); // deferencing end()?
			return mOwner->mValues[mLoc];
		}
		const TKTValue &	key() const
		{
			assert(mOwner);
			assert(mLoc>=0&&mLoc<CAPACITY); // deferencing end()?
			return mOwner->index_to_key(mLoc);
		}
		TVTValue &	value() const
		{
			assert(mOwner);
			assert(mLoc>=0&&mLoc<CAPACITY); // deferencing end()?
			return mOwner->mValues[mLoc];
		}
		TVTValue *	operator->() const
		{
			assert(mOwner);
			assert(mLoc>=0&&mLoc<CAPACITY); // deferencing end()?
			return &mOwner->mValues[mLoc];
		}
	};
	class const_iterator
	{
		friend class map_base<K,V,IS_MULTI>;

		int									mLoc;
		const map_base<K,V,IS_MULTI>*		mOwner;

	public:
		const_iterator(const map_base<K,V,IS_MULTI> *owner=0, int loc=tree_node::NULL_NODE) :
			mOwner(owner),
			mLoc(loc)
		{
		}
		const_iterator(const const_iterator &o) :
			mOwner(o.mOwner),
			mLoc(o.mLoc)
		{
		}
		const_iterator(const iterator &o) :
			mOwner(o.mOwner),
			mLoc(o.mLoc)
		{
		}
		void operator=(const const_iterator &o)
		{
			mOwner=o.mOwner;
			mLoc=o.mLoc;
		}
		void operator=(const iterator &o)
		{
			mOwner=o.mOwner;
			mLoc=o.mLoc;
		}


		const_iterator	operator++()		//prefix
		{
			assert(mOwner);
			mLoc=mOwner->next(mLoc);
			return *this;
		}
		const_iterator	operator++(int)		//postfix
		{
			assert(mOwner);
			const_iterator old(*this);
			mLoc=mOwner->next(mLoc);
			return old;
		}

		const_iterator	operator--()		//prefix
		{
			assert(mOwner);
			mLoc=mOwner->previous(mLoc);
			return *this;
		}
		const_iterator	operator--(int)		//postfix
		{
			assert(mOwner);
			const_iterator old(*this);
			mLoc=mOwner->previous(mLoc);
			return old;
		}

		bool	operator!=(const const_iterator &p) const	{return (mLoc!=p.mLoc || mOwner!=p.mOwner);}
		bool	operator==(const const_iterator &p) const 	{return (mLoc==p.mLoc && mOwner==p.mOwner);}
		bool	operator!=(const iterator &p) const	{return (mLoc!=p.mLoc || mOwner!=p.mOwner);}
		bool	operator==(const iterator &p) const 	{return (mLoc==p.mLoc && mOwner==p.mOwner);}

		const TVTValue &	operator*() const
		{
			assert(mOwner);
			assert(mLoc>=0&&mLoc<CAPACITY); // deferencing end()?
			return mOwner->mValues[mLoc];
		}
		const TKTValue &	key() const
		{
			assert(mOwner);
			assert(mLoc>=0&&mLoc<CAPACITY); // deferencing end()?
			return mOwner->index_to_key(mLoc);
		}
		const TVTValue &	value() const
		{
			assert(mOwner);
			assert(mLoc>=0&&mLoc<CAPACITY); // deferencing end()?
			return mOwner->mValues[mLoc];
		}
		const TVTValue *	operator->() const
		{
			assert(mOwner);
			assert(mLoc>=0&&mLoc<CAPACITY); // deferencing end()?
			return &mOwner->mValues[mLoc];
		}
	};
	friend class iterator;
	friend class const_iterator;

    ////////////////////////////////////////////////////////////////////////////////////
	// Seach For A Given Key.  Will Return end() if Failed  - O(log n)
    ////////////////////////////////////////////////////////////////////////////////////
	iterator	find(const TKTValue &key)
	{
		return iterator(this,tree_base<K, IS_MULTI>::find_index(key));
	}

    ////////////////////////////////////////////////////////////////////////////////////
	// Get An Iterator To The Smallest Element  - O(log n)
    ////////////////////////////////////////////////////////////////////////////////////
	iterator	begin()
	{
		return iterator(this, tree_base<K,IS_MULTI>::front());
	}

	////////////////////////////////////////////////////////////////////////////////////
	// Get An Iterator To The Largest Element  - O(log n)
    ////////////////////////////////////////////////////////////////////////////////////
	iterator	rbegin()
	{
		return iterator(this, tree_base<K,IS_MULTI>::back());
	}

    ////////////////////////////////////////////////////////////////////////////////////
	// The Invalid Iterator, Use As A Stop Condition In Your For Loops  - O(1)
    ////////////////////////////////////////////////////////////////////////////////////
	iterator	end()
	{
		return iterator(this);
	}

    ////////////////////////////////////////////////////////////////////////////////////
	// Seach For A Given Key.  Will Return end() if Failed  - O(log n)
    ////////////////////////////////////////////////////////////////////////////////////
	const_iterator	find(const TKTValue &key) const
	{
		return const_iterator(this, find_index(key));
	}

    ////////////////////////////////////////////////////////////////////////////////////
	// Get An const_iterator To The Smallest Element  - O(log n)
    ////////////////////////////////////////////////////////////////////////////////////
	const_iterator	begin() const
	{
		return const_iterator(this, tree_base<K,IS_MULTI>::front());
	}

	////////////////////////////////////////////////////////////////////////////////////
	// Get An const_iterator To The Largest Element  - O(log n)
    ////////////////////////////////////////////////////////////////////////////////////
	const_iterator	rbegin() const
	{
		return const_iterator(this, tree_base<K,IS_MULTI>::back());
	}

    ////////////////////////////////////////////////////////////////////////////////////
	// The Invalid const_iterator, Use As A Stop Condition In Your For Loops  - O(1)
    ////////////////////////////////////////////////////////////////////////////////////
	const_iterator	end() const
	{
		return const_iterator(this);
	}
    ////////////////////////////////////////////////////////////////////////////////////
	// Removes The Element Pointed To At (it) And Decrements (it)  - O((log n)^2)
    ////////////////////////////////////////////////////////////////////////////////////
	void		erase(const iterator &it)
	{
		assert(it.mOwner==this && it.mLoc>=0&&it.mLoc<CAPACITY);
		erase_index(it.mLoc);
		mValues.destruct(it.mLoc);
	}
private:
	bool check_validity()
	{
#if (0)
		int cnt=0;
		iterator it=begin();
		for (;it!=end();it++)
		{
			cnt++;
		}
//		assert(cnt==size());
		return cnt==size();
#else
		return true;
#endif
	}
};

template<class K,class V, int ARG_CAPACITY>
class map_vs : public map_base<
	storage::value_semantics_node<K,ARG_CAPACITY,tree_node>,
	storage::value_semantics<V,ARG_CAPACITY>,
	0 >
{
public:
	typedef typename storage::value_semantics<V,ARG_CAPACITY> VStorageTraits;
	typedef typename VStorageTraits::TValue TTValue;
	static const int CAPACITY = ARG_CAPACITY;
	map_vs() {}
};

template<class K,class V, int ARG_CAPACITY>
class map_os : public map_base<
	storage::value_semantics_node<K,ARG_CAPACITY,tree_node>,
	storage::object_semantics<V,ARG_CAPACITY>,
	0 >
{
public:
	typedef typename storage::object_semantics<V,ARG_CAPACITY> VStorageTraits;
	typedef typename VStorageTraits::TValue TTValue;
	static const int CAPACITY = ARG_CAPACITY;
	map_os() {}
};

template<class K,class V, int ARG_CAPACITY,int ARG_MAX_CLASS_SIZE>
class map_is : public map_base<
	storage::value_semantics_node<K,ARG_CAPACITY,tree_node>,
	storage::virtual_semantics<V,ARG_CAPACITY,ARG_MAX_CLASS_SIZE>,
	0 >
{
public:
	typedef typename storage::virtual_semantics<V,ARG_CAPACITY,ARG_MAX_CLASS_SIZE> VStorageTraits;
	typedef typename VStorageTraits::TValue TTValue;
	static const int CAPACITY = ARG_CAPACITY;
	static const int MAX_CLASS_SIZE = ARG_MAX_CLASS_SIZE;
	map_is() {}
};

}

#endif
