恢复生命周期结束的对象的成员函数协程是不是UB?

Is it UB to resume a member function coroutine of an object whose lifetime has ended?

这个问题源于这个评论:

关于这个例子:

auto foo() -> folly::coro::Task<int> {
    auto task = []() -> folly::coro::Task<int> {
        co_return 1;
    }();
    return task;
}

所以问题是执行foo返回的协程是否会导致UB。

"Calling"一个成员函数(在对象生命周期结束后)是UB:http://eel.is/c++draft/basic.life#6.2

...any pointer that represents the address of the storage location where the object will be or was located may be used but only in limited ways. [...] The program has undefined behavior if:

[...]

-- the pointer is used to access a non-static data member or call a non-static member function of the object, or

但是,在这个例子中:

此恢复是否被视为未定义行为?

[dcl.fct.def.coroutine]p3:

The promise type of a coroutine is std::coroutine_traits<R, P1, ..., Pn>::promise_type, where R is the return type of the function, and P1 ... Pn are the sequence of types of the function parameters, preceded by the type of the implicit object parameter (12.4.1) if the coroutine is a non-static member function.

隐式对象参数在您的示例中是一个 const 引用,因此在销毁闭包对象后恢复执行时该引用将悬空。

然而,关于在执行成员函数期间对象被销毁的注意事项,这本身确实很好,并且除了标准本身之外没有其他内容在 [basic] 中暗示这一点:

Before the lifetime of an object has started but after the storage which the object will occupy has been allocated or, after the lifetime of an object has ended and before the storage which the object occupied is reused or released, any pointer that represents the address of the storage location where the object will be or was located may be used but only in limited ways. [...]

void B::mutate() {
  new (this) D2;    // reuses storage --- ends the lifetime of *this
  f();              // undefined behavior
  ... = this;       // OK, this points to valid memory
}

(注意:上面的UB是因为隐含的this没有被洗白,仍然引用隐含的对象参数。)

因此,您的示例似乎定义明确,条件是恢复执行不属于与原始调用相同的规则。请注意,对闭包对象的引用可能是悬空的,但在暂停和恢复之间不会以任何方式访问它。