From 551530658fa43c19fd4d86748dd24950380750be Mon Sep 17 00:00:00 2001 From: Stephane Del Pino <stephane.delpino44@gmail.com> Date: Thu, 11 Oct 2018 15:14:38 +0200 Subject: [PATCH] Add conversion of Array<data_type> to an "Array<another_data_type>" "Array<another_data_type>" is actually (CastArray<another_data_type>). This is in fact just a view which allow to access/modify original array's data reinterpreting them to another type. The only constrain w.r. to the type is that one must have sizeof(data_type)*Array::size() == sizeof(other_data_type)*CastArray::size(). CastArray can be built thanks to the helper static function cast_array_to<other_data_type>::from(given_array). Usage: for instance, one writes: Array<double> x(3); x[0]=1;x[1]=2;x[2]=3; CastArray y = cast_array_to<int>::from(x); // ok! y values can change CastArray z = cast_array_to<const int>::from(x); // ok! z values cannot change Array<const double> cx = x; CastArray cy = cast_array_to<int>::from(cx); // invalid! cannot remove const CastArray cz = cast_array_to<const int>::from(cx);// ok! CastArray t = cast_array_to<TinyVector<4,int>>::from(x); // ok! In last example, execution will fail (sizes are incompatible), but would success if the size of x was a multiple of 2. It is unclear if one should impose sizeof(other_data_type) <= sizeof(data_type) --- src/utils/CastArray.hpp | 72 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 72 insertions(+) create mode 100644 src/utils/CastArray.hpp diff --git a/src/utils/CastArray.hpp b/src/utils/CastArray.hpp new file mode 100644 index 000000000..0f9ec5145 --- /dev/null +++ b/src/utils/CastArray.hpp @@ -0,0 +1,72 @@ +#ifndef CAST_ARRAY_HPP +#define CAST_ARRAY_HPP + +#include <Array.hpp> + +template <typename DataType, + typename CastDataType> +class CastArray +{ + private: + const Array<DataType> m_array; + const size_t m_size; + CastDataType* const m_values; + + public: + PASTIS_INLINE + const size_t& size() const + { + return m_size; + } + + PASTIS_INLINE + CastDataType& operator[](const size_t& i) const + { + Assert(i<m_size); + return m_values[i]; + } + + PASTIS_INLINE + 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*>(&(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)) { + std::cerr << "cannot cast array to the chosen data type\n"; + std::exit(1); + } + } + + PASTIS_INLINE + CastArray(const CastArray&) = default; + + PASTIS_INLINE + CastArray(CastArray&&) = default; + + PASTIS_INLINE + CastArray& operator=(const CastArray&) = default; + + PASTIS_INLINE + CastArray& operator=(CastArray&&) = default; + + PASTIS_INLINE + ~CastArray() = default; +}; + +template <typename CastDataType> +struct cast_array_to +{ + template <typename DataType> + PASTIS_INLINE + static CastArray<DataType, CastDataType> + from(const Array<DataType>& array) + { + return CastArray<DataType, CastDataType>(array); + } +}; + +#endif // CAST_ARRAY_HPP -- GitLab