【问题标题】:Unroll loop at compile time在编译时展开循环
【发布时间】:2017-08-18 14:00:50
【问题描述】:

我想为i = 0,1, ... , n 将大量行写入foo(i) 形式的C++ 文件中,有没有办法在编译时执行此操作?

我想这样做是因为我有一个模板类:

template <int X> class MyClass{ ... }

我想测试很多不同的“X”值,例如:

for (int i = 0; i < n; i++) {
    MyClass<i> bar;
    bar.method()
 }

这不起作用,因为它希望在编译时确定作为模板值传递的值。

我可以写出整个事情:

MyClass<0> bar0; bar0.method();
MyClass<1> bar1; bar1.method();

我可以做一个定义来加快速度,比如:

#define myMacro(x) MyClass<x> bar_x; bar_x.method();

但我仍然必须在任何地方写myMacro,而且我会经常更改范围以使其变得明智。如果我可以编写某种 for 循环的宏版本,那会为我节省很多时间。

更新:我实际上需要将变量传递给我的方法,所以我对@Pascal 给出的接受的答案进行了轻微更改

template<int X> class MyClass { public: void foo(int Y) { std::cout << X Y<< std::endl; } };
template<int X> inline void MyTest(int Y) { MyTest<X - 1>(Y); MyClass<X-1> bar; bar.foo(Y); }
template<> inline void MyTest<1>(int Y) { MyClass<0> bar; bar.foo(Y); }

【问题讨论】:

  • 您是否需要将整数值作为模板参数(在编译时确定)而不是函数参数(在运行时确定)?
  • @Peter 这是因为我正在测试代码。有机会我会重写它,使它成为一个接受运行时参数的函数,但出于外部原因,重要的是不要触及代码。

标签: c++ compilation variadic-macros


【解决方案1】:

更接近“宏观方式”的解决方案可以是模板递归:

template<int X> class MyClass { public: void foo() { std::cout << X << std::endl; } };
template<int X> inline void MyTest() { MyTest<X - 1>(); MyClass<X-1> bar; bar.foo(); }
template<> inline void MyTest<1>() { MyClass<0> bar; bar.foo(); }
int main()
{
    MyTest<5>();
    return 0;
}

这个例子的输出是:

0
1
2
3
4

【讨论】:

  • 这不是“宏方式”,使用模板进行编译时循环的方式是像这样使用递归。
  • 这个解决方案的问题在于它会进行递归宏实例化,这不是必需的并且会减慢编译速度。
  • @Pascal : 声明一个内联函数并不能保证编译器会内联它。
【解决方案2】:

如果您的循环阈值在编译时已知,这非常容易:

template<class CB, size_t... Is> void unroll_loop_impl(std::index_sequence<Is...> {}, CB&& cb) {
    void* aux[] = {(cb(Is), nullptr)...};
    (void)aux;
}


template<size_t N, class CB> void unroll_loop(CB&& cb) {
     using index_seqeunce_t = std::make_index_sequence<N>;

     unroll_loop_impl(std::move(cb), index_sequence_t{});
}

【讨论】:

  • 我确实知道编译时的循环阈值,但很抱歉,我不明白这个解决方案。我看不到您的变量如何链接到我正在尝试使用的变量,而且我不熟悉您正在使用的一些 std 函数。我想一般原则是制作一个模板类,它传递一个类来展开?
  • @SergeyA - 您认为这“超级简单”,但 OP 显然不理解它。您可能希望解释它如何解决 OP 的问题。
猜你喜欢
  • 2021-10-04
  • 1970-01-01
  • 2011-09-02
  • 1970-01-01
  • 2011-12-03
  • 2011-10-08
  • 1970-01-01
  • 2021-12-26
  • 1970-01-01
相关资源
最近更新 更多