std::expected

来自cppreference.com
< cpp‎ | utility
 
 
工具库
语言支持
类型支持(基本类型、RTTI)
库功能特性测试宏 (C++20)
动态内存管理
程序工具
协程支持 (C++20)
变参数函数
调试支持
(C++26)
三路比较
(C++20)
(C++20)(C++20)(C++20)
(C++20)(C++20)(C++20)
通用工具
日期和时间
函数对象
格式化库 (C++20)
(C++11)
关系运算符 (C++20 中弃用)
整数比较函数
(C++20)(C++20)(C++20)   
(C++20)
交换类型运算
(C++14)
(C++11)
(C++11)
(C++11)
(C++17)
常用词汇类型
(C++11)
(C++17)
(C++17)
(C++17)
(C++11)
(C++17)
expected
(C++23)
初等字符串转换
(C++17)
(C++17)

 
 
在标头 <expected> 定义
template< class T, class E >
class expected;
(1) (C++23 起)
template< class T, class E >

    requires std::is_void_v<T>

class expected<T, E>;
(2) (C++23 起)

类模板 std::expected 提供表示两个值之一的方式:它要么表示一个 T 类型的预期 值,要么表示一个 E 类型的非预期 值。std::expected 决不会无值。

1) 主模板。在自身的存储中包含预期值或非预期值。不会进行动态分配。
2) void 部分特化。表示一个 void 类型的预期值或在自身的存储中包含非预期值。不会进行动态分配。

如果程序以引用类型、函数类型,或 std::unexpected 的特化实例化 expected,那么程序非良构。另外,T 必须不是 std::in_place_tstd::unexpect_t

模板形参

T - 预期值的类型。类型必须是(可有 cv 限定的)void,或者符合可析构 (Destructible) 要求(尤其是不允许数组或引用类型)。
E - 非预期值的类型。类型必须符合可析构 (Destructible) 要求,且必须对于 std::unexpected 为合法的模板实参(尤其是不允许数组、非对象类型及 cv 限定的类型)。

成员类型

成员类型 定义
value_type T
error_type E
unexpected_type std::unexpected<E>

成员别名模板

类型 定义
rebind<U> std::expected<U, error_type>

数据成员

成员 定义
bool has_val expected 对象当前是否表示预期值
(仅用于阐述的成员对象*)
T val (仅限主模板) 预期值
(仅用于阐述的变体成员对象*)
E unex 非预期值
(仅用于阐述的变体成员对象*)

成员函数

构造 expected 对象
(公开成员函数)
销毁 expected 对象以及其所含的值
(公开成员函数)
(C++23)
赋值内容
(公开成员函数)
观察器
访问预期值
(公开成员函数)
检查对象是否含有预期值
(公开成员函数)
返回预期值
(公开成员函数)
返回非预期值
(公开成员函数)
如果有预期值则返回它,否则返回另一个值
(公开成员函数)
如果有非预期值则返回它,否则返回另一个值
(公开成员函数)
单子操作
若存在预期值则返回给定的函数在其上的结果,否则返回 expected 本身
(公开成员函数)
若存在预期值则返回含有变换后的预期值的 expected,否则返回 expected 本身
(公开成员函数)
expected 含有预期值则返回其自身,否则返回给定的函数在非预期值上的结果
(公开成员函数)
若含有预期值则返回 expected 本身,否则返回含有变换后非预期值的 expected
(公开成员函数)
修改器
原位构造预期值
(公开成员函数)
交换内容
(公开成员函数)

非成员函数

比较 expected 对象
(函数模板)
特化 std::swap 算法
(函数)

辅助类

表示一个非预期值
(类模板)
指示对含有非预期值的 expected 的有检查访问的异常
(类模板)
expected 中非预期值的原位构造标签
(类) (常量)

注解

拥有相同功能的类型在 Rust 与 Haskell 中分别被称为 ResultEither

功能特性测试 标准 功能特性
__cpp_lib_expected 202202L (C++23) 类模板 std::expected 和关联的辅助类
202211L (C++23) std::expected 的单体式函数

示例

#include <cmath>
#include <expected>
#include <iomanip>
#include <iostream>
#include <string_view>
 
enum class parse_error
{
    invalid_input,
    overflow
};
 
auto parse_number(std::string_view& str) -> std::expected<double, parse_error>
{
    const char* begin = str.data();
    char* end;
    double retval = std::strtod(begin, &end);
 
    if (begin == end)
        return std::unexpected(parse_error::invalid_input);
    else if (std::isinf(retval))
        return std::unexpected(parse_error::overflow);
 
    str.remove_prefix(end - begin);
    return retval;
}
 
int main()
{
    auto process = [](std::string_view str)
    {
        std::cout << "str: " << std::quoted(str) << ", ";
        if (const auto num = parse_number(str); num.has_value())
            std::cout << "值: " << *num << '\n';
            // 如果 num 没有值,那么解引用 num 会造成未定义行为,而
            // num.value() 会抛出 std::bad_expected_access。
            // num.value_or(123) 则使用指定的默认值 123。
        else if (num.error() == parse_error::invalid_input)
            std::cout << "错误:无效输入\n";
        else if (num.error() == parse_error::overflow)
            std::cout << "错误:溢出\n";
        else
            std::cout << "非预期!\n"; // 或调用 std::unreachable();
    };
 
    for (auto src : {"42", "42abc", "meow", "inf"})
        process(src);
}

输出:

str: "42", 值: 42
str: "42abc", 值: 42
str: "meow", 错误:无效输入
str: "inf", 错误:溢出

引用

  • C++23 标准(ISO/IEC 14882:2024):
  • 22.8 Expected objects [expected]

参阅

(C++17)
类型安全的可辨识联合体
(类模板)
(C++17)
可能或可能不保有一个对象的包装器
(类模板)