Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Static multidimensional array, dimensionality definition at compile time

Is there any syntax through which I can define the dimensionality of a static array at compile time? Let's assume I have a tuple of size D, with values d_0,...,d_{D-1}. I would like to be able to create an array T arr[d_0][d_1]...[d_{D-1}]. Is there any way to achieve this at compile time? I am specifically asking about static array syntax, not about how to nest structs.

Here's a code snippet to clarify what I want to achieve:

template<typename T, template<typename, auto> typename Container, auto DimC, auto...Dim>
struct NestedContainer
{
    using type = Container<typename NestedContainer<T, Container, Dim...>::type, DimC>;
};

template<typename T, template<typename, auto> typename Container, auto Dim>
struct NestedContainer<T, Container, Dim>
{
    using type = Container<T, Dim>;
};

template<typename T, int D>
struct Arr
{
    T e[D];

    T& operator[](int i) { return e[i]; }
};

template<typename T, int D, int...Dim>
struct MultiArr
{
    using multi_arr = typename NestedContainer<T, Arr, Dim...>::type;
    multi_arr e[D];

    auto& operator[](int i) { return e[i]; }
};

Used like so:

MultiArr<float, 3, 3, 3> a;
a[2][2][2] = 3;

I am curious whether this is achievable through some form of syntax without nesting classes.

like image 217
lightxbulb Avatar asked Mar 04 '23 17:03

lightxbulb


1 Answers

It can easily be done using template metaprogramming recursion. The only tricky thing is that you need to apply the extents in the correct order. Note that int[x][y] is (conceptually) (int[y])[x].

#include <cstddef>
#include <type_traits>

template <typename E, size_t... extents>
struct MultiArrHelper;

template <typename E>
struct MultiArrHelper<E> {
    using type = E;
};

template <typename E, size_t extent, size_t... extents>
struct MultiArrHelper<E, extent, extents...> {
    using type = typename MultiArrHelper<E, extents...>::type[extent];
};

template <typename E, size_t... extents>
using MultiArr = typename MultiArrHelper<E, extents...>::type;

int main() {
    MultiArr<int, 2, 2, 3> a;
    static_assert(std::is_same<decltype(a), int[2][2][3]>::value);
}

http://coliru.stacked-crooked.com/a/6b89020318e78b90

like image 92
Brian Bi Avatar answered Mar 22 '23 22:03

Brian Bi