简体   繁体   English

在编译时使用给定函数初始化纯2D数组

[英]Initialize plain 2D array with a given function on compile time

I want to create a 2D-array populated by some known function with no runtime overhead . 我想创建一个由一些已知函数填充的2D数组, 没有运行时开销

To have an example, suppose a function f(x, y) = 10 * y + x , let x be in {1, 2, 3} and y in {4, 5, 6} . 举个例子,假设函数f(x, y) = 10 * y + x ,令x{1, 2, 3}并且在{4, 5, 6} {1, 2, 3} y I want to create a 2D array with content 我想创建一个包含内容的2D数组

41 42 43
51 52 53
61 62 63

Now, the easiest way to go is just hard-code the values directly in my sources. 现在,最简单的方法就是直接在我的源代码中对值进行硬编码。 And it is indeed appropriate for my task, so the question is just out of curiosity. 这确实适合我的任务,所以问题只是出于好奇。

I would like to create a metafunc and a struct possessed with some kind of black magic, which allows me to define an array out of given sets of values for x and y . 我想创建一个metafunc和一个拥有某种黑魔法的结构,它允许我用xy的给定值集定义一个数组。 Like this: 像这样:

template<int X> struct Func {
  template<int Y> struct over {
    static const int value = 10 * Y + X;  // f(x, y)
  };
};

template<int... args1> struct Rows {
  template<int... args2> struct Cols {
    static const int data[sizeof...(args1)][sizeof...(args2)];
  };
};

template<int... args1>
template<int... args2>
const int Rows<args1...>::Cols<args2...>::data[sizeof...(args1)][sizeof...(args2)] = {
  { Func<args1>::over<args2>::value... }  // This does not do what I want :(
                                          // Need some black magic here
};

// Here is my precious table
const auto& table = Rows<1, 2, 3>::Cols<4, 5, 6>::data;

If I print values from the table, I have this: 如果我从表中打印值,我有:

41 52 63
 0  0  0
 0  0  0

I understand what's happening, the term Func<args1>::over<args2>::value has two parameter packs in it, args1 and args2 , so applying ... on it expand them simultaneously, and I only have 3 members instead of 9. 我理解发生了什么,术语Func<args1>::over<args2>::value有两个参数包, args1args2 ,所以应用...就可以同时扩展它们,而我只有3个成员而不是9。

If you've reached so far, you've already understood what I want. 如果到目前为止,你已经明白了我想要的东西。 So the question is, how do I do it? 所以问题是,我该怎么做? How do I apply ellipsis separately to both parameter packs so I can have cartesian combination in the initializer? 如何将省略号分别应用于两个参数包,以便我可以在初始化程序中使用笛卡尔组合? Or maybe there are some other ways to do it? 或者也许有其他方法可以做到这一点?

I am aware of this answer and that answer . 我知道这个答案答案 They use std::array instead of plain array, so they first construct 1D-arrays, and then initialize 2D-array with a number of 1D-array. 它们使用std::array而不是plain数组,因此它们首先构造1D数组,然后使用多个1D数组初始化2D数组。 But if I understood correctly, this initialization has to be done in runtime . 但如果我理解正确,这个初始化必须在运行时完成。 I want to avoid that. 我想避免这种情况。 However, I have no objections against std::array . 但是,我对std::array没有异议。 I suppose that with a proper compiler they are just as fast as plain arrays. 我认为通过适当的编译器,它们与普通数组一样快。

By the way, here is my possible solution using generalized constexpr from C++14 and a question about it. 顺便说一句,这是我使用来自C ++ 14的通用constexpr以及关于它的问题的可能解决方案 Any ideas on how to solve the task with constexpr from C++11 are also welcomed. 关于如何用C ++ 11中的constexpr解决任务的任何想法也受到欢迎。

The only way I found it is to separate the parameter packs by commas and expand one of them, and then to expand the other from the outside: 我发现它的唯一方法是用逗号分隔参数包并展开其中一个,然后从外部扩展另一个:

#include <array>
#include <utility>

using namespace std;

template<class T, T Y, T... Xs>
constexpr array<T, sizeof...(Xs)> a1{10*Y+Xs...};

template<class T, T... Xs, T... Ys>
constexpr auto a2(integer_sequence<T, Xs...>, integer_sequence<T, Ys...>) {
    return array<array<T, sizeof...(Xs)>, sizeof...(Ys)>{a1<T, Ys, Xs...>...};
}

array<array<int, 3>, 3> table(a2(
    integer_sequence<int, 1, 2, 3>(),
    integer_sequence<int, 4, 5, 6>()
));

The asm result is this: asm结果如下:

table:
        .long   41
        .long   42
        .long   43
        .long   51
        .long   52
        .long   53
        .long   61
        .long   62
        .long   63

Code in Compiler Explorer 编译器资源管理器中的代码

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM