I'm using 2-dimensional arrays based on std::array
.
Basically instead of:
MyType myarray[X_SIZE][Y_SIZE];
I have:
std::array<std::array<MyType, Y_SIZE>, X_SIZE> myarray;
This works perfectly fine but IMO the declaration is not very readable.
Is there a way to declare this using some clever C++ template mecanism, so the declaration could look something like this?
My2DArray<Mytype, X_SIZE, Y_SIZE> myarray;
An array with more than one dimension is known as a multi-dimensional array. The most commonly used multi-dimensional arrays are 2-D and 3-D arrays. We can say that any higher dimensional array is basically an array of arrays.
A very common example of a 2D Array is Chess Board. A chessboard is a grid containing 64 1×1 square boxes. You can similarly visualize a 2D array.
For this, we have multidimensional arrays. A multidimensional array is an array containing one or more arrays. PHP supports multidimensional arrays that are two, three, four, five, or more levels deep. However, arrays more than three levels deep are hard to manage for most people.
Accessing Elements of Three-Dimensional Arrays Elements in three-dimensional arrays are commonly referred by x [i] [j] [k] where ‘i’ is the array number, ‘j’ is the row number and ‘k’ is the column number.
If you want just 2D arrays, it's fairly straightforward:
template <class T, std::size_t X, std::size_t Y>
using My2DArray = std::array<std::array<T, Y>, X>;
If you want a generic mechanism not limited to 2D arrays, it can be done too:
template <class T, std::size_t N, std::size_t... Ns>
struct AddArray {
using type = std::array<typename AddArray<T, Ns...>::type, N>;
};
template <class T, std::size_t N>
struct AddArray<T, N> {
using type = std::array<T, N>;
};
template <class T, std::size_t... N>
using MyNDArray = typename AddArray<T, N...>::type;
[Live example]
We can wrap one of the existing MyNDArray
/ md_array_t
answers to arrive at an alternative interface:
template <typename Arr, std::size_t... Is>
constexpr auto make_array_impl(std::index_sequence<Is...>)
-> md_array_t<std::remove_all_extents_t<Arr>,
std::extent_v<Arr, Is>...>;
template <typename Arr>
using make_array = decltype(make_array_impl<Arr>(
std::make_index_sequence<std::rank_v<Arr>>{}));
Compiler Explorer
This allows us to write make_array<int[4][5][6]>
to mean array<array<array<int, 6>, 5, 4>
.
Explanation:
std:rank
gives the number of dimensions of an array type. Thus, for int[4][5][6]
, it returns 3.make_index_sequence
to end up with a pack of indices. (0, 1, 2
)std::remove_all_extents
gives us the underlying type of the array; T[a][b]...[n]
-> T
(int
)std::extent
gives us the extent of the given dimension. We call this for each index. (4, 5, 6
).By passing these to our previously-implemented md_array_t
, we end up with md_array_t<int, 4, 5, 6>
, which produces what we want.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With