How can I write a beautiful inline recursive lambda in C++?

1.6k views Asked by At

As I know in C++17, I can write a recursive lambda like this:

auto dfs = [&](const auto &self, int x) -> void {
    // ....
    self(self, x);
};

dfs(dfs, 0);

Unfortunately, I have to endure one more parameter which is a bit ugly. And I doubt the possibility for the compiler to make it inline. Are there new options in new C++ standards? (C++20 or C++23)

3

There are 3 answers

4
Artyer On

You can use an explicit object parameter with a deduced type:

auto dfs = [&](this const auto &self, int x) -> void {
    // ....
    self(x);
};

dfs(0);  // `self` is `dfs`

This is a C++23 feature

0
sudo rm -rf slash On

I'm not sure if this counts as beautiful, but you might consider this:

std::function<void(int)> dfs = [&](int x) -> void {
    // ....
    dfs(x);
};

dfs(0);

The compiler may be able to inline the std::function call, but only in simple cases. Of course, it cannot fully inline a recursive function.

0
Neil On

If you don't have access to C++23 then you can wrap your lambda in another lambda that hides the extra argument, e.g. like this:

int main(int argc, char **argv) {
    auto fact = [&](int x) -> int {
        auto do_fact = [&](const auto &self, int x) -> int {
            return x ? x * self(self, x - 1) : 1;
        };
        return do_fact(do_fact, x);
    };
    return fact(argc);
}

clang with -O and gcc with -O2 will compile the above into a simple multiplication loop (clang tries to be extra clever at higher optimisation levels).