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

30

我在 StackOverflow 上找到了一篇最受尊重的答案,其中提到了 std::expected 模板类的使用示例:C++20 中的协程是什么?

与此同时,我在 cppreference.com 上没有找到任何有关这个类的信息。能否请您解释一下它是什么?


6
这是一个幻想,可能不会发生,但是...仍有可能。 - Ted Lyngmo
6
你无法在cppreference上找到它,因为它不是标准的一部分。 - Sergey Kolesnik
一些关于它的信息:https://github.com/eugnsp/library/blob/master/cpp/std_library.md#stdexpected - Evg
3
这仍然只是一个提案 https://wg21.link/p0323 - 不管是否被认可,每个人都会在回答中注入自己的观点,无论是明确地还是隐含地。在这种情况下,意见是 std::expected 应该(并且将会)很快被标准化。 - StoryTeller - Unslander Monica
1
正如其他人所提到的,expected只是一种提议。但是你可以查找一些用户编写的方案:https://github.com/TartanLlama/expected。 - Ranoiaetep
2
https://en.cppreference.com/w/cpp/error/unexpected - user5545734
1个回答

58

实际上,了解 std::expected 最好的方法是通过(臭名昭著的)Andrei Alexandrescu 的有趣演讲:"Expect the Expected!"

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

以下是三种互补的解释,说明了 std::expected<T, E> 是什么:

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

    例如:

    std::expected<ParsedData, ParsingError> parse_input(Input input);
    
  • 它是一种错误处理机制,是抛出异常的替代方案(在这种情况下,您总是返回您应该返回的值),以及返回状态/错误代码的替代方案(在这种情况下,您永远不会返回您想要的值,并且必须使用输出参数)。

    以下是应用于前面示例函数的两种替代错误处理机制:

    ParsedData    parse_input_2(Input input) noexcept(false);
    ParsingError  parse_input_3(ParsedData& result, Input input);
    
  • 它是类型TE的区分联合体,具有一些便利方法。

"它比仅使用std::variant<T,E>更好吗?"

它的行为有些类似于std::optional<T>,着重于预期情况而不是意外情况:

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

实际上,如果我们得到了一个错误,最后一种访问模式的行为会与std::optional不同:它会抛出带有返回的错误的bad_expected_access<E>。可以将这种行为视为从基于预期的错误处理切换到基于异常的错误处理的一种方式。

"嗨,我在标准中找过它了,但没找到!"

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

话虽如此 - 它已经相当可用了,因为它不需要新的语言设施:

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

不要介意(但相关):estd::expected c++11 实现也可以在这里找到。 - Malachi
1
@Malachi:已将其添加为选项,如有需要,请随意编辑重新表述。 - einpoklum

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接