C++ 中的 std::expected 是什么?

Fed*_*dor 34 c++ error-handling c++-faq c++23 std-expected

std::expected在最受尊敬的 stackoverflow 答案之一中,我找到了模板类用法 的示例: What are coroutines in C++20?

同时我在 cppreference.com 上找不到任何关于此类的提及。你能解释一下它是什么吗?

ein*_*ica 62

事实上,最好的了解方式std::expected是著名的安德烈·亚历山德雷斯库(Andrei Alexandrescu)的有趣演讲:“期待所期待的!”

什么std::expected是以及何时使用

以下是对 anstd::expected<T, E>是什么的三个补充解释:

  • 它是函数的返回类型,该函数应该返回一个T值 - 但可能会遇到一些错误,在这种情况下它将返回该错误的描述符,类型为E

    一个例子:

    std::expected<ParsedData, ParsingError> parse_input(Input input);
    
    Run Code Online (Sandbox Code Playgroud)
  • 它是一种错误处理机制,是抛出异常(在这种情况下你总是返回你应该返回的值)和返回状态/错误代码(在这种情况下你永远不会返回你想要的值,并且有使用外参数)。

    以下是应用于上一个示例中的函数的两种替代错误处理机制:

    ParsedData    parse_input_2(Input input) noexcept(false);
    ParsingError  parse_input_3(ParsedData& result, Input input);
    
    Run Code Online (Sandbox Code Playgroud)
  • T它是类型和一些便捷方法的可区分联合E

“这比仅仅一个更好吗std::variant<T,E>?”

它的行为有点像std::optional<T>,将重点放在预期的而不是意外的情况上:

  • result.has_value()- 如果我们得到一个值而不是一个错误,则为 true。
  • if (result)- 检查相同的事情
  • *result- 为我们提供T值(如果存在),否则为未定义行为(与 相同std::optional,尽管许多人不喜欢这样)。
  • result.value()T,如果存在,则为我们提供值,否则抛出异常。

std::optional实际上,最后一种访问模式的行为与我们收到错误时不同:它抛出的是 a bad_expected_access<E>,并返回错误。这种行为可以被认为是从基于预期的错误处理切换到基于异常的错误处理的一种方法。

“哎呀,我在标准里找了,没有啊!”

std::expected将成为即将推出的 C++23 标准的一部分。该提案(P0323)最近已被接受。

话虽这么说,它已经非常有用了,因为它不需要新的语言设施:

  • 我可以推荐一个 Sy Brand (tartanllama) 的实现,它可以与 C++11 或更高版本一起使用。它还有一些简洁的函数式扩展(可能不是标准化的)。
  • @Malachi 推荐estd::expected,它是用于嵌入式环境的标准库实现的一部分。