//------------------------------------------------------------------------------
//Declaration
trait allocator_c(otype T, otype allocator_t) {
	void ctor(allocator_t* const);
	void dtor(allocator_t* const);
	void realloc(allocator_t* const, size_t);
	T* data(allocator_t* const);
};

forall(otype T, otype allocator_t | allocator_c(T, allocator_t))
struct vector
{
	allocator_t storage;
	size_t size;
};

//------------------------------------------------------------------------------
//Initialization
forall(otype T, otype allocator_t | allocator_c(T, allocator_t))
void vector_ctor(vector(T, allocator_t) *const this);

forall(otype T, otype allocator_t | allocator_c(T, allocator_t))
void dtor(vector(T, allocator_t) *const this);

//------------------------------------------------------------------------------
//Allocator
forall(otype T)
struct heap_allocator
{
	T* storage;
	size_t capacity;
};

forall(otype T)
void ctor(heap_allocator(T) *const this);

forall(otype T)
void dtor(heap_allocator(T) *const this);

forall(otype T)
void realloc(heap_allocator(T) *const this, size_t size);

forall(otype T)
inline T* data(heap_allocator(T) *const this)
{
	return this->storage;
}

//------------------------------------------------------------------------------
//Capacity
forall(otype T, otype allocator_t | allocator_c(T, allocator_t))
inline bool empty(vector(T, allocator_t) *const this)
{
	return this->size == 0;
}

forall(otype T, otype allocator_t | allocator_c(T, allocator_t))
inline bool size(vector(T, allocator_t) *const this)
{
	return this->size;
}

forall(otype T, otype allocator_t | allocator_c(T, allocator_t))
inline void reserve(vector(T, allocator_t) *const this, size_t size)
{
	realloc(&this->storage, this->size+1);
}

//------------------------------------------------------------------------------
//Modifiers
forall(otype T, otype allocator_t | allocator_c(T, allocator_t))
void push_back(vector(T, allocator_t) *const this, T value);
