如何在编译时生成嵌套循环 [英] How to generate nested loops at compile time

查看:79
本文介绍了如何在编译时生成嵌套循环的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个整数 N ,我在编译时就知道.我还有一个 std :: array ,其中包含描述 N 维数组形状的整数.我想在编译时使用元编程技术生成嵌套循环,如下所述.

I have an integer N which I know at compile time. I also have an std::array holding integers describing the shape of an N-dimensional array. I want to generate nested loops, as described bellow, at compile time, using metaprogramming techniques.

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函数,生成循环并调用该函数的接口,以产生与上述相同的代码.我知道一个人可以在运行时用一个while循环和一个索引数组编写一个等效的循环,并且已经有这个问题的答案.但是,我对此解决方案不感兴趣.我对涉及预处理器魔术的解决方案也不感兴趣.

Note the parameter N is known at compile time but might change unpredictably between compilations, hence I can't hard code the loops as above. Ideally the loop generation mechanism will provide an interface which accepts the lambda function, generates the loops and calls the function producing the equivalent code as above. I am aware that one can write an equivalent loop at runtime with a single while loop and an array of indices, and there are answers to this question already. I am, however, not interested in this solution. I am also not interested in solutions involving preprocessor magic.

推荐答案

这样的事情(注意:我将形状"作为可变参数模板参数集.)

Something like this (NOTE: I take the "shape" as a variadic template argument set..)

#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;
}

这篇关于如何在编译时生成嵌套循环的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆