老铁爱金衫 2025-08-06 05:50 采纳率: 98.2%
浏览 2
已采纳

如何使用C++23的`std::expected`处理错误?

**如何在C++23中使用`std::expected`进行错误处理?** C++23引入的`std::expected`为函数返回值提供了一种类型安全的错误处理机制,它既可以表示成功时的值(`T`),也可以表示错误时的异常信息(如`E`)。与`std::optional`不同,`std::expected`明确表达了操作可能失败的语义。常见问题包括:如何正确构造和返回`std::expected`对象?如何提取成功值或错误信息?如何结合`std::error_code`进行标准化错误处理?此外,开发者常困惑于何时使用`std::expected`而非异常机制,以及如何在实际项目中替代传统的错误码或`std::pair`模式。掌握这些问题有助于写出更清晰、可维护的错误处理逻辑。
  • 写回答

1条回答 默认 最新

  • Qianwei Cheng 2025-08-06 05:50
    关注

    如何在 C++23 中使用 std::expected 进行错误处理?

    C++23 引入了 std::expected,为函数返回值提供了一种类型安全的错误处理机制。它既可以表示成功时的值(T),也可以表示错误时的信息(如 E)。与 std::optional 不同,std::expected 明确表达了操作可能失败的语义。

    1. 基本概念与类型定义

    std::expected<T, E> 是一个模板类,表示一个可能成功(包含值 T)或失败(包含错误 E)的结果。常见的错误类型包括 std::error_code、枚举类型或自定义错误结构。

    
    #include <expected>
    #include <iostream>
    
    std::expected<int, std::string> divide(int a, int b) {
        if (b == 0) {
            return std::unexpected("Division by zero");
        }
        return a / b;
    }
    

    2. 构造与返回 std::expected 对象

    构造 std::expected 时,可以使用直接构造或通过 std::unexpected 构造错误状态。

    • 成功返回:return T;return std::expected<T, E>(T{});
    • 错误返回:return std::unexpected(E{});
    
    std::expected<double, std::error_code> safe_sqrt(double x) {
        if (x < 0) {
            return std::unexpected(std::make_error_code(std::errc::invalid_argument));
        }
        return std::sqrt(x);
    }
    

    3. 提取成功值或错误信息

    可以通过 value()error() 方法分别获取成功值或错误信息。使用前建议通过 has_value() 检查状态。

    
    auto result = divide(10, 2);
    if (result.has_value()) {
        std::cout << "Result: " << result.value() << '\n';
    } else {
        std::cout << "Error: " << result.error() << '\n';
    }
    

    4. 结合 std::error_code 进行标准化错误处理

    为了与系统错误码兼容,推荐使用 std::error_code 作为错误类型。它支持跨平台的错误码定义,并能与标准库的错误机制无缝集成。

    函数说明
    std::make_error_code()构造标准错误码
    std::errc::invalid_argument标准错误码枚举值

    5. 何时使用 std::expected 而非异常机制

    使用 std::expected 的优势在于:

    • 类型安全:编译期可检测错误类型
    • 无异常依赖:适合禁用异常的项目
    • 性能更优:避免栈展开的开销

    适用于错误是常见且预期的情况(如文件不存在、网络超时),而异常更适合不可恢复的错误(如内存分配失败)。

    6. 替代传统错误码和 std::pair<bool, T> 模式

    std::expected 可替代 bool + 值的模式,提供更清晰的语义和更强的类型安全性。

    
    // 旧模式
    std::pair<bool, int> parse_int(const std::string& s);
    
    // 新模式
    std::expected<int, std::string> parse_int(const std::string& s);
    

    7. 示例:完整的错误处理流程图

    graph TD A[调用函数] --> B{是否成功?} B -->|是| C[获取值] B -->|否| D[获取错误] C --> E[继续处理] D --> F[记录日志或重试]
    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论

报告相同问题?

问题事件

  • 已采纳回答 10月23日
  • 创建了问题 8月6日