C ++ 11:std :: get<>相当于n维数组

时间:2017-09-04 09:59:16

标签: c++ c++11 templates template-meta-programming

我想知道是否有类似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;
}

1 个答案:

答案 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);
}

live wandbox example

如果您想要运行时版本:

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);
}

live wandbox example

请注意,我使用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...);
}

live example on wandbox