Search code examples
c++lambdaclosuresc++20c++-coroutine

Is it safe to capture `this` in a coroutine lambda (C++)


I've been working with c++20 coroutines and I stumbled upon this issue with the lifetime of the lambda captures not extending for the entire life of the coroutine.

I was wondering what's safe to capture, since I've been having to copy all my captures into new objects like this:

[a1=object]() -> task<void> {
    // need to copy into a new object to safely reference for the lifetime of the coroutine
    auto object = a1;
    co_await something;
    // ...

When I captured this explicitly in my program:

[this]() -> {
    co_await something;
    this->....

I was able to reference this after a suspend with no issue.

However, when reading the standard, I found this:

An entity is captured by reference if it is implicitly or explicitly captured but not captured by copy. It is unspecified whether additional unnamed non-static data members are declared in the closure type for entities captured by reference.

Given that whether it creates the pointer as a property is "unspecified", does this mean I just got lucky? Or is there something different about this captures?


Solution

  • Programmers should ignore that sentence in the standard: it merely allows implementations to allocate less memory than might naïvely be expected for lambda objects with reference captures (especially when the call operator is inlined).