Elegantly define multi-dimensional array in modern C++
Asked Answered
A

1

27

Defining multi-dimensional array using the T[][][] syntax is easy. However, this creates a raw array type which doesn't fit nicely into modern C++. That's why we have std::array since C++11. But the syntax to define a multi-dimensional array using std::array is quite messy. For example, to define a three-dimensional int array, you would have to write std::array<std::array<std::array<int, 5>, 5>, 5>. The syntax doesn't scale at all. I'm asking for a fix for this issue. Maybe, this issue cannot be fixed using existing utility provided by C++. In that case, I'm happy with a custom tool developed to ease the syntax.

Found a solution myself:

template <typename T, std::size_t n, std::size_t... ns>
struct multi_array {
  using type = std::array<typename multi_array<T, ns...>::type, n>;
};

template <typename T, std::size_t n>
struct multi_array<T, n> {
  using type = std::array<T, n>;
};

template <typename T, std::size_t... ns>
using multi_array_t = typename multi_array<T, ns...>::type;

Wondering whether the implementation can be further simplified.

Azalea answered 26/1, 2016 at 6:25 Comment(11)
@AngryLettuce I think that would be a little too heavy for simple matters like this. I don't want to pull in a whole Boost just for this.Azalea
Are typedef's not acceptable: typedef std::array< std::array< std::array<int, 5 > > > threeD; .. threeD arr; arr[0][0][0] ...? This example would have to be modified to allow for different types, obviously, but curious if that might help?Semaphore
You could use the approach in the answers of the question at #24463856.Toomer
Also https://mcmap.net/q/535211/-less-verbose-way-to-declare-multidimensional-std-array/636019 – the same question, but tagged c++11.Yseulta
Note that the memory layout of a nested std::array isn't guaranteed to be the same as that of a C=style array of arrays (at least in C++11, I'm not sure if that got fixed in C++14.)Pentlandite
@Pentlandite Isn't std::array just a simple wrapper around raw array?Azalea
@Azalea But the standard allows it to have some padding at the end (or at least it did in C++11.)Pentlandite
Main difficulty is access using indices.Duero
@Pentlandite Nested std::array are stored in contiguous mem locations. See https://mcmap.net/q/356473/-does-std-array-of-std-array-have-contiguous-memoryDeafmute
@MandeepSingh Yes. My comment still stands.Pentlandite
@Pentlandite Ah yes, you are right, read your comment again and you are not talking about contiguous mem location but probably about padding which might occur :)Deafmute
D
13

Refer to Multi-dimensional arrays in C++11

template <class T, std::size_t I, std::size_t... J>
struct MultiDimArray 
{
  using Nested = typename MultiDimArray<T, J...>::type;
  // typedef typename MultiDimArray<T, J...>::type Nested;
  using type = std::array<Nested, I>;
  // typedef std::array<Nested, I> type;
};

template <class T, std::size_t I>
struct MultiDimArray<T, I> 
{
  using type = std::array<T, I>;
  // typedef std::array<T, I> type;
};

MultiDimArray<float, 3, 4, 5, 6, 7>::type floats;

MultiDimArray is a pair of meta-functions to compute nested type for multi-dimensional std::array. The most general MultiDimArray is a variadic template of unsigned integers to pass an arbitrary number of dimensions. The terminating MultiDimArray specialization defines the simplest case of single dimensional std::array.

Dorison answered 26/1, 2016 at 6:54 Comment(2)
Could the implementation be further simplified?Azalea
Its usage can be a tiny bit more improved by using template alias on top of it: template <class T, size_t I, size_t... J> using MultiDimArray_t = typename MultiDimArray<T, I, J...>::type; MultiDimArray_t<float, 3, 4, 5, 6, 7> floatArr;Deafmute

© 2022 - 2024 — McMap. All rights reserved.