首页 > 解决方案 > C++ 查找 co_await 等待结果类型

问题描述

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

template<class Awaitable>
task<> f(Awaitable&& awaitable)
{
  using result_type = decltype(co_await awaitable);
}

有什么办法可以做到吗?

这里的主要目的是确定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());
  }
}

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

谢谢

标签: c++c++20c++-coroutine

解决方案


通常没有办法做到这一点,因为协co_await机制部分依赖于调用函数的承诺类型co_await。调用a 时co_await <expr>,它必须转换<expr>为可等待类型。该过程的一部分涉及要求协程的承诺类型在此转换中权衡(如果它愿意)。由于 promise 类型是由协程的签名定义的,因此 any 的结果类型co_await <expr>取决于调用它的函数的签名。

这就是为什么co_await不能在未评估的上下文中使用的原因;它的行为取决于上下文。

现在,如果您知道您的 Promise 类型没有await_transform(您可能确实知道,因为它是您的Promise 类型),那么可以计算结果类型。for 的可等待类型co_await <expr>将只是<expr>. 然后通过调用表达式将其转换为等待者对象operator co_await。这有点难以计算,因为它可以通过成员函数或非成员运算符调用来调用,所以它是元编程的一个棘手位。

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


推荐阅读