#ifndef SUB_ARRAY_HPP #define SUB_ARRAY_HPP #include <utils/Array.hpp> #include <utils/PugsAssert.hpp> #include <utils/PugsMacros.hpp> #include <utils/PugsUtils.hpp> #include <algorithm> template <typename DataType> class [[nodiscard]] SubArray { public: using data_type = DataType; using index_type = size_t; private: // underlying array Array<DataType> m_array; DataType* m_sub_values; size_t m_size; // Allows const version to access our data friend SubArray<std::add_const_t<DataType>>; public: PUGS_INLINE size_t size() const noexcept { return m_size; } PUGS_INLINE DataType& operator[](index_type i) const noexcept(NO_ASSERT) { Assert(i < m_size); return m_sub_values[i]; } PUGS_INLINE void fill(const DataType& data) const { static_assert(not std::is_const<DataType>(), "Cannot modify SubArray of const"); // could consider to use std::fill parallel_for( this->size(), PUGS_LAMBDA(index_type i) { m_sub_values[i] = data; }); } template <typename DataType2> PUGS_INLINE SubArray& operator=(const SubArray<DataType2>& sub_array) noexcept { // ensures that DataType is the same as source DataType2 static_assert(std::is_same<std::remove_const_t<DataType>, std::remove_const_t<DataType2>>(), "Cannot assign SubArray of different type"); // ensures that const is not lost through copy static_assert(((std::is_const<DataType2>() and std::is_const<DataType>()) or not std::is_const<DataType2>()), "Cannot assign SubArray of const to SubArray of non-const"); m_array = sub_array.m_array; m_size = sub_array.m_size; m_sub_values = sub_array.m_sub_values; return *this; } PUGS_INLINE SubArray& operator=(const SubArray&) = default; PUGS_INLINE SubArray& operator=(SubArray&&) = default; PUGS_INLINE explicit SubArray(Array<DataType> array, size_t begin, size_t size) : m_array{array}, m_sub_values{&array[0] + begin}, m_size{size} { Assert(begin + size <= array.size(), "SubView is not contained in the source Array"); static_assert(not std::is_const<DataType>(), "Cannot allocate SubArray of const data: only view is " "supported"); } PUGS_INLINE SubArray() = default; PUGS_INLINE SubArray(const SubArray&) = default; template <typename DataType2> PUGS_INLINE SubArray(const SubArray<DataType2>& sub_array) noexcept { this->operator=(sub_array); } PUGS_INLINE SubArray(SubArray &&) = default; PUGS_INLINE ~SubArray() = default; }; #endif // SUB_ARRAY_HPP