#ifndef CAST_ARRAY_HPP #define CAST_ARRAY_HPP #include <utils/Array.hpp> #include <utils/Exceptions.hpp> #include <utils/PugsTraits.hpp> #include <iostream> template <typename DataType, typename CastDataType> class [[nodiscard]] CastArray { public: using data_type = CastDataType; private: const Array<DataType> m_array; const size_t m_size; CastDataType* const m_values; public: PUGS_INLINE const size_t& size() const { return m_size; } PUGS_INLINE CastDataType& operator[](size_t i) const { Assert(i < m_size); return m_values[i]; } PUGS_INLINE CastArray& operator=(const CastArray&) = default; PUGS_INLINE CastArray& operator=(CastArray&&) = default; explicit CastArray(const Array<DataType>& array) : m_array(array), m_size(sizeof(DataType) * array.size() / sizeof(CastDataType)), m_values((array.size() == 0) ? nullptr : reinterpret_cast<CastDataType*>(&(static_cast<DataType&>(array[0])))) { static_assert((std::is_const_v<CastDataType> and std::is_const_v<DataType>) or (not std::is_const_v<DataType>), "CastArray cannot remove const attribute"); if (sizeof(DataType) * array.size() % sizeof(CastDataType)) { throw UnexpectedError("cannot cast array to the chosen data type"); } } explicit CastArray(DataType & value) : m_size(sizeof(DataType) / sizeof(CastDataType)), m_values(reinterpret_cast<CastDataType*>(&value)) { static_assert((std::is_const_v<CastDataType> and std::is_const_v<DataType>) or (not std::is_const_v<DataType>), "CastArray cannot remove const attribute"); static_assert(is_trivially_castable<DataType>, "Defining CastArray from non trivially castable type is not " "allowed"); } PUGS_INLINE CastArray(DataType && value) = delete; PUGS_INLINE CastArray(const CastArray&) = default; PUGS_INLINE CastArray(CastArray &&) = default; PUGS_INLINE ~CastArray() = default; }; template <typename CastDataType> struct cast_array_to { template <typename DataType> PUGS_INLINE static CastArray<DataType, CastDataType> from(const Array<DataType>& array) { return CastArray<DataType, CastDataType>(array); } }; template <typename CastDataType> struct cast_value_to { template <typename DataType> PUGS_INLINE static CastArray<DataType, CastDataType> from(DataType& value) { return CastArray<DataType, CastDataType>(value); } }; #endif // CAST_ARRAY_HPP