C++ lambda的深递归
我有一个由N级循环组成的程序。但N不是固定的,所以我使用模板来帮助。逻辑如下C++ lambda的深递归,c++,lambda,C++,Lambda,我有一个由N级循环组成的程序。但N不是固定的,所以我使用模板来帮助。逻辑如下 #include <type_traits> void do_something1() {} void do_something2() {} enum Case { one, two }; struct loop { template<int N, Case case_, typename Lambda> std::enable_if_t < (0 < N) >
#include <type_traits>
void do_something1() {}
void do_something2() {}
enum Case { one, two };
struct loop {
template<int N, Case case_, typename Lambda>
std::enable_if_t < (0 < N) > func(Lambda&& visit) const {
//return directly in some cases, so complexity is not a problem
func<N - 1, one>([&visit] {
do_something1();// depend on the results of func<N - 1, one>
visit();
});
func<N - 1, two>([&visit] {
do_something2();// depend on the results of func<N - 1, two>
visit();
});
}
template<int N, Case case_, typename Lambda>
std::enable_if_t < (0 == N) > func(Lambda&& visit) const {
visit();
}
};
int main() {
loop{}.func<32, one>([] {});
return 0;
}
但是,由于深度递归,这将无法编译。在我看来,是内联和func中的两个分支导致了这个问题。那么,有没有一种有效的方法来解决这个问题呢?内联可以解决运行时的复杂性。提前返回也解决了运行时的复杂性。但是,编译器错误是因为您具有编译时复杂性。即使是无法访问的代码也必须编译 如果编译器将其内联,那么该代码将具有巨大的复杂性。这两个分支都是内联的,这意味着f的//return-early-check在f中内联两次,f的//return-early-check在f中内联两次,因此在f中内联4次,因此f将内联大约40亿次。任何一个好的编译器都不应该有这样的问题;它应该跳过内联
简单的解决方法是去掉Case,反正它不使用,并使N成为正则变量。一个更复杂的方法是在运行时检查变量N是否有一些小的常量值Nc,然后才调用该函数的模板化版本。通过选择Nc,您可以限制模板实例化深度。您有2**32个函数调用要访问和函数实例化…@Jarod42我认为有4*32个访问,即每个N和case。在模板参数中,如果添加括号,比较会更清楚:std::enable_if_t