如何在编译时生成嵌套循环

Teo*_*lov 28 c++ templates metaprogramming c++11 c++14

我有一个整数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.
                }
          }
     }
}
Run Code Online (Sandbox Code Playgroud)

注意参数N在编译时是已知的,但可能在编译之间不可预测地改变,因此我不能像上面那样对循环进行硬编码.理想情况下,循环生成机制将提供一个接受lambda函数的接口,生成循环并调用函数产生如上所述的等效代码.我知道可以在运行时使用单个while循环和索引数组编写一个等效循环,并且已经有了这个问题的答案.但是,我对此解决方案不感兴趣.我对涉及预处理器魔法的解决方案也不感兴趣.

Nim*_*Nim 25

像这样的东西(注意:我把"形状"作为可变参数模板参数集..)

#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;
}
Run Code Online (Sandbox Code Playgroud)

  • @ Cheersandhth.-Alf,我的理解(其中可能会被破坏)是op想要生成一个任意维度循环,其中维度的数量是已知的但在编译时是可变的,并且该范围在编译时也是已知的,但是需要调用的函数是任意的.所以constexpr是没有实际意义的,它是生成任意维度循环的构造,而不必为OP所追求的所有维度明确地手动编码各个循环? (2认同)