在编译时展开循环
Unroll loop at compile time
我想为 i = 0,1, ... , n
将大量行写入 foo(i)
形式的 C++ 文件中,有没有办法在编译时执行此操作?
我想这样做是因为我有一个模板 class:
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); }
如果您的循环阈值在编译时已知,这非常容易:
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{});
}
更接近"macro way"的解决方案可以是模板递归:
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
我想为 i = 0,1, ... , n
将大量行写入 foo(i)
形式的 C++ 文件中,有没有办法在编译时执行此操作?
我想这样做是因为我有一个模板 class:
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); }
如果您的循环阈值在编译时已知,这非常容易:
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{});
}
更接近"macro way"的解决方案可以是模板递归:
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