如何在C++中编写内联递归Lambda?C++20/23是否有新方案?
C20与C23中的递归Lambda实现方案
针对你提到的C17递归Lambda需要额外传递self参数的痛点,C20和C++23确实提供了更简洁的实现方式,同时也能解决你关心的内联优化问题:
C++20的实现方式
在C++20中,你可以通过两种方式实现无需显式传递self的递归Lambda:
方式一:借助std::function
这种写法无需额外传递self,代码更简洁,示例如下:
#include <functional> int main() { std::function<void(int)> dfs; dfs = [&](int x) -> void { if (x >= 5) return; // 直接调用自身 dfs(x + 1); }; dfs(0); }
虽然std::function存在类型擦除的理论开销,但开启优化(如-O2)后,GCC、Clang、MSVC等主流编译器都会尽可能消除这部分开销并完成内联。
方式二:手动实现Y组合子
如果你想完全避免类型擦除,可以用Y组合子实现零开销的递归Lambda,示例如下:
template<typename F> struct YCombinator { F f; template<typename... Args> decltype(auto) operator()(Args&&... args) { return f(*this, std::forward<Args>(args)...); } }; template<typename F> YCombinator(F) -> YCombinator<F>; int main() { auto dfs = YCombinator{[&](auto& self, int x) -> void { if (x >= 5) return; self(x + 1); }}; dfs(0); }
这种写法没有类型擦除的额外开销,编译器更容易进行内联优化,性能表现和C++17的self传递方案相当甚至更优。
C++23的原生递归Lambda
C++23直接支持原生递归Lambda,这是最简洁的实现方式,无需任何额外工具,示例如下:
int main() { auto dfs = [&](int x) -> void { if (x >= 5) return; // 直接调用自身,无需额外参数或包装 dfs(x + 1); }; dfs(0); }
这种语法完全消除了C++17方案中传递self的繁琐,而且因为是原生语法,编译器对这种递归模式的识别更直接,开启优化后几乎都能轻松完成内联,不会有性能损耗。
关于内联的补充说明
你担心的C17方案内联问题,实际上主流编译器在开启-O2及以上优化级别时,都能识别self传递的递归模式并完成内联。而C23的原生递归Lambda因为语法更贴合编译器的优化逻辑,内联的可靠性和效率会更高。
内容的提问来源于stack exchange,提问作者Junhui Zhu
相关产品推荐
相关产品推荐

