Mik*_*ail 6 c++ arrays variadic-templates c++11
我想创建一个由一些已知函数填充的2D数组,没有运行时开销.
有一个例子,假设一个功能f(x, y) = 10 * y + x,让x在{1, 2, 3}和y中{4, 5, 6}.我想创建一个包含内容的2D数组
41 42 43
51 52 53
61 62 63
Run Code Online (Sandbox Code Playgroud)
现在,最简单的方法就是直接在我的源代码中对值进行硬编码.这确实适合我的任务,所以问题只是出于好奇.
我想创建一个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;
Run Code Online (Sandbox Code Playgroud)
如果我从表中打印值,我有:
41 52 63
0 0 0
0 0 0
Run Code Online (Sandbox Code Playgroud)
我明白发生了什么,术语Func<args1>::over<args2>::value有两个参数包在里面,args1和args2,因此应用...上他们同时展开,而我只有3名成员,而不是9.
如果到目前为止,你已经明白了我想要的东西.所以问题是,我该怎么做?如何将省略号分别应用于两个参数包,以便我可以在初始化程序中使用笛卡尔组合?或者也许有其他方法可以做到这一点?
我知道这个答案和答案.它们使用std::array而不是普通数组,因此它们首先构造1D数组,然后使用多个1D数组初始化2D数组.但如果我理解正确,这个初始化必须在运行时完成.我想避免这种情况.但是,我没有异议std::array.我认为通过适当的编译器,它们与普通数组一样快.
顺便说一下,这是我使用C++ 14中的通用解决方案constexpr和关于它的问题的可能解决方案.关于如何使用constexprC++ 11 解决任务的任何想法也受到欢迎.
我发现它的唯一方法是用逗号分隔参数包并展开其中一个,然后从外部展开另一个:
#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>()
));
Run Code Online (Sandbox Code Playgroud)
asm结果是这样的:
table:
.long 41
.long 42
.long 43
.long 51
.long 52
.long 53
.long 61
.long 62
.long 63
Run Code Online (Sandbox Code Playgroud)