C++查找co-await不可用的结果类型



我想知道是否可以找到awaitable的coawait的结果类型:由于不可能在未评估的上下文中使用co-await,我无法进行

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

有什么办法可以做到这一点吗?

这里的主要目的是确定result_type是否为void,这基本上就是我们所拥有的:我们想触发_and_fullet任务,并在完成时调用一个方法,但由于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());
}
}

也许有一种更简单的方法,但现在我想不出任何方法。

谢谢

通常无法做到这一点,因为co_await的协程机制在一定程度上依赖于调用co_await的函数的承诺类型。当调用co_await <expr>时,它将不得不将<expr>转换为一个不可用的类型。这个过程的一部分涉及要求协同程序的promise类型参与这个转换(如果它选择的话(。由于promise类型是由协程的签名定义的,因此任何co_await <expr>的结果类型都取决于调用它的函数的签名

这就是为什么co_await不能在未评估的上下文中使用;它的行为是上下文相关的。

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

一旦有了awaiter对象类型,就可以获得其await_resume()的返回类型;这就是CCD_ 12表达式的类型。

好的,非常感谢,现在我明白了decltype(co_await awaitable)不被允许的原因。所以,如果我很好地测试了你,如果我从https://lewissbaker.github.io/2017/11/17/understanding-operator-co-await为了从awaitable类型中获得awaiter(假设为了简化,我跳过了非成员运算符(,我可以得到这样的结果(也许还有更简单的东西,我不习惯写检测idom(:

#include <type_traits>
template< class, class = std::void_t<> >
struct has_co_await_operator : std::false_type
{};
template< class T >
struct has_co_await_operator< T, std::void_t< decltype(std::declval<T>().operator co_await()) > >
: std::true_type
{};
template< class T >
constexpr bool has_co_await_operator_v = has_co_await_operator<T>::value;
template< class T >
struct get_awaiter : std::conditional< has_co_await_operator_v<T>, decltype(std::declval<T>().operator co_await()), T>
{};
template<class T>
using get_awaiter_t = typename get_awaiter<T>::type;
template<class Awaitable>
struct awaitable_result
{
using type = decltype(std::declval<get_awaiter_t<Awaitable>>().await_resume());
};
template<class T>
using awaitable_result_t = typename awaitable_result<T>::type;

https://godbolt.org/z/dAVfVX

你觉得可以吗?

相关内容

最新更新