正常
std::expected (C++23)
In a Nutshell
Holds either the expected normal value T or an unexpected error E — a type-safe, zero-overhead error-propagation mechanism that replaces exceptions and the std::pair<T, Error> pattern.
Header
#include <expected>
Core API Cheat Sheet
| Operation | Signature | Description |
|---|---|---|
| Construct (success value) | expected(T value) | Wraps a normal value |
| Construct (error) | expected(unexpect_t, E err) | Wraps an error (std::unexpected{err}) |
| Check for success | bool has_value() const noexcept | Whether a normal value is held |
| Implicit bool conversion | explicit operator bool() const noexcept | Same as has_value |
| Get the value | T& value() | Returns a reference to the normal value (throws on failure) |
| Get the error | const E& error() const | Returns a reference to the error |
| Dereference | T& operator*() | Accesses the normal value (unchecked; undefined behavior if it holds an error) |
| Chained transform | auto transform(F&& f) | If a value is held, applies f to it and wraps the result |
| Chained error handling | auto and_then(F&& f) | If a value is held, calls f and returns its expected result |
| Error branch | auto or_else(F&& f) | If an error is held, calls f to handle it |
| Error transform | auto transform_error(F&& f) | If an error is held, applies f to the error |
| Create a success value | std::expected<T, E>(value) | Factory: directly constructs a success |
| Create an error value | std::unexpected{err} | Factory: constructs an unexpected for implicit conversion to expected |
Minimal Example
Expand codeCollapse21 lines
C++
// Standard: C++23
#include <expected>
#include <iostream>
#include <string>
std::expected<int, std::string> divide(int a, int b) {
if (b == 0) return std::unexpected{"division by zero"};
return a / b;
}
int main() {
auto r1 = divide(10, 3);
if (r1) std::cout << *r1 << "\n"; // 3
auto r2 = divide(10, 0);
if (!r2) std::cout << r2.error() << "\n"; // division by zero
// Chained calls
auto r3 = divide(20, 4).transform([](int v) { return v * 2; });
std::cout << *r3 << "\n"; // 10
}Embedded Applicability: High
- A zero-overhead abstraction: its size is
sizeof(T) + sizeof(E)plus a discriminant flag, with no heap allocation - Replaces the exception-handling mechanism, making it a good fit for embedded environments where exceptions are disabled (
-fno-exceptions) - More type-safe than the error code + output parameter pattern, forcing callers to handle errors
- Chained operations (transform/and_then) can compose complex workflows while keeping the code linear and readable
Compiler Support
| GCC | Clang | MSVC |
|---|---|---|
| 12 | 16 | 19.36 |
See Also
Part of the content references cppreference.com, licensed under CC-BY-SA 4.0