thecodex.expert · The Codex Family of Knowledge
C++

Standard Library

std::expected, added in C++23, finally gives C++ a genuinely typed way to return either a value or an error — without throwing an exception or resorting to an error-code out-parameter.

C++20 / C++23 std::expected since C++23 Last verified:
Canonical Definition

std::optional<T> (C++17) represents a value that might not be present, replacing the older pattern of a special sentinel value or a raw pointer that might be null. std::variant<Types...> (C++17) is a type-safe union — unlike C's raw union, it tracks which type is actually active and throws if accessed incorrectly, rather than silently reinterpreting bytes. std::expected<T, E>, added in C++23, lets a function return either a successful value or a specific error type explicitly in its signature, without needing an exception or an error-code out-parameter — directly comparable to Rust's Result or TypeScript's discriminated unions for error handling.

std::optional: explicit absence, since C++17

has_value() and the * operator (or value()) are the standard way to check and unwrap — the type signature itself documents that findUser might legitimately have nothing to return.

C++optional_example.cpp
std::optional<std::string> findUser(int id) {
    if (id == 1) return "Alice";
    return std::nullopt;   // explicitly "no value"
}

auto result = findUser(2);
if (result.has_value()) {
    std::cout << *result << "\n";
} else {
    std::cout << "not found\n";
}

std::variant: a genuinely type-safe union

Unlike C's raw union, accessing a variant as the WRONG currently-active type throws std::bad_variant_access rather than silently reinterpreting bytes — std::visit is the idiomatic way to handle every possible alternative safely.

C++variant_example.cpp
std::variant<int, std::string> value = 42;

std::visit([](auto&& v) {
    std::cout << v << "\n";   // works for whichever alternative is currently active
}, value);

value = "hello";   // now holds a string instead

std::expected: explicit error handling, since C++23

The function's own signature documents both the success type AND the error type directly — callers must explicitly check has_value() before accessing the result, making error handling visible rather than an easily-ignored exception that might slip past an untested code path.

C++expected_example.cpp
std::expected<int, std::string> parseNumber(const std::string& s) {
    try {
        return std::stoi(s);
    } catch (...) {
        return std::unexpected("not a valid number");
    }
}

auto result = parseNumber("abc");
if (result.has_value()) {
    std::cout << *result << "\n";
} else {
    std::cout << "Error: " << result.error() << "\n";
}

Sources

1
ISO/IEC 14882 (C++ Standard), "General utilities library," cppreference.com/w/cpp/utility, covering std::optional, std::variant, and std::expected.