#pragma once #include "TypeTraits.h" #include #include #include #include #include namespace sls { template class FixedCapacityContainer { public: using size_type = typename std::array::size_type; using value_type = typename std::array::value_type; using iterator = typename std::array::iterator; using const_iterator = typename std::array::const_iterator; private: size_type current_size{}; std::array data_; public: FixedCapacityContainer() = default; explicit FixedCapacityContainer(std::initializer_list l) : current_size(l.size()) { size_check(l.size()); std::copy(l.begin(), l.end(), data_.begin()); } /** Copy construct from another container */ template ::value && std::is_same::value>::type> FixedCapacityContainer(const V &v) : current_size(v.size()) { size_check(v.size()); std::copy(v.begin(), v.end(), data_.begin()); } /** copy assignment from another container */ template typename std::enable_if::value, FixedCapacityContainer &>::type operator=(const V &other) { size_check(other.size()); std::copy(other.begin(), other.end(), data_.begin()); current_size = other.size(); return *this; } /** Compare FixedCapacityContainer with any other container*/ // template // typename std::enable_if::value, bool>::type // operator==(const V &other) const noexcept { // if (current_size != other.size()) { // return false; // } else { // for (size_t i = 0; i != current_size; ++i) { // if (data_[i] != other[i]) { // return false; // } // } // } // return true; // } // template // typename std::enable_if::value, bool>::type // operator!=(const V &other) const noexcept { // return !(*this == other); // } operator std::vector() { return std::vector(begin(), end()); } T &operator[](size_t i) { return data_[i]; } const T &operator[](size_t i) const { return data_[i]; } constexpr size_type size() const noexcept { return current_size; } bool empty() const noexcept { return current_size == 0; } constexpr size_t capacity() const noexcept { return Capacity; } void push_back(const T &value) { if (current_size == Capacity) { throw std::runtime_error("Container is full"); } else { data_[current_size] = value; ++current_size; } } void resize(size_t new_size) { if (new_size > Capacity) { throw std::runtime_error("Cannot resize beyond capacity"); } else { current_size = new_size; } } void erase(T *ptr) { if (ptr >= begin() && ptr < end()) { current_size = static_cast(ptr - begin()); } else { throw std::runtime_error("tried to erase with a ptr outside obj"); } } template bool is_equal(const Container &c) const noexcept { if (current_size != c.size()) { return false; } else { for (size_t i = 0; i != current_size; ++i) { if (data_[i] != c[i]) { return false; } } } return true; } T &front() noexcept { return data_.front(); } T &back() noexcept { return data_[current_size - 1]; } constexpr const T &front() const noexcept { return data_.front(); } constexpr const T &back() const noexcept { return data_[current_size - 1]; } // iterators iterator begin() noexcept { return data_.begin(); } // auto begin() noexcept -> decltype(data_.begin()) { return data_.begin(); // } const_iterator begin() const noexcept { return data_.begin(); } iterator end() noexcept { return &data_[current_size]; } const_iterator end() const noexcept { return &data_[current_size]; } const_iterator cbegin() const noexcept { return data_.cbegin(); } const_iterator cend() const noexcept { return &data_[current_size]; } void size_check(size_type s) const { if (s > Capacity) { throw std::runtime_error( "Capacity needs to be same size or larger than vector"); } } } __attribute__((packed)); template bool operator==(const FixedCapacityContainer &lhs, const FixedCapacityContainer &rhs) { return lhs.is_equal(rhs); } template bool operator!=(const FixedCapacityContainer &lhs, const FixedCapacityContainer &rhs) { return !(lhs.is_equal(rhs)); } // Compare with array template bool operator==(const FixedCapacityContainer &lhs, const std::array &rhs) { return lhs.is_equal(rhs); } template bool operator==(const std::array &lhs, const FixedCapacityContainer &rhs) { return rhs.is_equal(lhs); } template bool operator!=(const FixedCapacityContainer &lhs, const std::array &rhs) { return !lhs.is_equal(rhs); } template bool operator!=(const std::array &lhs, const FixedCapacityContainer &rhs) { return !rhs.is_equal(lhs); } // Compare with vector template bool operator==(const FixedCapacityContainer &lhs, const std::vector &rhs) { return lhs.is_equal(rhs); } template bool operator==(const std::vector &lhs, const FixedCapacityContainer &rhs) { return rhs.is_equal(lhs); } template bool operator!=(const FixedCapacityContainer &lhs, const std::vector &rhs) { return !lhs.is_equal(rhs); } template bool operator!=(const std::vector &lhs, const FixedCapacityContainer &rhs) { return !rhs.is_equal(lhs); } /** support flipped order compare */ // template // typename std::enable_if::value, bool>::type operator==( // const C &container, // const FixedCapacityContainer &fixed_container) noexcept { // return fixed_container.operator==(container); // } // /** support flipped order compare */ // template // typename std::enable_if::value, bool>::type operator!=( // const C &container, // const FixedCapacityContainer &fixed_container) noexcept { // return fixed_container.operator!=(container); // } } // namespace sls