#pragma once #include #include #include namespace Blah { // A mix between an std::vector and an std::array // The goal is to have an std::vector implementation that lives // on the stack instead of the heap template class StackVector { private: char m_buffer[sizeof(T) * Capacity]; int m_count; public: static inline constexpr size_t MaxCapacity = Capacity; StackVector(); StackVector(const std::initializer_list& init); StackVector(const StackVector& src); StackVector(StackVector&& src) noexcept; ~StackVector(); StackVector& operator=(const StackVector& src); StackVector& operator=(StackVector&& src) noexcept; void clear(); int size() const; constexpr int capacity() { return Capacity; } T* expand(int amount = 1); void push_back(const T& item); void push_back(T&& item); template void emplace_back(Args&&...args); T& operator[](int index); const T& operator[](int index) const; T* data(); const T* data() const; T* begin(); const T* begin() const; T* end(); const T* end() const; T& front(); const T& front() const; T& back(); const T& back() const; void erase(int index, int elements = 1); T pop(); }; template inline StackVector::StackVector() { m_count = 0; } template inline StackVector::StackVector(const std::initializer_list& init) { m_count = 0; for (auto& it : init) push_back(it); } template inline StackVector::StackVector(const StackVector& src) { for (int i = 0; i < src.m_count; i++) new (data() + i) T(src.data()[i]); m_count = src.m_count; } template inline StackVector::StackVector(StackVector&& src) noexcept { for (int i = 0; i < src.m_count; i++) new (data() + i) T(std::move(src.data()[i])); m_count = src.m_count; } template inline StackVector::~StackVector() { clear(); } template inline StackVector& StackVector::operator=(const StackVector& src) { clear(); for (int i = 0; i < src.m_count; i++) new (data() + i) T(std::move(src.data()[i])); m_count = src.m_count; return *this; } template inline StackVector& StackVector::operator=(StackVector&& src) noexcept { clear(); for (int i = 0; i < src.m_count; i++) new (data() + i) T(std::move(src.data()[i])); m_count = src.m_count; return *this; } template inline void StackVector::clear() { for (int i = 0; i < m_count; i++) data()[i].~T(); m_count = 0; } template inline int StackVector::size() const { return m_count; } template inline T* StackVector::expand(int amount) { BLAH_ASSERT(m_count + amount <= Capacity, "Exceeded StackVector Capacity"); if (amount > 0) { int count = m_count; for (int i = 0; i < amount; i++) new (data() + count + i) T(); m_count += amount; return &data()[count]; } return (T*)m_buffer; } template inline void StackVector::push_back(const T& item) { BLAH_ASSERT(m_count + 1 <= Capacity, "Exceeded StackVector Capacity"); new (data() + m_count) T(item); m_count++; } template inline void StackVector::push_back(T&& item) { BLAH_ASSERT(m_count + 1 <= Capacity, "Exceeded StackVector Capacity"); new (data() + m_count) T(std::move(item)); m_count++; } template template inline void StackVector::emplace_back(Args && ...args) { BLAH_ASSERT(m_count + 1 <= Capacity, "Exceeded StackVector Capacity"); new (data() + m_count) T(std::forward(args)...); m_count++; } template inline T& StackVector::operator[](int index) { BLAH_ASSERT(index >= 0 && index < m_count, "Index out of range"); return data()[index]; } template inline const T& StackVector::operator[](int index) const { BLAH_ASSERT(index >= 0 && index < m_count, "Index out of range"); return data()[index]; } template inline T* StackVector::data() { return (T*)m_buffer; } template inline const T* StackVector::data() const { return (T*)m_buffer; } template inline T* StackVector::begin() { return (T*)m_buffer; } template inline const T* StackVector::begin() const { return (T*)m_buffer; } template inline T* StackVector::end() { return ((T*)m_buffer) + m_count; } template inline const T* StackVector::end() const { return ((T*)m_buffer) + m_count; } template inline T& StackVector::front() { BLAH_ASSERT(m_count > 0, "Index out of range"); return data()[0]; } template inline const T& StackVector::front() const { BLAH_ASSERT(m_count > 0, "Index out of range"); return data()[0]; } template inline T& StackVector::back() { BLAH_ASSERT(m_count > 0, "Index out of range"); return data()[m_count - 1]; } template inline const T& StackVector::back() const { BLAH_ASSERT(m_count > 0, "Index out of range"); return data()[m_count - 1]; } template inline void StackVector::erase(int index, int elements) { BLAH_ASSERT(index >= 0 && index + elements <= m_count, "Index out of range"); if (elements >= 1) { for (int i = index; i < (m_count - elements); i++) data()[i] = std::move(data()[i + elements]); for (int i = m_count - elements; i < m_count; i++) data()[i].~T(); m_count -= elements; } } template inline T StackVector::pop() { BLAH_ASSERT(m_count > 0, "Index out of range"); T value = std::move(data()[m_count - 1]); data()[m_count - 1].~T(); m_count--; return value; } }