1

Is there a way to refer to the closure object from inside its operator()?
Simplified version of what I'd like to do with Boost.Asio:

tcp::acceptor acceptor;

auto handler = [&acceptor]( )
{
    // ...
    acceptor.async_accept( *this );
};

acceptor.async_accept( handler );

But there is no separate this for lambdas.
And I cannot capture reference to handler, because its type isn't yet known. The only workaround I see now is to write separate functor class, simply because there is a this-pointer.

Deduplicator
  • 44,692
  • 7
  • 66
  • 118
Vasyl Demianov
  • 305
  • 1
  • 9

1 Answers1

2

You're right, you cannot write recursive lambdas in C++11, 14 and 17, nor collections of mutually recursive lambdas.

Several future extensions have been suggested that would enable this, but nothing is decided as of yet. Current workarounds consist of creating a type-erasing std::function wrapper, or indeed as you point out, to just write your own functor classes.

(The latter is generally always an option when you have a question of the sort "can lambdas do X" -- lambdas are just syntactic sugar around existing language features, and those features will always be there when you need them.)

Kerrek SB
  • 464,522
  • 92
  • 875
  • 1,084
  • Well, the better work-around is [using a Y-combinator](https://stackoverflow.com/a/40873657/3204551). After defining it once, one can always reuse it. – Deduplicator Aug 25 '18 at 21:48
  • @Deduplicator: Thanks for the link. That's certainly a nice piece of code, though I'd put that in the "custom class" kind of solution. You could perhaps also make a case about that solution requiring templates (even for one specific instance of recursion), when a case-specific custom class might be able to do the same job but be simpler. But it looks like a nice tool for sure. – Kerrek SB Aug 25 '18 at 22:39
  • ha! never tried or even got interest in std::function, but it turned out super easy and almost as concise as lambda itself! to fix my original code, what is only needed is replace auto with std::function< void () > and then it is possible to capture it. thanks! :) – Vasyl Demianov Aug 26 '18 at 11:44
  • @VasylDemianov: Yes, but beware that this comes at significant runtime cost, since `std::function` type-erases the callable, and so there's a dynamic dispatch involved at every call. – Kerrek SB Aug 26 '18 at 14:36
  • @KerrekSB, why significant? It's only virtual method call, basically one additional dereference, no? I have an idea how it works, I implemented shared pointer and its shared state object as an excercise, pretty neat. :) – Vasyl Demianov Aug 27 '18 at 18:25
  • @VasylDemianov: Well, it's significant in general, since the cost *may* be high compared to the cost of the lambda body itself. It is of course possible to have a situation where the cost is insignificant. But for a general-purpose answer the cost should be pointed out, and it's up to you whether you can tolerate it. – Kerrek SB Aug 28 '18 at 00:19