web-dev-qa-db-ja.com

C ++はco_await awaitable結果タイプを見つけます

Awaitableの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());
  }
}

たぶんもっと簡単な方法があるかもしれませんが、今のところ私は考えていません。

ありがとうございました

7
Victor Burckel

ありがとうございます。decltype(co_await awaitable)が許可されない理由がわかりました。だから私があなたをよく理解していて、疑似コードを https://lewissbaker.github.io/2017/11/17/understanding-operator-co-await から受け取って、 awaitable型(簡略化のために非メンバー演算子をスキップするとします)、次のような結果が得られます(おそらく、検出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

よろしいですか?

0
Victor Burckel