Recursive lambda expressions in C++

Previous: Lambda expressions in C++

Unlike Python, C++ lambdas don’t support generic recursion. There are workarounds, but they all come with meaningful drawbacks. Additionally, I believe recursion has little place in production code, recursive lambdas even less so. The options below are fun to know, but should be considered trivia at best.

std::function

#include <functional>
std::function<int(int)> factorial = [&](int n) -> int {
  return n <= 1 ? 1 : n * factorial(n - 1);
};

Works from C++11 onward. The main drawback is that you must spell out all parameter types inside the std::function template, which largely defeats the brevity that made you want a lambda in the first place. There’s also a runtime overhead cost from type erasure.

Self-reference via parameter

auto factorial = [](auto self, int n) -> int {
  return n <= 1 ? 1 : n * self(self, n - 1);
};

No overhead, but the calling convention is awkward — you have to pass the lambda into itself: factorial(factorial, 5). This leaks the implementation detail to every call site.

Y-combinator

auto y = [](auto f) {
  return [=](auto... args) {
    return f(f, args...);
  };
};

auto factorial = y([](auto self, int n) -> int {
  return n <= 1 ? 1 : n * self(self, n - 1);
});

This is getting into extreme trivia territory. It’s a neat functional programming pattern that produces a clean call site, with the downside of being incredibly opaque.

Conclusion

Please just write a named function