#ifndef __SRB2_CORE_STATIC_VEC_HPP__ #define __SRB2_CORE_STATIC_VEC_HPP__ #include #include #include #include #include #include #include #include #include "../cxxutil.hpp" namespace srb2 { template class StaticVec { std::array arr_ {{}}; size_t size_ = 0; public: constexpr StaticVec() {} StaticVec(const StaticVec& rhs) { for (size_t i = size_; i > 0; i--) { arr_[i] = T(); } size_ = rhs.size(); for (size_t i = 0; i < size_; i++) { arr_[i] = rhs.arr_[i]; } } StaticVec(StaticVec&& rhs) noexcept(std::is_nothrow_move_assignable_v) { for (size_t i = size_; i > 0; i--) { arr_[i] = T(); } size_ = rhs.size(); for (size_t i = 0; i < size_; i++) { arr_[i] = std::move(rhs.arr_[i]); } while (rhs.size() > 0) { rhs.pop_back(); } } constexpr StaticVec(std::initializer_list list) noexcept(std::is_nothrow_move_assignable_v) { size_ = list.size(); size_t i = 0; for (auto itr = list.begin(); itr != list.end(); itr++) { arr_[i] = *itr; i++; } } ~StaticVec() = default; StaticVec& operator=(const StaticVec& rhs) { for (size_t i = size_; i > 0; i--) { arr_[i] = T(); } size_ = rhs.size(); for (size_t i = 0; i < size_; i++) { arr_[i] = rhs.arr_[i]; } return *this; } StaticVec& operator=(StaticVec&& rhs) noexcept(std::is_nothrow_move_constructible_v) { for (size_t i = size_; i > 0; i--) { arr_[i] = T(); } size_ = rhs.size(); for (size_t i = 0; i < size_; i++) { arr_[i] = std::move(rhs.arr_[i]); } while (rhs.size() > 0) { rhs.pop_back(); } return *this; } void push_back(const T& value) { arr_[size_++] = value; } void pop_back() { arr_[size_--] = T(); } void resize(size_t size, T value = T()) { if (size >= Limit) { throw std::length_error("new size >= Capacity"); } if (size == size_) { return; } else if (size < size_) { while (size_ > size) { pop_back(); } } else { while (size_ < size) { push_back(value); } } } constexpr T* begin() noexcept { return &arr_[0]; } constexpr const T* begin() const noexcept { return cbegin(); } constexpr const T* cbegin() const noexcept { return &arr_[0]; } constexpr T* end() noexcept { return &arr_[size_]; } constexpr const T* end() const noexcept { return cend(); } constexpr const T* cend() const noexcept { return &arr_[size_]; } constexpr std::reverse_iterator rbegin() noexcept { return &arr_[size_]; } constexpr std::reverse_iterator crbegin() const noexcept { return &arr_[size_]; } constexpr std::reverse_iterator rend() noexcept { return &arr_[0]; } constexpr std::reverse_iterator crend() const noexcept { return &arr_[0]; } constexpr bool empty() const noexcept { return size_ == 0; } constexpr size_t size() const noexcept { return size_; } constexpr size_t capacity() const noexcept { return Limit; } constexpr size_t max_size() const noexcept { return Limit; } constexpr T& operator[](size_t index) noexcept { return arr_[index]; } T& at(size_t index) { if (index >= size_) { throw std::out_of_range("index >= size"); } return this[index]; } constexpr const T& operator[](size_t index) const noexcept { return arr_[index]; } const T& at(size_t index) const { if (index >= size_) { throw std::out_of_range("index >= size"); } return this[index]; } T& front() { return *arr_[0]; } T& back() { return *arr_[size_ - 1]; } }; } // namespace srb2 template bool operator==(const srb2::StaticVec& lhs, const srb2::StaticVec& rhs) { const size_t size = lhs.size(); if (size != rhs.size()) { return false; } for (size_t i = 0; i < lhs; i++) { if (rhs[i] != lhs[i]) { return false; } } return true; } template bool operator!=(const srb2::StaticVec& lhs, const srb2::StaticVec& rhs) { return !(lhs == rhs); } template struct std::hash> { uint64_t operator()(const srb2::StaticVec& input) const { constexpr const uint64_t prime {0x00000100000001B3}; std::size_t ret {0xcbf29ce484222325}; for (auto itr = input.begin(); itr != input.end(); itr++) { ret = (ret * prime) ^ std::hash(*itr); } return ret; } }; #endif // __SRB2_CORE_STATIC_VEC_HPP__