You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

C++20协程搭配Boost ASIO具体执行器遇编译错误,求解决方案

使用Boost ASIO+C++20协程时,用具体执行器替代多态执行器的编译问题

我正在用Boost ASIO结合C++20协程实现简易UDP客户端,为了低成本提升性能,尝试用具体执行器类型asio::io_context::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,

若将asio::awaitable<T, E>的模板参数E替换为多态的asio::any_io_executor,代码可正常编译。现询问:为避免多态执行器的开销,将host_to_endpoint返回asio::awaitable<T, executor_type>的做法是否正确?若正确,如何修改代码使其编译通过?


解答

1. 做法的正确性

用具体执行器asio::io_context::executor_type替代asio::any_io_executor的思路完全正确。多态执行器会引入类型擦除带来的额外开销(比如虚函数调用、潜在的动态内存分配),而具体执行器是静态类型,编译器能在编译期完成全面优化,确实可以低成本提升性能,尤其适合对延迟、吞吐量敏感的场景。

2. 编译错误原因

编译失败的核心是:resolver.async_resolve搭配默认asio::use_awaitable返回的是asio::awaitable<..., asio::any_io_executor>,但当前协程的返回类型是asio::awaitable<..., executor_type>,两者的执行器类型不匹配,导致协程的await_transform无法找到适配的重载处理这个awaitable对象。

3. 修复方案

要让异步操作返回的awaitable使用具体执行器,需要绑定对应执行器到awaitable token上,有两种可行方式:

方式一:绑定当前协程的执行器

通过asio::this_coro::executor获取当前协程的具体执行器,再用asio::bind_executor绑定到use_awaitable:

asio::awaitable<asio::ip::udp::endpoint, executor_type> host_to_endpoint(std::string host) {
    asio::ip::udp::resolver::query query{std::move(host), "1234"};
    // 获取当前协程的执行器并绑定到awaitable token
    auto token = asio::bind_executor(co_await asio::this_coro::executor, asio::use_awaitable);
    const auto endpoints = co_await resolver.async_resolve(query, token);

    co_return *endpoints.begin();
}

方式二:显式指定执行器类型的use_awaitable

直接创建带具体执行器类型参数的use_awaitable_t实例:

asio::awaitable<asio::ip::udp::endpoint, executor_type> host_to_endpoint(std::string host) {
    asio::ip::udp::resolver::query query{std::move(host), "1234"};
    // 显式指定执行器类型的use_awaitable
    const auto endpoints = co_await resolver.async_resolve(query, asio::use_awaitable_t<executor_type>{});

    co_return *endpoints.begin();
}

两种方式都能让async_resolve返回的awaitable使用具体的executor_type,与当前协程的返回类型匹配,从而通过编译,同时保留具体执行器的性能优势。

内容的提问来源于stack exchange,提问作者Matus Novak

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.17 01:43:16