Suppose the following multi_array structure:
template <typename type, std::size_t... sizes>
struct multi_array
{
using storage_type = typename storage_type<type, sizes...>::type;
using value_type = type;
using size_type = std::array<std::size_t , sizeof...(sizes)>;
using difference_type = std::array<std::ptrdiff_t, sizeof...(sizes)>;
using reference = value_type&;
using const_reference = const value_type&;
// ...
storage_type data_ {};
size_type sizes_ {sizes...};
}
// Example usage:
// multi_array<float, 3, 4, 5> three_dimensional_float_array;
// storage_type will be std::array<std::array<std::array<float, 5>, 4>, 3>
// size_type will be std::array<std::size_t, 3>
where:
// Helpers to create a std::array<std::array<...>> from a pack expansion.
template <typename type, std::size_t... sizes>
struct storage_type;
template <typename _type, std::size_t size, std::size_t... sizes>
struct storage_type<_type, size, sizes...>
{
using type = std::array<typename storage_type<_type, sizes...>::type, size>;
};
template <typename _type>
struct storage_type<_type>
{
using type = _type;
};
I am now trying to implement the .at() function:
[[nodiscard]]
constexpr reference at (const size_type& position)
{
// This has to be:
// data_[position[0]][position[1]][position[2]]...;
}
Fold expressions do not work in this case so a recursive solution is necessary.
I think this is the way, but can't seem to come up with the right answer:
[[nodiscard]]
constexpr reference at(const size_type& position)
{
return access_type<value_type, sizeof...(sizes)>::at(data_, position);
}
template <typename type, std::size_t size, std::size_t index = 0>
struct access_type
{
template <typename array_type>
auto at (const array_type& array, const std::array<std::size_t, size>& position, type& current) // Problem: Reference is not a type& for intermediates.
{
if constexpr (index == 0)
current = &array;
if constexpr (index + 1 != size)
{
return access_type::at<type, size, index + 1>(array, position, current);
}
}
};
Something along these lines, perhaps: