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

如何在C++20协程+Boost ASIO中获取错误码而非异常处理?

问题描述

我有一个boost::asio::steady_timer timer,想要通过boost::asio::steady_timer::async_wait执行异步等待。传统回调方式中,错误会作为参数传入完成处理的lambda:

timer.async_wait([](const auto &boost_error) {
    // 检查boost_error
});

使用协程时,配合boost::asio::use_awaitable可以通过co_await调用:

co_await timer.async_wait(boost::asio::use_awaitable);

但错误处理方式发生了变化:要捕获定时器被cancel这类错误,必须将co_await包裹在try/catch块中。我想知道,Boost能否支持在await异步操作时直接返回错误码?比如这样:

std::variant<void, error_code> result = co_await timer.async_wait(boost::asio::use_awaitable);
解决方案

Boost Asio确实支持无需异常捕获、直接获取错误码的协程用法,主要有两种常用实现方式:

1. 用as_tuple()包装awaitable token

Boost Asio的use_awaitable_t提供了as_tuple()方法,让co_await返回一个包含错误码(若操作有结果则同时包含结果)的tuple。对于async_wait这类无返回结果的操作,tuple中仅包含std::error_code:

auto [ec] = co_await timer.async_wait(boost::asio::use_awaitable.as_tuple());
if (ec) {
    // 处理错误(比如定时器被cancel的情况)
}

这种方式无需try/catch,错误处理逻辑和传统回调模式更贴近。

2. 自定义返回错误码的awaitable token

如果你更偏好返回std::variant或单独的std::error_code,可以自定义一个简单的awaitable token。以无结果的异步操作为例,我们可以实现一个token让co_await直接返回std::error_code:

struct use_error_code {};

template <typename CompletionToken>
auto async_wait(boost::asio::steady_timer& timer, CompletionToken&& token) {
    return boost::asio::async_compose<CompletionToken, void(std::error_code)>(
        [&timer](auto&& self) {
            timer.async_wait(std::move(self));
        },
        token,
        timer.get_executor()
    );
}

// 使用示例
std::error_code ec = co_await timer.async_wait(use_error_code{});
if (ec) {
    // 处理错误
}

这种方式灵活性更高,你可以根据需求轻松修改返回类型,比如改成返回std::variant<void, std::error_code>。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.13 04:56:18