#ifndef STACK_H #define STACK_H #include #include #include #include #define DEFAULT_STACK_SIZE 4 enum class StackErr { ok, bad_alloc, empty, }; template requires std::formattable class Stack { private: uint64_t len; uint64_t cap; T *data; public: Stack(); ~Stack(); std::expected pop(); std::expected peek(); StackErr push(T val); void print(); }; template requires std::formattable Stack::Stack() { Stack new_stack; new_stack.data = new T[DEFAULT_STACK_SIZE]; new_stack.cap = 0; new_stack.len = 0; return new_stack; } template requires std::formattable Stack::~Stack() { delete[] this->data; } template requires std::formattable StackErr Stack::push(T value) { // If not enough space allocate more space if (this->len >= this->cap) { uint64_t new_capacity = this->cap * 2; T *tmp; try { tmp = new T[new_capacity]; } catch (const std::bad_alloc& e) { return StackErr::bad_alloc; } for (int i = 0; i < this->len; i++) { tmp[i] = this->data[i]; } delete[] this->data; this->data = tmp; } this->data[this->len] = value; this->len++; return StackErr::ok; } template requires std::formattable std::expected Stack::pop() { if (this->len == 0) { return std::unexpected(StackErr::empty); } T return_val = this->data[this->len - 1]; if (this->cap / 4 > this->len) { uint64_t new_capacity = this->cap / 2; T *tmp; try { tmp = new T[new_capacity]; } catch (const std::bad_alloc& e) { return std::unexpected(StackErr::bad_alloc); } for (int i = 0; i < this->len; i++) { tmp[i] = this->data[i]; } delete[] this->data; this->data = tmp; } return std::expected(return_val); } #endif // !ST