#pragma once #include #include #include #include #define DESTROY(x) //------------------------------------------------------------------------------ //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 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); //------------------------------------------------------------------------------ //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); } //------------------------------------------------------------------------------ //Element access forall(otype T, otype allocator_t | allocator_c(T, allocator_t)) inline T at(vector(T, allocator_t) *const this, size_t index) { // assert(index < this->size); return data(&this->storage)[index]; } forall(otype T, otype allocator_t | allocator_c(T, allocator_t)) inline T ?[?](vector(T, allocator_t) *const this, size_t index) { return data(&this->storage)[index]; } forall(otype T, otype allocator_t | allocator_c(T, allocator_t)) inline T front(vector(T, allocator_t) *const this) { return data(&this->storage)[0]; } forall(otype T, otype allocator_t | allocator_c(T, allocator_t)) inline T back(vector(T, allocator_t) *const this) { return data(&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); forall(otype T, otype allocator_t | allocator_c(T, allocator_t)) void pop_back(vector(T, allocator_t) *const this); forall(otype T, otype allocator_t | allocator_c(T, allocator_t)) void clear(vector(T, allocator_t) *const this); //------------------------------------------------------------------------------ //Iterators forall(otype T, otype allocator_t | allocator_c(T, allocator_t)) inline T* begin(vector(T, allocator_t) *const this) { return data(&this->storage); } forall(otype T, otype allocator_t | allocator_c(T, allocator_t)) inline const T* cbegin(const vector(T, allocator_t) *const this) { return data(&this->storage); } forall(otype T, otype allocator_t | allocator_c(T, allocator_t)) inline T* end(vector(T, allocator_t) *const this) { return data(&this->storage) + this->size; } forall(otype T, otype allocator_t | allocator_c(T, allocator_t)) inline const T* cend(const vector(T, allocator_t) *const this) { return data(&this->storage) + this->size; } //------------------------------------------------------------------------------ //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; }