使用带有 c++20 协程的具体执行器类型的 Boost asio 会导致编译错误

问题描述 投票:0回答:1

我正在使用 Boost ASIO 库和 C++20 协程实现一个非常简单的 UDP 客户端。

为了尝试以较低的成本获得一点性能,我尝试使用具体的执行器类型

asio::io_service::executor_type
而不是多态
asio::any_io_executor

这是一个例子:

using executor_type = asio::io_context::executor_type;
using udp_resolver_type = asio::ip::basic_resolver<asio::ip::udp, executor_type>;

asio::io_context ctx;
udp_resolver_type resolver{ctx};

asio::awaitable<asio::ip::udp::endpoint, executor_type> host_to_endpoint(std::string host) {
    asio::ip::udp::resolver::query query{std::move(host), "1234"};
    const auto endpoints = co_await resolver.async_resolve(query, asio::use_awaitable);

    co_return *endpoints.begin();
}

然而,编译错误发生在

co_await resolver.async_resolve
:

error: no matching member function for call to 'await_transform'
   13 |     const auto endpoints = co_await resolver.async_resolve(query, asio::use_awaitable);
note: candidate function not viable: no known conversion from 'decltype(asio::async_initiate<const asio::use_awaitable_t<> &, void (asio::error_code, results_type)>(declval<initiate_async_resolve>(), token, q))' (aka 'awaitable<asio::ip::basic_resolver_results<asio::ip::udp>, asio::any_io_executor>') to 'this_coro::executor_t' for 1st argument
  203 |   auto await_transform(this_coro::executor_t) noexcept
... several other candidate functions ...
note: candidate template ignored: could not match 'asio::io_context::basic_executor_type<std::allocator<void>, 0>' against 'asio::any_io_executor'
  168 |   auto await_transform(awaitable<T, Executor> a) const
note: candidate template ignored: substitution failure [with Op = decltype(asio::async_initiate<const asio::use_awaitable_t<> &, void (asio::error_code, results_type)>(declval<initiate_async_resolve>(), token, q))]: no type named 'type' in 'asio::constraint<false>'
  177 |   auto await_transform(Op&& op,

如果我将

E
的模板参数
asio::awaitable<T, E>
executor_type
替换为多态
asio::any_io_executor
那么它编译得很好。

我的问题是,为了避免多态

asio::any_io_executor
的成本,我是否正确地假设函数
host_to_endpoint
应该返回
asio::awaitable<T, E>
以及具体
E = executor_type
的模板参数?如果是,我该如何修复我的代码,以便它可以使用具体的执行器进行编译?

c++ c++20 boost-asio asio
1个回答
0
投票

完成令牌与周围的 coro 上下文(promise 类型)一致。因此您可能想要:

asio::use_awaitable_t<executor_type> use_awaitable;
auto const endpoints = co_await resolver.async_resolve(std::move(host), "1234", use_awaitable);

(请注意,

resolver::query
已弃用)。

但是,出于效率的考虑,无论如何总是更喜欢

asio::deferred
,它将自动由你的 coro 上下文进行等待转换:

auto const endpoints = co_await resolver.async_resolve(std::move(host), "1234", asio::deferred);

事实上,在最新的 Asio 版本中,

deferred
已成为全局默认完成标记,这意味着所有 Asio 的启动函数都可以简单地省略完成标记:

auto endpoints = co_await resolver.async_resolve(std::move(host), "1234);

过简单的生活,过幸福的生活:)

© www.soinside.com 2019 - 2024. All rights reserved.