【问题标题】:C++11: std::get<> equivalent for n-dimensional arraysC++11:n 维数组的 std::get<> 等效项
【发布时间】:2017-09-04 09:59:16
【问题描述】:

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

【问题讨论】:

  • 你的阵列是什么样的?它真的是多维的arr[0][1][2] 还是用作多维的一维数组?
  • 我更新了问题,真的是[][][]..
  • 我认为有必要将 [] 运算符推广到参数包的需要:/

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


【解决方案1】:
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

【讨论】:

  • 编译时数组索引的意义何在?我们为此提供了元组。 OP 想要一个接收包(常规、非模板)参数的函数,例如 get(a,1,2,3,1)
  • 问题不太清楚 - 还添加了运行时版本。
  • 测试了一下,c++11的东西好像因为类型推导问题无法编译。
  • @dgrat:我添加了一个实例
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-08-23
  • 1970-01-01
  • 2011-08-14
  • 1970-01-01
  • 2021-02-22
相关资源
最近更新 更多