Reputation: 286
Is there a way to extend/modify/implement a constexpr to return a std::tuple of the dimensions of a multidimensional C-style array?
#include <iostream>
#include <tuple>
template<typename T, std::size_t N>
auto arraysize(T (&arr)[N])
{
return std::make_tuple(N);
}
IOW, how to make arraysize to work for any-dimensional array? The above "works" but only returns one dimension:
int i[5];
std::cout << std::get<0>(arraysize(i)) << std::endl;
works, and returns 5. And,
char c[3][4];
std::cout << std::get<0>(arraysize(c)) << std::endl;
works, and returns 3, but
std::cout << std::get<1>(arraysize(c)) << std::endl;
doesn't compile because the arraysize() is not coded right. Is there a way to code it as a constexpr to handle any-dimensional array? Tried using parameter packs but was not successful.
Upvotes: 2
Views: 217
Reputation: 61970
Use std::rank
and std::extent
with the index sequence trick: live example
#include <tuple>
#include <type_traits>
#include <utility>
template<typename Arr, std::size_t... Is>
constexpr auto extents_impl(const Arr&, std::index_sequence<Is...>) {
return std::make_tuple(std::extent_v<Arr, Is>...);
}
template<typename Arr>
constexpr auto extents(const Arr& arr) {
return extents_impl(arr, std::make_index_sequence<std::rank_v<Arr>>{});
}
These traits also return 0 for a non-array type or an array of unknown bound, leaving you with an empty tuple if your function is not given an array type. You can, of course, perform additional checking there if you wish.
Upvotes: 5