Z
ZHANK
编程在线教程C++ 教程std::expected 错误处理
C++20/23 与惯用法

std::expected 错误处理

expected 替代异常、and_then/or_else 链式、monadic 操作

std::expected 错误处理

std::expected<T, E>(C++23)是 Result 类型的标准实现——要么有值,要么有错误。链式 and_then/or_else 替代 try/catch。

学完本章你将: 掌握 expected 替代异常、and_then/or_else 链式。


基本用法

cpp
#include <expected>
#include <string>

std::expected<int, std::string> divide(int a, int b) {
    if (b == 0) return std::unexpected("除数不能为零");
    return a / b;
}

int main() {
    auto result = divide(10, 2);

    // 检查
    if (result.has_value())
        std::cout << result.value() << "\n";  // 5
    else
        std::cout << "错误: " << result.error() << "\n";

    // value_or
    std::cout << result.value_or(-1) << "\n";

    // 解引用
    std::cout << *result << "\n";
}

Monadic 链式操作

cpp
// and_then —— 成功时继续
auto process = divide(10, 2)
    .and_then([](int n) -> std::expected<int, std::string> {
        if (n > 100) return std::unexpected("结果过大");
        return n * 2;
    })
    .and_then([](int n) { return n + 1; });

// or_else —— 失败时处理
auto recovered = divide(10, 0)
    .or_else([](const std::string& err) {
        return 42;  // 返回默认值
    });

// transform —— 转换值(不改变错误)
auto squared = divide(10, 2)
    .transform([](int n) { return n * n; });

为什么用 expected

cpp
// ❌ 异常——性能差、控制流不清晰
// ✅ 返回错误码——容易忽略
// ✅ std::expected——必须处理(编译器可警告)

// 适用场景:
// - 可预期的失败(解析、验证、IO)
// - 性能敏感的路径
// - 函数式风格的流水线处理