我有一个整数 N ,在编译时知道。我也有一个 std::array ,其中包含描述 N -维数组形状的整数。我想在编译时使用元编程技术生成嵌套循环,如下所述。
constexpr int N {4};
constexpr std::array<int, N> shape {{1,3,5,2}};
auto f = [/* accept object which uses coords */] (auto... coords) {
// do sth with coords
};
// This is what I want to generate.
for(int i = 0; i < shape[0]; i++) {
for(int j = 0; j < shape[1]; j++) {
for(int k = 0; k < shape[2]; k++) {
for(int l = 0; l < shape[3]; l++) {
f(i,j,k,l) // object is modified via the lambda function.
}
}
}
}
请注意,参数 N 在编译时是已知的,但在编译之间可能会发生不可预测的变化,因此我无法对上述循环进行硬编码。理想情况下,循环生成机制将提供一个接受lambda函数,生成循环并调用该函数的接口(interface),以产生与上述相同的代码。我知道一个人可以在运行时用一个while循环和一个索引数组编写一个等效的循环,并且已经有这个问题的答案。但是,我对此解决方案不感兴趣。我对涉及预处理器魔术的解决方案也不感兴趣。
最佳答案
这样的事情(注意:我将“形状”作为可变参数模板参数集。)
#include <iostream>
template <int I, int ...N>
struct Looper{
template <typename F, typename ...X>
constexpr void operator()(F& f, X... x) {
for (int i = 0; i < I; ++i) {
Looper<N...>()(f, x..., i);
}
}
};
template <int I>
struct Looper<I>{
template <typename F, typename ...X>
constexpr void operator()(F& f, X... x) {
for (int i = 0; i < I; ++i) {
f(x..., i);
}
}
};
int main()
{
int v = 0;
auto f = [&](int i, int j, int k, int l) {
v += i + j + k + l;
};
Looper<1, 3, 5, 2>()(f);
auto g = [&](int i) {
v += i;
};
Looper<5>()(g);
std::cout << v << std::endl;
}