【问题标题】:Static multidimensional array, dimensionality definition at compile time静态多维数组,在编译时定义维度
【发布时间】:2019-11-28 20:32:34
【问题描述】:

是否有任何语法可以在编译时定义静态数组的维度?假设我有一个大小为 D 的元组,其值为 d_0,...,d_{D-1}。我希望能够创建一个数组T arr[d_0][d_1]...[d_{D-1}]。有没有办法在编译时实现这一点?我专门询问静态数组语法,而不是如何嵌套结构。

这是一个代码 sn-p 来阐明我想要实现的目标:

template<typename T, template<typename, auto> typename Container, auto DimC, auto...Dim>
struct NestedContainer
{
    using type = Container<typename NestedContainer<T, Container, Dim...>::type, DimC>;
};

template<typename T, template<typename, auto> typename Container, auto Dim>
struct NestedContainer<T, Container, Dim>
{
    using type = Container<T, Dim>;
};

template<typename T, int D>
struct Arr
{
    T e[D];

    T& operator[](int i) { return e[i]; }
};

template<typename T, int D, int...Dim>
struct MultiArr
{
    using multi_arr = typename NestedContainer<T, Arr, Dim...>::type;
    multi_arr e[D];

    auto& operator[](int i) { return e[i]; }
};

这样使用:

MultiArr<float, 3, 3, 3> a;
a[2][2][2] = 3;

我很好奇这是否可以通过某种形式的语法来实现,而无需嵌套类。

【问题讨论】:

  • tuple 中的值在编译时是否已知(是constexpr)?
  • 另外,你会接受std::array 来代替原始数组吗?
  • @NathanOliver 不,我特意询问的是一个普通的静态数组。元组是编译时间。
  • 似乎您正在搜索某种宏来生成尺寸括号。但是我怀疑在编译时是否存在一种通用的填充括号方法,而无需明确地对每组可能的数组维度进行硬编码
  • 范围是来自实际的std::tuple 对象,还是像MultiArr&lt;float, 3, 3, 3&gt; 示例中那样以逗号分隔的列表形式输入?

标签: c++ arrays c++17 compile-time


【解决方案1】:

使用模板元编程递归可以轻松完成。唯一棘手的是您需要以正确的顺序应用范围。请注意,int[x][y] 是(概念上)(int[y])[x]。

#include <cstddef>
#include <type_traits>

template <typename E, size_t... extents>
struct MultiArrHelper;

template <typename E>
struct MultiArrHelper<E> {
    using type = E;
};

template <typename E, size_t extent, size_t... extents>
struct MultiArrHelper<E, extent, extents...> {
    using type = typename MultiArrHelper<E, extents...>::type[extent];
};

template <typename E, size_t... extents>
using MultiArr = typename MultiArrHelper<E, extents...>::type;

int main() {
    MultiArr<int, 2, 2, 3> a;
    static_assert(std::is_same<decltype(a), int[2][2][3]>::value);
}

http://coliru.stacked-crooked.com/a/6b89020318e78b90

【讨论】:

  • type[extent] 的作用对吗?据我所知,这会递归并不断添加括号,直到它到达类型然后附加它。这正是我想要实现的目标,但我不确定你能做到这一点。谢谢。
  • @lightxbulb 诀窍是在最后应用第一个范围;这就是它的作用。如果我们想先应用第一个范围(这会给出错误的答案),那么 [extent] 将在 E 之后,而不是在末尾。
  • 等等,反之亦然吗?当我阅读它时,假设我调用MultiArr&lt;int,e1,e2&gt;,那么首先我们将到达递归的底部,设置type = int,然后设置type = (int)[e2],然后设置type = (int[e2])[e1]?这在某种意义上是不是相反,还是我误解了它? (int[e2])[e1] 是否真的等同于 int[e1][e2]? (我放括号只是为了强调应用的顺序。
  • @lightxbulb 我已经解释过了。您需要执行(int[e2])[e1] 以获得所需的结果int[e1][e2]。
  • 谢谢你的澄清,我不确定我是否理解正确,现在我明白你的意思了。
猜你喜欢
  • 1970-01-01
  • 2022-01-16
  • 2015-06-23
  • 1970-01-01
  • 2012-02-25
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多