一聚教程网:一个值得你收藏的教程网站

最新下载

热门教程

C++基于std::expected的组合式异步异常处理流如何实现

时间:2026-07-12 09:23:53 编辑:袖梨 来源:一聚教程网

std::expected 仅适用于同步结果管道,不支持异步调度或等待;其 and_then/or_else 为立即求值的类型安全转换,异步组合需依赖 std::future 或协程配合自定义 awaiter。

std::expected 不能直接用于异步流,别硬套

它不是 std::futurestd::coroutine_handle 的替代品,也没有内置调度、等待或链式转发能力。强行用 std::expected<T, E> 包裹异步结果(比如把 std::future<std::expected<int, std::error_code>> 当“组合式流”用),只会让错误传播变隐晦、取消逻辑丢失、执行时机不可控。

真正能组合的只有 std::expected 的值转换逻辑

它的价值在同步上下文里的“结果管道”:拿到一个 std::expected<T, E> 后,用 and_then / or_else 做类型安全的链式转换,类似 Rust 的 ? 或 Haskell 的 >>=。但这些函数本身不触发异步操作,也不处理线程切换。

  • and_then 接收一个返回 std::expected<U, E> 的函数,成功时调用并返回新预期值
  • or_else 在失败时调用,参数是 E&,返回另一个 std::expected<T, F>
  • 所有操作都是立即求值的——没有延迟、没有 await、不涉及 executor

想组合异步操作?得靠 std::future + 手动适配 expected

典型做法是把异步任务封装成返回 std::future<std::expected<T, E>> 的函数,再用 std::async 或 executor 提交;组合则靠手动 then(C++20 没标准 then,需用 std::future::wait_for + 回调模拟,或依赖第三方如 boost::asio::awaitable)。

示例片段(简化版):

立即学习“C++免费学习笔记(深入)”;

auto load_config() -> std::future<std::expected<Config, std::error_code>> {    return std::async(std::launch::async, []() -> std::expected<Config, std::error_code> {        if (auto ec = read_file("config.json", ...)) return unexpected(ec);        return parse_config(...);    });}// 组合:必须显式 .get() 或 co_await(若用协程)auto run() -> std::future<std::expected<Result, std::error_code>> {    return std::async(std::launch::async, []() {        auto cfg = load_config().get(); // 阻塞获取        if (!cfg) return std::unexpected(cfg.error());        return process(cfg.value());    });}

协程是目前最接近“组合式异步异常流”的可行路径

C++20 协程 + std::expected 才能逼近你想要的效果:用 co_await 等待异步操作,用 co_return std::expected<...> 统一成功/失败出口,再靠 co_await 自动传播错误(前提是 awaiter 正确处理 std::expected 的 error 分支)。

关键点:

  • awaiter 的 await_resume() 必须检查 std::expected 是否有值,否则 co_await 会崩溃或静默忽略错误
  • 不能直接 co_await 一个 std::future<std::expected<...>> —— 它没定义对应 awaiter,得自己写或用 boost::asio::use_awaitable
  • 协程栈上无法自动传播 std::expected 错误到调用方,必须显式 co_return std::unexpected(...)

真正难的不是语法,是把 executor、取消信号、超时、错误分类这些都对齐到 std::expected 的 error 类型上——没人能绕开这层设计权衡。

热门栏目