std::expected

来自cppreference.com
< cpp‎ | utility
 
 
工具库
通用工具
日期和时间
函数对象
格式化库 (C++20)
(C++11)
关系运算符 (C++20 中弃用)
整数比较函数
(C++20)(C++20)(C++20)
(C++20)
swap 与类型运算
(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;
(C++23 起)

类模板 std::expected 提供存储二个值之一的方式。 std::expected 的对象再任何给定时刻要么保有一个期待的 T 类型值,要么保有一个不期待的 E 类型值。 std::expected 决不会无值。

存储的值直接分配于 expected 对象所占用的存储中。不发生动态分配。

若程序以引用类型、函数类型,或 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 template< class U >

using rebind = expected<U, error_type>;

成员函数

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

非成员函数

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

辅助类

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

注解

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

功能特性测试 标准
__cpp_lib_expected 202202L (C++23)

示例

#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 << "value: " << *num << '\n';
            // If num did not have a value, dereferencing num
            // would cause an undefined behavior, and
            // num.value() would throw std::bad_expected_access.
            // num.value_or(123) uses specified default value 123.
        }
        else if (num.error() == parse_error::invalid_input)
        {
            std::cout << "error: invalid input\n";
        }
        else if (num.error() == parse_error::overflow)
        {
            std::cout << "error: overflow\n";
        }
        else
        {
            std::cout << "unexpected!\n"; // or invoke std::unreachable();
        }
    };
 
    for (auto src: { "42", "42abc", "meow", "inf" })
        process(src);
}

输出:

str: "42", value: 42
str: "42abc", value: 42
str: "meow", error: invalid input
str: "inf", error: overflow

引用

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

参阅

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