std::expected
From cppreference.com
C++
Feature test macros (C++20)
Concepts library (C++20)
Metaprogramming library (C++11)
Ranges library (C++20)
Filesystem library (C++17)
Concurrency support library (C++11)
Execution control library (C++26)
Utilities library
Relational operators (deprecated in C++20)
Integer comparison functions
Swap and type operations
Common vocabulary types
Type support (basic types, RTTI)
Library feature-test macros (C++20)
(C++11)
(C++20)
(C++26)
(C++20)
Coroutine support (C++20)
Contract support (C++26)
(C++20)(C++20)
(C++20)
(C++20)
(C++20)
(C++20)
(C++20)
(C++20)
(C++20)
(C++20)
(C++20)
(C++20)
(C++20)
(C++20)
(C++20)(C++20)(C++20)
(C++20)(C++20)(C++20)
General utilities
(C++20)(C++20)(C++20)
(C++20)(C++20)(C++20)
(C++20)
std::expected
Defined in header
<expected>
template< class T, class E >
class expected;
(1)
(since C++23)
class expected;
template< class T, class E >
(2)
(since C++23)
requires std::is_void_v <T>
The class template std::expected
provides a way to represent either of two values: an expected value of type T
, or an unexpected value of type E
. expected
is never valueless.
1) The main template. Contains the expected or unexpected value within its own storage, which is nested within the
expected
object.2) The void partial specialization. Represents an expected void value or contains an unexpected value. If it contains an unexpected value, it is nested within the
expected
object.A program is ill-formed if it instantiates an expected
with a reference type, a function type, or a specialization of std::unexpected. In addition, T
must not be std::in_place_t or std::unexpect_t.
Contents
[edit] Template parameters
T
-
the type of the expected value. The type must either be (possibly cv-qualified) void, or meet the Destructible requirements (in particular, array and reference types are not allowed).
E
-
the type of the unexpected value. The type must meet the Destructible requirements, and must be a valid template argument for std::unexpected (in particular, arrays, non-object types, and cv-qualified types are not allowed).
[edit] Nested types
Type
Definition
value_type
T
error_type
E
unexpected_type
std::unexpected<E>
[edit] Member templates
Template
Definition
rebind<U>
std::expected<U, error_type>
[edit] Data members
Member
Description
bool
(exposition-only member object*)
has_val
whether the expected
object currently represents the expected value(exposition-only member object*)
T
val
(main template only)
the expected value(exposition-only variant member object*)
E
unex
the unexpected value(exposition-only variant member object*)
[edit] Member functions
Observers
Monadic operations
returns the result of the given function on the expected value if it exists; otherwise, returns the
(public member function) [edit]
expected
itself (public member function) [edit]
returns an
(public member function) [edit]
expected
containing the transformed expected value if it exists; otherwise, returns the expected
itself (public member function) [edit]
returns the
(public member function) [edit]
expected
itself if it contains an expected value; otherwise, returns the result of the given function on the unexpected value (public member function) [edit]
returns the
(public member function) [edit]
expected
itself if it contains an expected value; otherwise, returns an expected
containing the transformed unexpected value (public member function) [edit]
Modifiers
[edit] Non-member functions
[edit] Helper classes
(C++23)
expected
that contains an unexpected value (class template) [edit]
[edit] Notes
Types with the same functionality are called Result
in Rust and Either
in Haskell.
Feature-test macro | Value | Std | Feature |
---|---|---|---|
__cpp_lib_expected |
202202L |
(C++23) | class template std::expected and associated helper classes
|
202211L |
(C++23) | Monadic functions for std::expected
|
[edit] Example
Run this code
#include <cmath> #include <expected> #include <iomanip> #include <iostream> #include <string_view> enum class parse_error { invalid_input, overflow }; auto parse_number(std::string_view & str) -> std::expected<double, parse_error> { const char* begin = str.data(); char* end; double retval = std::strtod (begin, &end); if (begin == end) return std::unexpected (parse_error::invalid_input); else if (std::isinf (retval)) return std::unexpected (parse_error::overflow); str.remove_prefix(end - begin); return retval; } int main() { auto process = [](std::string_view str) { std::cout << "str: " << std::quoted (str) << ", "; if (const auto num = parse_number(str); num.has_value()) std::cout << "value: " << *num << '\n'; // If num did not have a value, dereferencing num // would cause an undefined behavior, and // num.value() would throw std::bad_expected_access. // num.value_or(123) uses specified default value 123. else if (num.error() == parse_error::invalid_input) std::cout << "error: invalid input\n"; else if (num.error() == parse_error::overflow) std::cout << "error: overflow\n"; else std::cout << "unexpected!\n"; // or invoke std::unreachable(); }; for (auto src : {"42", "42abc", "meow", "inf"}) process(src); }
Output:
str: "42", value: 42 str: "42abc", value: 42 str: "meow", error: invalid input str: "inf", error: overflow
[edit] Defect reports
The following behavior-changing defect reports were applied retroactively to previously published C++ standards.
DR | Applied to | Behavior as published | Correct behavior |
---|---|---|---|
LWG 4141 | C++23 | the requirement of storage allocation was confusing |
the contained object must be nested within the expected object
|
[edit] References
- C++23 standard (ISO/IEC 14882:2024):
- 22.8 Expected objects [expected]