expected
std::expected 是 C++23 引入的类型,表示"要么包含一个期望值,要么包含一个错误"。它类似 Rust 的 Result<T, E>,是比异常和 optional 更好的函数返回错误方式。
头文件与基本特征
#include <expected>
| 特征 | 说明 |
|---|---|
| 角色 | 值或错误,二者必居其一 |
| 类比 | Rust Result<T, E> |
| 与 optional 区别 | optional<T> 只表示"T 或空",expected<T, E> 表示"T 或错误 E" |
| 访问值 | value() 或 *,有错误时 value() 抛异常 |
| 访问错误 | error() |
| 单子操作 | and_then(), or_else(), transform() 函数式链式调用 |
基本用法
#include <expected>
#include <iostream>
#include <string>
enum class Error { Invalid, Overflow };
std::expected<int, Error> divide(int a, int b) {
if (b == 0) return std::unexpected(Error::Invalid);
if (a == INT_MIN && b == -1) return std::unexpected(Error::Overflow);
return a / b;
}
int main() {
auto r1 = divide(10, 2);
auto r2 = divide(10, 0);
if (r1.has_value()) {
std::cout << "result = " << r1.value() << '\n'; // 5
}
if (!r2.has_value()) {
std::cout << "error!\n";
}
// 带默认值
int safe = r2.value_or(-1); // -1
return 0;
}
单子链式操作(Monadic)
C++23 为 expected 提供了单子操作,可以链式调用,避免层层 if 判断:
auto result = divide(10, 2)
.transform([](int x) { return x * 2; }) // 值 → 映射
.and_then([](int x) { return divide(x, 5); }) // 值 → 可能失败
.or_else([](Error e) { // 错误 → 恢复
return 0;
});
常用接口
| 接口 | 作用 |
|---|---|
has_value() | 是否包含期望值 |
value() | 获取值,有错误抛 std::bad_expected_access |
error() | 获取错误 |
value_or(default) | 有值则返回,否则返回默认值 |
operator* / operator-> | 访问值(不检查) |
transform(fn) | 对值做映射 |
and_then(fn) | 对值做可能失败的操作 |
or_else(fn) | 处理错误 |
std::unexpected(e) | 构造错误状态 |
使用注意
expected是基于栈的,没有动态分配。- 错误类型可以是任意类型(枚举、结构体、
std::error_code等)。 - 不要用
expected替代所有异常——只在"预期内的、可恢复的"错误场景使用。 *取值为未定义行为,用前先has_value()检查。
小结
std::expected<T, E> 是 C++23 中最期待的类型之一。它让"函数可能失败"成为类型签名的一部分,链式调用消除嵌套 if。配合 std::error_code 做错误类型,是 C++ 错误处理的现代化方向。