// // Created by Patrick Maschek on 19.12.2023. // #ifndef UDIFF_IMMARRAY_H_ #define UDIFF_IMMARRAY_H_ #include #include #include #include #include "helper.h" namespace cc { template class const_vector { static_assert(N > 0, "Capacity of const_vector has to be greater than 0"); public: using value_type = T; using size_type = std::size_t; using difference_type = std::ptrdiff_t; using reference = value_type&; using const_reference = const value_type&; using pointer = value_type *; using const_pointer = const value_type *; using iterator = pointer; using const_iterator = const_pointer; using reverse_iterator = std::reverse_iterator; using const_reverse_iterator = std::reverse_iterator; protected: T _arr[N] = {}; static constexpr const size_type _len = N; size_type _size = 0; public: constexpr const_vector() noexcept = default; constexpr explicit const_vector(const value_type &value) noexcept; constexpr const_vector(size_type count, const value_type &value) noexcept; constexpr explicit const_vector(const value_type (&array)[N]) noexcept; constexpr const_vector(std::initializer_list values) noexcept; template constexpr const_vector(InputIt first, InputIt last); constexpr const_vector(const const_vector& other) noexcept; constexpr const_vector(const_vector&& other) noexcept; constexpr const_vector& operator=(const const_vector& other); constexpr const_vector& operator=(const_vector&& other) noexcept; constexpr const_vector& operator=(const value_type (&array)[N]) noexcept; constexpr void assign(size_type count, const value_type& value) noexcept; template constexpr void assign(InputIt first, InputIt last); constexpr void assign(std::initializer_list values); constexpr reference at(size_type pos); constexpr const_reference at(size_type pos) const; [[nodiscard]] constexpr size_type size() const noexcept { return _size; } constexpr T& operator[](size_type pos) { return _arr[pos]; } constexpr const T& operator[](size_type pos) const { return _arr[pos]; } #ifdef UNIT_TEST friend test_const_vector; #endif }; template const_vector(A[]) -> const_vector>; template const_vector(T...) -> const_vector, sizeof...(T)>; template constexpr const_vector::const_vector(const value_type &value) noexcept : _size(N) { std::fill(std::begin(_arr), std::end(_arr), value); } template constexpr const_vector::const_vector(size_type count, const value_type &value) noexcept { if (count > N) count = N; _size = count; std::fill(_arr, _arr + _size, value); } template constexpr const_vector::const_vector(const value_type (&array)[N]) noexcept : _size(N) { std::move(std::begin(array), std::end(array), _arr); } template constexpr const_vector::const_vector(std::initializer_list values) noexcept : _size(values.size()) { std::move(values.begin(), values.end(), _arr); } template template constexpr const_vector::const_vector(InputIt first, InputIt last) { //static_assert(std::distance(first, last) > N, "tried inserting more elements than const_vector is in size"); _size = std::distance(first, last); std::copy(first, last, _arr); } template constexpr const_vector::const_vector(const const_vector &other) noexcept { static_assert(N >= other._size, "size of other has to be equal to or smaller than this"); std::copy(other._arr, other._arr, _arr); } template constexpr const_vector::const_vector(const_vector &&other) noexcept { static_assert(N == other.N, "size of const_vectors does not match"); std::move(other.begin(), other.end(), _arr); } template constexpr const_vector &const_vector::operator=(const const_vector &other) { if (this == &other) return *this; static_assert(N == other._len, "Cannot assign const_vector to other with different size"); assign(other.begin(), other.end()); return *this; } template constexpr const_vector &const_vector::operator=(const_vector &&other) noexcept { static_assert(N == other._len, "Cannot assign const_vector to other with different size"); if (N != other.N) throw std::exception(); std::move(other.begin(), other.end(), _arr); return *this; } template constexpr const_vector &const_vector::operator=(const value_type (&array)[N]) noexcept { assign(std::begin(array), std::end(array)); return *this; } template constexpr void const_vector::assign(const_vector::size_type count, const value_type &value) noexcept { if (count > N) count = N; _size = count; std::fill(std::begin(_arr), std::end(_arr), value); } template template constexpr void const_vector::assign(InputIt first, InputIt last) { auto distance = std::distance(first, last); if (distance > N) throw std::invalid_argument("Iterator distance in assign surpasses size" + std::to_string(distance) + ">=" + std::to_string(N)); _size = distance; std::copy(first, last, _arr); } template constexpr void const_vector::assign(std::initializer_list values) { auto values_size = std::distance(values.begin(), values.end()); if (values_size > N) throw std::invalid_argument("Initializer list in assign has more elements than size" + std::to_string(values_size) + ">=" + std::to_string(N)); _size = values_size; std::copy(values.begin(), values.end(), _arr); } template constexpr const_vector::reference const_vector::at(const_vector::size_type pos) { if (pos >= _size) throw std::out_of_range("Pos " + std::to_string(pos) + " is out of range"); return _arr[pos]; } template constexpr const_vector::const_reference const_vector::at(const_vector::size_type pos) const { if (pos >= _size) throw std::out_of_range("Pos " + std::to_string(pos) + " is out of range"); return _arr[pos]; } }; // cc #endif //UDIFF_IMMARRAY_H_