我想知道是否有类似std :: get的东西在编译时访问任何n维数组。例如。 get_value(arr, 1,2,3)
将返回值arr[1][2][3]
。我试图使用递归模板constexpr。但是,类型演绎似乎有问题。
#include <iostream>
#include <string>
#include <array>
template <class T, class FIRST, class ... REST>
constexpr auto get_value(T arr, FIRST first, REST... rest) {
auto sub = arr[first];
using sub_t = decltype(sub);
return get_value<sub_t, REST...>(sub, rest...);
}
// works for 1D
template<class T>
constexpr auto get_value(T arr, auto first) {
return arr[first];
}
int main()
{
using arr1_t = std::array<int, 5>;
using arr2_t = std::array<arr1_t, 5>;
arr1_t arr1 = {1,2,3,4,5};
arr2_t arr2 = {arr1, arr1, arr1, arr1, arr1};
std::cout << get_value(arr1, 1) << std::endl;
std::cout << get_value(arr2, 1,1) << std::endl;
}
答案 0 :(得分:2)
template <std::size_t I, std::size_t... Is, typename T>
auto get(const T& x)
{
if constexpr(sizeof...(Is) == 0) { return x[I]; }
else { return get<Is...>(x[I]); }
}
用法:
using array4d = std::array<std::array<std::array<std::array<int, 6>, 6>, 6>, 6>;
int main()
{
array4d a;
a[1][2][3][4] = 42;
assert((get<1, 2, 3, 4>(a)) == 42);
}
如果您想要运行时版本:
template <typename T, typename... Is>
auto get(const T& x, std::size_t i, Is... is)
{
if constexpr(sizeof...(Is) == 0) { return x[i]; }
else { return get(x[i], is...); }
}
用法:
int main()
{
array4d a;
a[1][2][3][4] = 42;
assert(get(a, 1, 2, 3, 4) == 42);
}
请注意,我使用C ++ 17 if constexpr
来定义递归的基本案例。在C ++ 11中,您可以提供重载:
template <typename T>
int get(const T& x, std::size_t i)
{
return x[i];
}
template <typename T, typename... Is>
int get(const T& x, std::size_t i, Is... is)
{
return get(x[i], is...);
}