C++ 查找 co_await 等待结果类型

Vic*_*kel 7 c++ c++20 c++-coroutine

我想知道是否有可能找到可等待的 co_await 的结果类型:因为不可能在未评估的上下文中使用 co_await,我不能做

template<class Awaitable>
task<> f(Awaitable&& awaitable)
{
  using result_type = decltype(co_await awaitable);
}
Run Code Online (Sandbox Code Playgroud)

有什么办法可以做到吗?

这里的主要目的是确定result_type是否为void,这里基本上是我们所拥有的:我们想要fire_and_forget一个任务,并在完成时调用一个方法,但由于void返回类型,这并不容易

template<class Awaitable, class Success, class Failure >
detail::fire_and_forget_task call_async_then(Awaitable awaitable, Success success, Failure failure)
{
  try
  {
    using result_type = ??
    if constexpr (std::is_same_v<void, result_t>)
    {
      co_await awaitable;
      success();
    }
    else
      success(co_await f);
  }
  catch(...)
  {
    failure(std::current_exception());
  }
}
Run Code Online (Sandbox Code Playgroud)

也许有一个更简单的方法来做到这一点,但现在我没有想到任何方法。

谢谢

Nic*_*las 2

There is no way to do this generally because co_await's coroutine machinery is in part dependent on the promise type for the function that invokes co_await. When a co_await <expr> is invoked, it will have to transform <expr> into an awaitable type. Part of that process involves asking the promise type for the coroutine to weigh in on this conversion if it so chooses. Since the promise type is defined by the signature of the coroutine, the result type of any co_await <expr> is therefore dependent on the signature of the function invoking it.

This is why co_await cannot be used in an unevaluated context; it's behavior is context-dependent.

Now, if you know that your promise type does not have await_transform (which you probably do know, since it's your promise type), then the result type is possible to compute. The awaitable type for co_await <expr> will just be the type of <expr>. This is then converted into an awaiter object via invoking operator co_await on the expression. That's a bit difficult to compute, as it could be invoked via a member function or a non-member operator call, so it's a tricky bit of metaprogramming.

一旦你有了等待者对象类型,你就可以获得它的返回类型await_resume();这是表达式的类型co_await <expr>