【发布时间】:2015-12-09 18:50:27
【问题描述】:
我想创建一个由一些已知函数填充的二维数组,没有运行时开销。
举个例子,假设一个函数f(x, y) = 10 * y + x,让x在{1, 2, 3}中,y在{4, 5, 6}中。我想创建一个包含内容的二维数组
41 42 43
51 52 53
61 62 63
现在,最简单的方法就是直接在我的源代码中对值进行硬编码。它确实适合我的任务,所以这个问题只是出于好奇。
我想创建一个 metafunc 和一个拥有某种黑魔法的结构,它允许我从x 和 y 的给定值集定义一个数组。像这样:
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;
如果我从表中打印值,我有这个:
41 52 63
0 0 0
0 0 0
我了解发生了什么,术语Func<args1>::over<args2>::value 中有两个参数包,args1 和args2,因此在其上应用... 同时扩展它们,我只有 3 个成员而不是 9 个。
如果你已经达到了这么远,那么你已经明白我想要什么了。所以问题是,我该怎么做?如何将省略号分别应用于两个参数包,以便在初始化程序中使用笛卡尔组合?或者也许还有其他方法可以做到这一点?
我知道this answer 和that answer。他们使用std::array而不是普通数组,所以他们首先构造一维数组,然后用多个一维数组初始化二维数组。但如果我理解正确的话,这个初始化必须在运行时完成。我想避免这种情况。但是,我对std::array 没有异议。我想通过适当的编译器,它们和普通数组一样快。
顺便说一句,这是我的possible solution 使用 C++14 中的通用constexpr 和一个关于它的问题。也欢迎任何关于如何使用 C++11 中的 constexpr 解决任务的想法。
【问题讨论】:
-
先遍历行,再遍历列。
-
我太可怕了,但现在写的方式是“模棱两可的”。该结构是嵌套的,但它没有嵌套的模板迭代。因此,也许可以尝试为顶级结构指定类型,然后使用可变参数列表创建另一个具有第二级严格的类型。然后用顶级实例化案例实例化一个特定案例。
-
你真的需要二维数组吗?您刚刚找到了一维数组的解决方案
-
澄清一下,如果您不嵌套模板级别,编译器将同时遍历行和列。但您想要的方式是,为每一行、每一列计算一个值。因此,对于每一行,指定一个列值数组。为行提供一个固定类型的实例化,并为列留下一个“开放的”可变参数列表。
-
@MrPisarik 同意。但这确实是一个好奇的问题。
标签: c++ arrays c++11 variadic-templates