为何boost::beast::http::async_write+as_tuple(deferred)无法转为目标awaitable类型?
此前可正常编译的代码,现在使用Clang编译时出现错误:使用完成令牌boost::asio::as_tuple(boost::asio::deferred)的boost::beast::http::async_write返回值,无法转换为boost::asio::awaitable<std::tuple<boost::system::error_code, std::size_t>>。已知当前libclang头文件搜索路径异常,需添加-I/usr/lib/clang/19/include编译选项,疑惑是代码问题还是Clang安装问题。
错误信息
error: no viable conversion from returned value of type 'decltype(enable_if_t<enable_if_t<detail::are_completion_signatures<void (error_code, unsigned long)>::value, detail::async_result_has_initiate_memfn<as_tuple_t<deferred_t>, void (error_code, unsigned long)>>::value, async_result<decay_t<as_tuple_t<deferred_t>>, void (error_code, unsigned long)>>::initiate(static_cast<boost::beast::http::detail::run_write_msg_op<boost::asio::basic_stream_socket<boost::asio::ip::tcp>> &&>(initiation), static_cast<boost::asio::as_tuple_t<boost::asio::deferred_t> &&>(token), static_cast<const boost::beast::http::message<false, boost::beast::http::basic_string_body<char>> *&&>(args), static_cast<std::integral_constant<bool, true> &&>(args)))' (aka 'deferred_async_operation<void (std::tuple<boost::system::error_code, unsigned long>), boost::asio::async_result<boost::asio::as_tuple_t<boost::asio::deferred_t>, void (boost::system::error_code, unsigned long)>::init_wrapper<boost::beast::http::detail::run_write_msg_op<boost::asio::basic_stream_socket<boost::asio::ip::tcp, boost::asio::any_io_executor>>>, const boost::beast::http::message<false, boost::beast::http::basic_string_body<char, std::char_traits<char>, std::allocator<char>>, boost::beast::http::basic_fields<std::allocator<char>>> *, std::integral_constant<bool, true>>') to function return type 'boost::asio::awaitable<std::tuple<boost::system::error_code, std::size_t>>' (aka 'awaitable<tuple<boost::system::error_code, unsigned long>>') 179 |return boost::beast::http::async_write(stream, typed_message, boost::asio::as_tuple(boost::asio::deferred)); | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
涉及代码
template<typename stream_t> boost::asio::awaitable<void> response_worker(boost::asio::experimental::channel<void(boost::system::error_code, http_response_t)> &channel, stream_t &stream) { while (true) { boost::system::error_code ec; std::variant< boost::beast::http::response<boost::beast::http::string_body>, boost::beast::http::response<boost::beast::http::empty_body>, boost::beast::http::response<boost::beast::http::dynamic_body>, boost::beast::http::response<boost::beast::http::file_body>, boost::beast::http::response<boost::beast::http::buffer_body>> message = co_await channel.async_receive(boost::asio::redirect_error(boost::asio::deferred, ec)); if (ec == boost::asio::error::eof) { channel.close(); co_return; } const auto [ec2, transferred] = co_await std::visit( [&stream](auto &typed_message) -> boost::asio::awaitable<std::tuple<boost::system::error_code, std::size_t>> { return boost::beast::http::async_write(stream, typed_message, boost::asio::as_tuple(boost::asio::deferred)); }, message); //error handling } }
分析与解决
代码问题核心
lambda显式声明的返回类型boost::asio::awaitable<std::tuple<boost::system::error_code, std::size_t>>,与boost::beast::http::async_write实际返回的deferred_async_operation类型不匹配。boost::asio::as_tuple(boost::asio::deferred)返回的是延迟操作对象,它是可被co_await的对象,但并非直接属于awaitable类型,因此无法直接转换。
修复方案
去掉lambda的显式返回类型声明,改用auto让编译器自动推导正确的可等待类型:
const auto [ec2, transferred] = co_await std::visit( [&stream](auto &typed_message) { return boost::beast::http::async_write(stream, typed_message, boost::asio::as_tuple(boost::asio::deferred)); }, message);
或者使用decltype(auto)显式保留返回值的原始类型:
const auto [ec2, transferred] = co_await std::visit( [&stream](auto &typed_message) -> decltype(auto) { return boost::beast::http::async_write(stream, typed_message, boost::asio::as_tuple(boost::asio::deferred)); }, message);
关于Clang安装问题
当前错误本质是类型不匹配,更可能是Boost版本更新后,deferred令牌的返回类型与awaitable的转换规则发生变化导致的代码兼容性问题,而非头文件路径异常。若修改代码后编译成功,即可确认是代码写法问题;若仍报错,再排查Clang版本与Boost版本的兼容性,或头文件路径是否正确覆盖了所需的标准库/Boost头文件。
内容的提问来源于stack exchange,提问作者climb4

