#ifndef STACKALLOCATOR_H #define STACKALLOCATOR_H #include #include namespace StackAllocator { struct Pointer { int lastPointer; int pointer; }; Pointer allocate(int bytesPerElement, int& elements); void free(const Pointer& p); int grow(const Pointer& p, int bytesPerElement, int elements); void* get(const Pointer& p); template class Array final { int length; Pointer dataPointer; public: Array(int n) : length(n), dataPointer(StackAllocator::allocate(sizeof(T), length)) { for(int i = 0; i < length; i++) { new((*this) + i) T; } } ~Array() { for(int i = 0; i < length; i++) { (*this)[i].~T(); } StackAllocator::free(dataPointer); } Array(const Array&) = delete; Array& operator=(const Array&) = delete; Array(Array&&) = delete; Array& operator=(Array&&) = delete; int getLength() const { return length; } int grow(int n) { int add = StackAllocator::grow(dataPointer, sizeof(T), n); for(int i = length; i < length + add; i++) { new((*this) + i) T(); } length += add; return add; } T& operator[](int index) { return static_cast(StackAllocator::get(dataPointer))[index]; } const T& operator[](int index) const { return static_cast(StackAllocator::get(dataPointer))[index]; } operator T*() { return static_cast(StackAllocator::get(dataPointer)); } }; template class Object final { int length; Pointer dataPointer; public: Object() : length(1), dataPointer(StackAllocator::allocate(sizeof(T), length)) { if(!hasError()) { new(StackAllocator::get(dataPointer)) T; } } ~Object() { if(!hasError()) { (*this)->~T(); } StackAllocator::free(dataPointer); } Object(const Object&) = delete; Object& operator=(const Object&) = delete; Object(Object&&) = delete; Object& operator=(Object&&) = delete; bool hasError() { return length != 1; } T* operator->() { return static_cast(StackAllocator::get(dataPointer)); } operator T&() { return *static_cast(StackAllocator::get(dataPointer)); } }; } #endif