CodeBlanks Logo Icon CodeBlanks

std::expected

Learn error handling with std::expected.

What is std::expected?

std::expected<T, E> is a type introduced with C++23: it holds either a T value or an E error. Instead of throwing an exception, it returns the error as a value.

Example: std::expected<int, std::string> divide(int a, int b). On success return a / b;, on error return std::unexpected(std::string("division by zero"));. The caller checks the state with r.has_value(), gets the value with r.value() and the error with r.error(). This provides error handling without the cost of exceptions; it is especially useful to separate real exceptions from expected failures.

value() and error()

From a std::expected object you get the value with .value() and the error with .error(). You must check .has_value() first.

Example: auto r = divide(10, 2); if (r.has_value()) std::cout << r.value(); else std::cout << r.error();. If you call .value() when there is no value, an exception is thrown. So you must check has_value() first. Errors are produced with std::unexpected: return std::unexpected(std::string("error"));. This is an explicit and type-safe error handling.

Practice Write divide with std::expected

Write std::expected<int, std::string> divide(int a, int b): if b == 0 return std::unexpected(std::string("division by zero"));, otherwise return a / b;. In main call divide(10, 2); if has_value() is true print value(), otherwise print error() with std::cout.

Starter code

main.cpp
#include <iostream>
#include <expected>
#include <string>

// Write the divide function with std::expected

int main() {
    // Call divide and print the result
    return 0;
}

Sample solution

main.cpp
#include <iostream>
#include <expected>
#include <string>

std::expected<int, std::string> divide(int a, int b) {
    if (b == 0) return std::unexpected(std::string("division by zero"));
    return a / b;
}

int main() {
    auto r = divide(10, 2);
    if (r.has_value()) std::cout << r.value();
    else std::cout << r.error();
    return 0;
}

Expected output

5

Questions and answers

Review the lesson questions together with their answers. To test yourself, solve the lesson interactively.

1 When should std::expected be used?

  • Always instead of exceptions
  • For multithreading
  • Only for memory errors
  • To return expected error conditions as values Correct answer

Explanation: std::expected returns expected errors as values instead of exceptions.

2 Match each member to its role

Term Meaning
has_value Has a value?
value() Get the value
error() Get the error
std::unexpected Produces an error

3 the .value() call

Question
if (r.has_value()) std::cout << r.____();
Answer
if (r.has_value()) std::cout << r.value();

Explanation: r.value() returns the successful result.

All lessons in Advanced