expected lite is a single-file header-only library for objects that either represent a valid value or an error that you can pass by value. It is intended for use with C++11 and later. The library is based on the std::expected proposal [1] .
Contents
- Example usage
- In a nutshell
- License
- Dependencies
- Installation
- Synopsis
- Comparison with like types
- Reported to work with
- Implementation notes
- Other implementations of expected
- Notes and references
- Appendix
#include "nonstd/expected.hpp"
#include <cstdlib>
#include <iostream>
#include <string>
using namespace nonstd;
using namespace std::literals;
auto to_int( char const * const text ) -> expected<int, std::string>
{
char * pos = nullptr;
auto value = strtol( text, &pos, 0 );
if ( pos != text ) return value;
else return make_unexpected( "'"s + text + "' isn't a number" );
}
int main( int argc, char * argv[] )
{
auto text = argc > 1 ? argv[1] : "42";
auto ei = to_int( text );
if ( ei ) std::cout << "'" << text << "' is " << *ei << ", ";
else std::cout << "Error: " << ei.error();
}
prompt> g++ -std=c++14 -Wall -I../include -o 01-basic.exe 01-basic.cpp && 01-basic.exe 123 && 01-basic.exe abc
'123' is 123, Error: 'abc' isn't a number
expected lite is a single-file header-only library to represent value objects that either contain a valid value or an error. The library is a partly implementation of the proposal for std::expected [1,2,3] for use with C++11 and later.
Some Features and properties of expected lite are ease of installation (single header), default and explicit construction of an expected, construction and assignment from a value that is convertible to the underlying type, copy- and move-construction and copy- and move-assignment from another expected of the same type, testing for the presence of a value, operators for unchecked access to the value or the error (pointer or reference), value() and value_or() for checked access to the value, relational operators, swap() and various factory functions.
Version 0.7.0 introduces the monadic operations of propsoal p2505.
expected lite shares the approach to in-place tags with any-lite, optional-lite and with variant-lite and these libraries can be used together.
Not provided are reference-type expecteds. expected lite doesn't honour triviality of value and error types. expected lite doesn't handle overloaded address of operators.
For more examples, see [1].
expected lite is distributed under the Boost Software License.
expected lite has no other dependencies than the C++ standard library.
expected lite is a single-file header-only library. Put expected.hpp
directly into the project source tree or somewhere reachable from your project.
Contents
- Configuration
- Types in namespace nonstd
- Interface of expected
- Algorithms for expected
- Interface of unexpected_type
- Algorithms for unexpected_type
If the compiler supports __has_include()
, expected lite supports the tweak header mechanism. Provide your tweak header as nonstd/expected.tweak.hpp
in a folder in the include-search-path. In the tweak header, provide definitions as documented below, like #define expected_CPLUSPLUS 201103L
.
-Dnsel_CPLUSPLUS=199711L
Define this macro to override the auto-detection of the supported C++ standard, or if your compiler does not set the __cplusplus
macro correctly.
At default, expected lite uses std::expected
if it is available and lets you use it via namespace nonstd
. You can however override this default and explicitly request to use std::expected
or expected lite's nonstd::expected
as nonstd::expected
via the following macros.
-Dnsel_CONFIG_SELECT_EXPECTED=nsel_EXPECTED_DEFAULT
Define this to nsel_EXPECTED_STD
to select std::expected
as nonstd::expected
. Define this to nsel_EXPECTED_NONSTD
to select nonstd::expected
as nonstd::expected
. Default is undefined, which has the same effect as defining to nsel_EXPECTED_DEFAULT
.
-Dnsel_P0323R=7 (default)
Define this to the proposal revision number to control the presence and behavior of features (see tables). Default is 7 for the latest revision.
-Dnsel_CONFIG_WIN32_LEAN_AND_MEAN=1
Define this to 0 if you want to omit automatic definition of WIN32_LEAN_AND_MEAN
. Default is 1 when _MSC_VER
is present.
-Dnsel_CONFIG_NO_EXCEPTIONS=0
Define this to 1 if you want to compile without exceptions. If not defined, the header tries and detect if exceptions have been disabled (e.g. via -fno-exceptions
or /kernel
). Default determined in header.
-Dnsel_CONFIG_NO_EXCEPTIONS_SEH=0
Define this to 1 or 0 to control the use of SEH when C++ exceptions are disabled (see above). If not defined, the header tries and detect if SEH is available if C++ exceptions have been disabled (e.g. via -fno-exceptions
or /kernel
). Default determined in header.
-Dnsel_CONFIG_CONFIRMS_COMPILATION_ERRORS=0
Define this macro to 1 to experience the by-design compile-time errors of the library in the test suite. Default is 0.
By default, expected lite provides monadic operations as described in P2505R5. You can disable these operations by defining the following macro.
-Dnsel_P2505R=0
You can use the R3 revision of P2505, which lacks error_or
, and uses remove_cvref
for transforms, by defining the following macro.
-Dnsel_P2505R=3
Purpose | Type | Note / Object |
---|---|---|
Expected | template<typename T, typename E = std::exception_ptr> class expected; |
nsel_P0323 <= 2 |
Expected | template<typename T, typename E> class expected; |
nsel_P0323 > 2 |
Error type | template<typename E> class unexpected_type; |
|
Error type | template<> class unexpected_type<std::exception_ptr>; |
nsel_P0323 <= 2 |
Error type | template<typename E> class unexpected; |
>= C++17 |
Traits | template<typename E> struct is_unexpected; |
nsel_P0323 <= 3 |
In-place value construction | struct in_place_t; | in_place_t in_place{}; |
In-place error construction | struct in_place_unexpected_t; | in_place_unexpected_t unexpect{}; |
In-place error construction | struct in_place_unexpected_t; | in_place_unexpected_t in_place_unexpected{}; |
Error reporting | class bad_expected_access; |
Kind | Method | Result |
---|---|---|
Construction | [constexpr] expected() noexcept(...) | an object with default value |
[constexpr] expected( expected const & other ) | initialize to contents of other | |
[constexpr] expected( expected && other ) | move contents from other | |
[constexpr] expected( value_type const & value ) | initialize to value | |
[constexpr] expected( value_type && value ) noexcept(...) | move from value | |
[constexpr] explicit expected( in_place_t, Args&&... args ) | construct value in-place from args | |
[constexpr] explicit expected( in_place_t, std::initializer_list<U> il, Args&&... args ) |
construct value in-place from args | |
[constexpr] expected( unexpected_type const & error ) | initialize to error | |
[constexpr] expected( unexpected_type && error ) | move from error | |
[constexpr] explicit expected( in_place_unexpected_t, Args&&... args ) |
construct error in-place from args | |
[constexpr] explicit expected( in_place_unexpected_t, std::initializer_list<U> il, Args&&... args ) |
construct error in-place from args | |
Destruction | ~expected() | destruct current content |
Assignment | expected operator=( expected const & other ) | assign contents of other; destruct current content, if any |
expected & operator=( expected && other ) noexcept(...) | move contents of other | |
expected & operator=( U && v ) | move value from v | |
expected & operator=( unexpected_type const & u ) | initialize to unexpected | |
expected & operator=( unexpected_type && u ) | move from unexpected | |
template<typename... Args> void emplace( Args &&... args ) |
emplace from args | |
template<typename U, typename... Args> void emplace( std::initializer_list<U> il, Args &&... args ) |
emplace from args | |
Swap | void swap( expected & other ) noexcept | swap with other |
Observers | constexpr value_type const * operator->() const | pointer to current content (const); must contain value |
value_type * operator->() | pointer to current content (non-const); must contain value |
|
constexpr value_type const & operator *() const & | the current content (const ref); must contain value |
|
constexpr value_type && operator *() && | the current content (non-const ref); must contain value |
|
constexpr explicit operator bool() const noexcept | true if contains value | |
constexpr has_value() const noexcept | true if contains value | |
constexpr value_type const & value() const & | current content (const ref); see note 1 |
|
value_type & value() & | current content (non-const ref); see note 1 |
|
constexpr value_type && value() && | move from current content; see note 1 |
|
constexpr error_type const & error() const & | current error (const ref); must contain error |
|
error_type & error() & | current error (non-const ref); must contain error |
|
constexpr error_type && error() && | move from current error; must contain error |
|
constexpr unexpected_type get_unexpected() const | the error as unexpected<>; must contain error |
|
template<typename Ex> bool has_exception() const |
true of contains exception (as base) | |
value_type value_or( U && v ) const & | value or move from v | |
value_type value_or( U && v ) && | move from value or move from v | |
constexpr error_type error_or( G && e ) const & | return current error or v [requires nsel_P2505R >= 4] | |
constexpr error_type error_or( G && e ) && | move from current error or from v [requires nsel_P2505R >=4] | |
Monadic operations (requires nsel_P2505R >= 3) |
constexpr auto and_then( F && f ) & G | return f(value()) if has value, otherwise the error |
constexpr auto and_then( F && f ) const & | return f(value()) if has value, otherwise the error | |
constexpr auto and_then( F && f ) && | return f(std::move(value())) if has value, otherwise the error | |
constexpr auto and_then( F && f ) const && | return f(std::move(value())) if has value, otherwise the error | |
constexpr auto or_else( F && f ) & | return the value, or f(error()) if there is no value | |
constexpr auto or_else( F && f ) const & | return the value, or f(error()) if there is no value | |
constexpr auto or_else( F && f ) && | return the value, or f(std::move(error())) if there is no value | |
constexpr auto or_else( F && f ) const && | return the value, or f(std::move(error())) if there is no value | |
constexpr auto transform( F && f ) & | return f(value()) wrapped if has value, otherwise the error | |
constexpr auto transform( F && f ) const & | return f(value()) wrapped if has value, otherwise the error | |
constexpr auto transform( F && f ) && | return f(std::move(value())) wrapped if has value, otherwise the error | |
constexpr auto transform( F && f ) const && | return f(std::move(value())) wrapped if has value, otherwise the error | |
constexpr auto transform_error( F && f ) & | return the value if has value, or f(error()) otherwise | |
constexpr auto transform_error( F && f ) const & | return the value if has value, or f(error()) otherwise | |
constexpr auto transform_error( F && f ) && | return the value if has value, or f(std::move(error())) otherwise | |
constexpr auto transform_error( F && f ) const && | return the value if has value, or f(std::move(error())) otherwise | |
... |
Note 1: checked access: if no content, for std::exception_ptr rethrows error(), otherwise throws bad_expected_access(error()).
Kind | Function |
---|---|
Comparison with expected | |
== != | template<typename T1, typename E1, typename T2, typename E2> constexpr bool operator op( expected<T1,E1> const & x, expected<T2,E2> const & y ) |
Comparison with expected | nsel_P0323R <= 2 |
< > <= >= | template<typename T, typename E> constexpr bool operator op( expected<T,E> const & x, expected<T,E> const & y ) |
Comparison with unexpected_type | |
== != | template<typename T1, typename E1, typename E2> constexpr bool operator op( expected<T1,E1> const & x, unexpected_type<E2> const & u ) |
template<typename T1, typename E1, typename E2> constexpr bool operator op( unexpected_type<E2> const & u, expected<T1,E1> const & x ) |
|
Comparison with unexpected_type | nsel_P0323R <= 2 |
< > <= >= | template<typename T, typename E> constexpr bool operator op( expected<T,E> const & x, unexpected_type<E> const & u ) |
template<typename T, typename E> constexpr bool operator op( unexpected_type<E> const & u, expected<T,E> const & x ) |
|
Comparison with T | |
== != | template<typename T, typename E> constexpr bool operator op( expected<T,E> const & x, T const & v ) |
template<typename T, typename E> constexpr bool operator op( T const & v, expected<T,E> const & x ) |
|
Comparison with T | nsel_P0323R <= 2 |
< > <= >= | template<typename T, typename E> constexpr bool operator op( expected<T,E> const & x, T const & v ) |
template<typename T, typename E> constexpr bool operator op( T const & v, expected<T,E> const & x ) |
|
Specialized algorithms | |
Swap | template<typename T, typename E> void swap( expected<T,E> & x, expected<T,E> & y ) noexcept( noexcept( x.swap(y) ) ) |
Make expected from | nsel_P0323R <= 3 |
Value | template<typename T> constexpr auto make_expected( T && v ) -> expected< typename std::decay<T>::type> |
Nothing | auto make_expected() -> expected<void> |
Current exception | template<typename T> constexpr auto make_expected_from_current_exception() -> expected<T> |
Exception | template<typename T> auto make_expected_from_exception( std::exception_ptr v ) -> expected<T> |
Error | template<typename T, typename E> constexpr auto make_expected_from_error( E e ) -> expected<T, typename std::decay<E>::type> |
Call | template<typename F> auto make_expected_from_call( F f ) -> expected< typename std::result_of<F()>::type> |
Call, void specialization | template<typename F> auto make_expected_from_call( F f ) -> expected<void> |
Kind | Method | Result |
---|---|---|
Construction | unexpected_type() = delete; | no default construction |
constexpr explicit unexpected_type( E const & error ) | copy-constructed from an E | |
constexpr explicit unexpected_type( E && error ) | move-constructed from an E | |
Observers | constexpr error_type const & error() const | can observe contained error |
error_type & error() | can modify contained error | |
deprecated | constexpr error_type const & value() const | can observe contained error |
deprecated | error_type & value() | can modify contained error |
Kind | Function |
---|---|
Comparison with unexpected | |
== != | template<typename E> constexpr bool operator op( unexpected_type<E> const & x, unexpected_type<E> const & y ) |
Comparison with unexpected | nsel_P0323R <= 2 |
< > <= >= | template<typename E> constexpr bool operator op( unexpected_type<E> const & x, unexpected_type<E> const & y ) |
Comparison with exception_ptr | |
== != | constexpr bool operator op( unexpected_type<std::exception_ptr> const & x, unexpected_type<std::exception_ptr> const & y ) |
Comparison with exception_ptr | nsel_P0323R <= 2 |
< > <= >= | constexpr bool operator op( unexpected_type<std::exception_ptr> const & x, unexpected_type<std::exception_ptr> const & y ) |
Specialized algorithms | |
Make unexpected from | |
Error | template<typename E> [constexpr] auto make_unexpected(E && v) -> unexpected_type< typename std::decay<E>::type> |
Arguments (in-place) | template<typename E, typename... Args> [constexpr] auto make_unexpected(in_place_t, Args &&... args) -> unexpected_type< typename std::decay<E>::type> |
Make unexpected from | nsel_P0323R <= 3 |
Current exception | [constexpr] auto make_unexpected_from_current_exception() -> unexpected_type< std::exception_ptr> |
Feature | std::pair |
std:: optional | std:: expected | nonstd:: expected | Boost. Expected | Nonco expected | Andrei Expected | Hagan required |
---|---|---|---|---|---|---|---|---|
More information | see [14] | see [5] | see [1] | this work | see [4] | see [7] | see [8] | see [13] |
C++03 | yes | no | no | no/not yet | no (union) | no | no | yes |
C++11 | yes | no | no | yes | yes | yes | yes | yes |
C++14 | yes | no | no | yes | yes | yes | yes | yes |
C++17 | yes | yes | no | yes | yes | yes | yes | yes |
DefaultConstructible | T param | yes | yes | yes | yes | no | no | no |
In-place construction | no | yes | yes | yes | yes | yes | no | no |
Literal type | yes | yes | yes | yes | yes | no | no | no |
Disengaged information | possible | no | yes | yes | yes | yes | yes | no |
Vary disengaged type | yes | no | yes | yes | yes | no | no | no |
Engaged nonuse throws | no | no | no | no | error_traits | no | no | yes |
Disengaged use throws | no | yes, value() | yes, value() | yes, value() | yes, value() |
yes, get() |
yes, get() |
n/a |
Proxy (rel.ops) | no | yes | yes | yes | yes | no | no | no |
References | no | yes | no/not yet | no/not yet | no/not yet | yes | no | no |
Chained visitor(s) | no | no | yes | yes | yes | no | no | no |
Note 1: std::experimental::expected
Note 2: sources for Nonco expected, Andrei Expected and Hagan required can befound in the spike-expected repository.
TBD
TBD
- Simon Brand. C++11/14/17 std::expected with functional-style extensions. Single-header.
- Isabella Muerte. MNMLSTC Core (C++11).
- Vicente J. Botet Escriba. stdmake's expected (C++17).
- Facebook. Folly's Expected.h (C++14).
[1] Vicente J. Botet Escriba. p0323 - A proposal to add a utility class to represent expected object (latest) (HTML). (r12, r11, r10, r9, r8, r7, r6, r5, r4, r3, r2, r1, r0, draft).
[2] Vicente J. Botet Escriba. JASEL: Just a simple experimental library for C++. Reference implementation of expected.
[3] Vicente J. Botet Escriba. Expected - An exception-friendly Error Monad. C++Now 2014. 24 September 2014.
[4] Pierre Talbot. Boost.Expected. Unofficial Boost candidate. 5 May 2013. GitHub, GSoC 2013 Proposal, [email protected].
[5] Fernando Cacciola and Andrzej Krzemieński. A proposal to add a utility class to represent optional objects (Revision 4). ISO/IEC JTC1 SC22 WG21 N3672 2013-04-19.
[6] Andrzej Krzemieński, Optional library implementation in C++11.
[7] Anto Nonco. Extending expected to deal with references. 27 May 2013.
[8] Andrei Alexandrescu. Systematic Error Handling in C++. Prepared for The C++and Beyond Seminar 2012. Video. Slides.
[9] Andrei Alexandrescu. Choose your Poison: Exceptions or Error Codes? (PDF). ACCU Conference 2007.
[10] Andrei Alexandrescu. The Power of None (PPT). Northwest C++ Users' Group. May 17th, 2006.
[11] Jon Jagger. A Return Type That Doesn't Like Being Ignored. Overload issue 53, February 2003.
[12] Andrei Alexandrescu. Error Handling in C++: Are we inching towards a total solution?. ACCU Conference 2002.
[13] Ken Hagan et al. Exploding return codes. comp.lang.c++.moderated. 11 February 2000.
[14] std::pair. cppreference.com
[15] Niall Douglas. Outcome. Very lightweight outcome<T> and result<T> (non-Boost edition).
[16] Niall Douglas. p0762 - Concerns about expected<T, E> from the Boost.Outcome peer review. 15 October 2017.
[17] Jeff Garland. p2505 - Monadic Functions for std::expected
(HTML). (r0, r1, r2, r3, r4, r5).
The version of expected lite is available via tag [.version]
. The following tags are available for information on the compiler and on the C++ standard library used: [.compiler]
, [.stdc++]
, [.stdlanguage]
and [.stdlibrary]
.
click to expand
unexpected_type: Disallows default construction
unexpected_type: Allows to copy-construct from unexpected_type, default
unexpected_type: Allows to move-construct from unexpected_type, default
unexpected_type: Allows to in-place-construct
unexpected_type: Allows to in-place-construct from initializer_list
unexpected_type: Allows to copy-construct from error_type
unexpected_type: Allows to move-construct from error_type
unexpected_type: Allows to copy-construct from unexpected_type, explicit converting
unexpected_type: Allows to copy-construct from unexpected_type, non-explicit converting
unexpected_type: Allows to move-construct from unexpected_type, explicit converting
unexpected_type: Allows to move-construct from unexpected_type, non-explicit converting
unexpected_type: Allows to copy-assign from unexpected_type, default
unexpected_type: Allows to move-assign from unexpected_type, default
unexpected_type: Allows to copy-assign from unexpected_type, converting
unexpected_type: Allows to move-assign from unexpected, converting
unexpected_type: Allows to observe its value via a l-value reference
unexpected_type: Allows to observe its value via a r-value reference
unexpected_type: Allows to modify its value via a l-value reference
unexpected_type: Allows to be swapped
unexpected_type<std::exception_ptr>: Disallows default construction
unexpected_type<std::exception_ptr>: Allows to copy-construct from error_type
unexpected_type<std::exception_ptr>: Allows to move-construct from error_type
unexpected_type<std::exception_ptr>: Allows to copy-construct from an exception
unexpected_type<std::exception_ptr>: Allows to observe its value
unexpected_type<std::exception_ptr>: Allows to modify its value
unexpected_type: Provides relational operators
unexpected_type: Provides relational operators, std::exception_ptr specialization
make_unexpected(): Allows to create an unexpected_type<E> from an E
make_unexpected(): Allows to in-place create an unexpected_type<E> from an E
unexpected: C++17 and later provide unexpected_type as unexpected
bad_expected_access: Disallows default construction
bad_expected_access: Allows construction from error_type
bad_expected_access: Allows to observe its error
bad_expected_access: Allows to change its error
bad_expected_access: Provides non-empty what()
expected: Allows to default construct
expected: Allows to default construct from noncopyable, noncopyable value type
expected: Allows to default construct from noncopyable, noncopyable error type
expected: Allows to copy-construct from expected: value
expected: Allows to copy-construct from expected: error
expected: Allows to move-construct from expected: value
expected: Allows to move-construct from expected: error
expected: Allows to copy-construct from expected; value, explicit converting
expected: Allows to copy-construct from expected; error, explicit converting
expected: Allows to copy-construct from expected; value, non-explicit converting
expected: Allows to copy-construct from expected; error, non-explicit converting
expected: Allows to move-construct from expected; value, explicit converting
expected: Allows to move-construct from expected; error, explicit converting
expected: Allows to move-construct from expected; value, non-explicit converting
expected: Allows to move-construct from expected; error, non-explicit converting
expected: Allows to forward-construct from value, explicit converting
expected: Allows to forward-construct from value, non-explicit converting
expected: Allows to in-place-construct value
expected: Allows to in-place-construct value from initializer_list
expected: Allows to copy-construct from unexpected, explicit converting
expected: Allows to copy-construct from unexpected, non-explicit converting
expected: Allows to move-construct from unexpected, explicit converting
expected: Allows to move-construct from unexpected, non-explicit converting
expected: Allows to in-place-construct error
expected: Allows to in-place-construct error from initializer_list
expected: Allows to copy-assign from expected, value
expected: Allows to copy-assign from expected, error
expected: Allows to move-assign from expected, value
expected: Allows to move-assign from expected, error
expected: Allows to forward-assign from value
expected: Allows to copy-assign from unexpected
expected: Allows to move-assign from unexpected
expected: Allows to move-assign from move-only unexpected
expected: Allows to emplace value
expected: Allows to emplace value from initializer_list
expected: Allows to be swapped
expected: Allows to observe its value via a pointer
expected: Allows to observe its value via a pointer to constant
expected: Allows to modify its value via a pointer
expected: Allows to observe its value via a l-value reference
expected: Allows to observe its value via a r-value reference
expected: Allows to modify its value via a l-value reference
expected: Allows to modify its value via a r-value reference
expected: Allows to observe if it contains a value (or error)
expected: Allows to observe its value
expected: Allows to modify its value
expected: Allows to move its value
expected: Allows to observe its error
expected: Allows to modify its error
expected: Allows to move its error
expected: Allows to observe its error as unexpected
expected: Allows to query if it contains an exception of a specific base type
expected: Allows to observe its value if available, or obtain a specified value otherwise
expected: Allows to move its value if available, or obtain a specified value otherwise
expected: Throws bad_expected_access on value access when disengaged
expected: Allows to observe its unexpected value, or fallback to the specified value with error_or [monadic p2505r4]
expected: Allows to map value with and_then [monadic p2505r3]
expected: Allows to map unexpected with or_else [monadic p2505r3]
expected: Allows to transform value [monadic p2505r3]
expected: Allows to map errors with transform_error [monadic p2505r3]
expected<void>: Allows to default-construct
expected<void>: Allows to copy-construct from expected<void>: value
expected<void>: Allows to copy-construct from expected<void>: error
expected<void>: Allows to move-construct from expected<void>: value
expected<void>: Allows to move-construct from expected<void>: error
expected<void>: Allows to in-place-construct
expected<void>: Allows to copy-construct from unexpected, explicit converting
expected<void>: Allows to copy-construct from unexpected, non-explicit converting
expected<void>: Allows to move-construct from unexpected, explicit converting
expected<void>: Allows to move-construct from unexpected, non-explicit converting
expected<void>: Allows to in-place-construct unexpected_type
expected<void>: Allows to in-place-construct error from initializer_list
expected<void>: Allows to copy-assign from expected, value
expected<void>: Allows to copy-assign from expected, error
expected<void>: Allows to move-assign from expected, value
expected<void>: Allows to move-assign from expected, error
expected<void>: Allows to emplace value
expected<void>: Allows to be swapped
expected<void>: Allows to observe if it contains a value (or error)
expected<void>: Allows to observe its value
expected<void>: Allows to observe its error
expected<void>: Allows to modify its error
expected<void>: Allows to move its error
expected<void>: Allows to observe its error as unexpected
expected<void>: Allows to query if it contains an exception of a specific base type
expected<void>: Throws bad_expected_access on value access when disengaged
expected<void>: Allows to observe unexpected value, or fallback to a default value with error_or [monadic p2505r4]
expected<void>: Allows to call argless functions with and_then [monadic p2505r3]
expected<void>: Allows to map to expected or unexpected with or_else [monadic p2505r3]
expected<void>: Allows to assign a new expected value using transform [monadic p2505r3]
expected<void>: Allows to map unexpected error value via transform_error [monadic p2505r3]
operators: Provides expected relational operators
operators: Provides expected relational operators (void)
swap: Allows expected to be swapped
std::hash: Allows to compute hash value for expected
tweak header: reads tweak header if supported [tweak]