#pragma once #include #include "Sizes.hpp" template class FlexArray { public: FlexArray() = default; FlexArray& operator=(const FlexArray& other) { m_count = other.m_count; m_array = other.m_array; return *this; } T& at(USize index) { assure_in_bounds(index); return m_array.at(index); } const T& at(USize index) const { assure_in_bounds(index); return m_array.at(index); } T& operator[](USize index) { assure_in_bounds(index); // STL doesn't do bounds-checks here, and it led to many headaches :( return m_array[index]; } const T& operator[](USize index) const { assure_in_bounds(index); return m_array[index]; } T& front() { return at(0); } const T& front() const { return at(0); } T& back() { return at(m_count - 1); } const T& back() const { return at(m_count - 1); } const T* data() const { return m_array.data(); } T* data() { return m_array.data(); } std::array& array() { return m_array; } const std::array& array() const { return m_array; } T* begin() { return m_array.begin(); } T* end() { return m_array.begin() + m_count; } Bool empty() const { return m_count == 0; } Bool full() const { return m_count == S; } USize size() const { return m_count; } USize max_size() const { return S; } void clear() { m_count = 0; m_array = {}; } void push_back(const T& value) { if (m_count >= S) throw std::out_of_range("flex array is full"); m_array[m_count] = value; m_count++; } template void emplace_back(Args&&... args) { if (full()) throw std::out_of_range("flex array is full"); m_array[m_count] = T{std::forward(args)...}; m_count++; } void pop_back() { if (empty()) throw std::out_of_range("flex array is empty"); m_array[m_count - 1] = {}; m_count--; } private: void assure_in_bounds(USize index) const { if (index >= m_count) throw std::out_of_range("flex array index out of range"); } USize m_count = 0; std::array m_array{}; };