28

In one of the most respected stackoverflow answer I found an example of std::expected template class usages: What are coroutines in C++20?

At the same time I cannot find any mentioning of this class on cppreference.com. Could you please explain what it is?

nachiketkulk
  • 1,141
  • 11
  • 22
Fedor
  • 17,146
  • 13
  • 40
  • 131
  • 6
    It's a fantasy - may not happen - but .. may still – Ted Lyngmo Jul 13 '21 at 19:52
  • 6
    you can't find it on cppreference because it is not a part of the standard – Sergey Kolesnik Jul 13 '21 at 19:52
  • Some info about it: https://github.com/eugnsp/library/blob/master/cpp/std_library.md#stdexpected – Evg Jul 13 '21 at 19:59
  • 3
    It's still only a proposal https://wg21.link/p0323 - respected answer or not, everybody injects their opinions into answers, whether explicitly or implicitly. In this case, it was the opinion that `std::expected` should (and would) be standardized soon. – StoryTeller - Unslander Monica Jul 13 '21 at 19:59
  • 1
    Like others had mentioned, `expected` was only proposed. But there are some user written ones you can lookup: https://github.com/TartanLlama/expected – Ranoiaetep Jul 13 '21 at 23:28
  • 2
    https://en.cppreference.com/w/cpp/error/unexpected –  Jul 20 '21 at 09:47

1 Answers1

55

Actually, the best way to learn about std::expected is a funny talk by the (in)famous Andrei Alexandrescu: "Expect the Expected!"

What std::expected is, and when it's used

Here are three complementing explanations of what an std::expected<T, E> is:

  • It is the return type of a function which is supposed to return a T value - but which may encounter some error, in which case it will return a descriptor of that error, of type E.

    An example:

    std::expected<ParsedData, ParsingError> parse_input(Input input);
    
  • It's an error-handling mechanism, being an alternative to throwing exceptions (in which case you always return the value you were supposed to), and to returning status/error codes (in which case you never return the value you want to, and have to use an out-parameter).

    Here are the two alternative error-handling mechanisms applied to the function from the previous example:

    ParsedData    parse_input_2(Input input) noexcept(false);
    ParsingError  parse_input_3(ParsedData& result, Input input);
    
  • It's a discriminated union of types T and E with some convenience methods.

"How is it better than just an std::variant<T,E>?"

It behaves somewhat like std::optional<T>, giving focus to the expected, rather than the unexpected, case:

  • result.has_value() - true if we got a value rather than an error.
  • if (result) - checks for the same thing
  • *result - gives us the T value if it exists, undefined behavior otherwise (same as std::optional, although many don't like this).
  • result.value(), gives us the T value if it exists, or throws otherwise.

Actually, that last mode of access behaves differently than std::optional if we got an error: What it throws is a bad_expected_access<E>, with the returned error. This behavior can be thought of as a way to switch from expected-based to exception-based error-handling.

"Hey, I looked for it in the standard and it isn't there!"

std::expected will be part of the upcoming C++23 standard. The proposal (P0323) has recently been accepted.

This being said - it is quite usable already, since it requires no new language facilities:

  • I can recommend one Sy Brand (tartanllama)'s implementation, which can be used with C++11 or later. It also has some neat functional-style extensions (which may not be standardized).
  • @Malachi recommends estd::expected, part of a standard library implementation intended for embedded environments.
einpoklum
  • 118,144
  • 57
  • 340
  • 684
  • Shameless (but relevant) plug: `estd::expected` c++11 implementation also available [here](https://github.com/malachi-iot/estdlib) – Malachi May 24 '23 at 18:55
  • 1
    @Malachi: Added it as an option, feel free to edit to rephrase if you like. – einpoklum May 24 '23 at 19:36