Files
2025-10-25 03:02:53 +03:00

1440 lines
57 KiB
Markdown
Raw Permalink Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

[expected.expected]
# 22 General utilities library [[utilities]](./#utilities)
## 22.8 Expected objects [[expected]](expected#expected)
### 22.8.6 Class template expected [expected.expected]
#### [22.8.6.1](#expected.object.general) General [[expected.object.general]](expected.object.general)
namespace std {template<class T, class E>class expected {public:using [value_type](#lib:expected,value_type "22.8.6.1General[expected.object.general]") = T; using [error_type](#lib:expected,error_type "22.8.6.1General[expected.object.general]") = E; using [unexpected_type](#lib:expected,unexpected_type "22.8.6.1General[expected.object.general]") = unexpected<E>; template<class U>using [rebind](#lib:expected,rebind "22.8.6.1General[expected.object.general]") = expected<U, error_type>; // [[expected.object.cons]](#expected.object.cons "22.8.6.2Constructors"), constructorsconstexpr expected(); constexpr expected(const expected&); constexpr expected(expected&&) noexcept(*see below*); template<class U, class G>constexpr explicit(*see below*) expected(const expected<U, G>&); template<class U, class G>constexpr explicit(*see below*) expected(expected<U, G>&&); template<class U = remove_cv_t<T>>constexpr explicit(*see below*) expected(U&& v); template<class G>constexpr explicit(*see below*) expected(const unexpected<G>&); template<class G>constexpr explicit(*see below*) expected(unexpected<G>&&); template<class... Args>constexpr explicit expected(in_place_t, Args&&...); template<class U, class... Args>constexpr explicit expected(in_place_t, initializer_list<U>, Args&&...); template<class... Args>constexpr explicit expected(unexpect_t, Args&&...); template<class U, class... Args>constexpr explicit expected(unexpect_t, initializer_list<U>, Args&&...); // [[expected.object.dtor]](#expected.object.dtor "22.8.6.3Destructor"), destructorconstexpr ~expected(); // [[expected.object.assign]](#expected.object.assign "22.8.6.4Assignment"), assignmentconstexpr expected& operator=(const expected&); constexpr expected& operator=(expected&&) noexcept(*see below*); template<class U = remove_cv_t<T>> constexpr expected& operator=(U&&); template<class G>constexpr expected& operator=(const unexpected<G>&); template<class G>constexpr expected& operator=(unexpected<G>&&); template<class... Args>constexpr T& emplace(Args&&...) noexcept; template<class U, class... Args>constexpr T& emplace(initializer_list<U>, Args&&...) noexcept; // [[expected.object.swap]](#expected.object.swap "22.8.6.5Swap"), swapconstexpr void swap(expected&) noexcept(*see below*); friend constexpr void swap(expected& x, expected& y) noexcept(noexcept(x.swap(y))); // [[expected.object.obs]](#expected.object.obs "22.8.6.6Observers"), observersconstexpr const T* operator->() const noexcept; constexpr T* operator->() noexcept; constexpr const T& operator*() const & noexcept; constexpr T& operator*() & noexcept; constexpr const T&& operator*() const && noexcept; constexpr T&& operator*() && noexcept; constexpr explicit operator bool() const noexcept; constexpr bool has_value() const noexcept; constexpr const T& value() const &; // freestanding-deletedconstexpr T& value() &; // freestanding-deletedconstexpr const T&& value() const &&; // freestanding-deletedconstexpr T&& value() &&; // freestanding-deletedconstexpr const E& error() const & noexcept; constexpr E& error() & noexcept; constexpr const E&& error() const && noexcept; constexpr E&& error() && noexcept; template<class U = remove_cv_t<T>> constexpr T value_or(U&&) const &; template<class U = remove_cv_t<T>> constexpr T value_or(U&&) &&; template<class G = E> constexpr E error_or(G&&) const &; template<class G = E> constexpr E error_or(G&&) &&; // [[expected.object.monadic]](#expected.object.monadic "22.8.6.7Monadic operations"), monadic operationstemplate<class F> constexpr auto and_then(F&& f) &; template<class F> constexpr auto and_then(F&& f) &&; template<class F> constexpr auto and_then(F&& f) const &; template<class F> constexpr auto and_then(F&& f) const &&; template<class F> constexpr auto or_else(F&& f) &; template<class F> constexpr auto or_else(F&& f) &&; template<class F> constexpr auto or_else(F&& f) const &; template<class F> constexpr auto or_else(F&& f) const &&; template<class F> constexpr auto transform(F&& f) &; template<class F> constexpr auto transform(F&& f) &&; template<class F> constexpr auto transform(F&& f) const &; template<class F> constexpr auto transform(F&& f) const &&; template<class F> constexpr auto transform_error(F&& f) &; template<class F> constexpr auto transform_error(F&& f) &&; template<class F> constexpr auto transform_error(F&& f) const &; template<class F> constexpr auto transform_error(F&& f) const &&; // [[expected.object.eq]](#expected.object.eq "22.8.6.8Equality operators"), equality operatorstemplate<class T2, class E2> requires (!is_void_v<T2>)friend constexpr bool operator==(const expected& x, const expected<T2, E2>& y); template<class T2>friend constexpr bool operator==(const expected&, const T2&); template<class E2>friend constexpr bool operator==(const expected&, const unexpected<E2>&); private:bool *has_val*; // *exposition only*union { T *val*; // *exposition only* E *unex*; // *exposition only*}; };}
[1](#expected.object.general-1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L8126)
Any object of type expected<T, E> either
contains a value of type T or
a value of type E nested within ([[intro.object]](intro.object "6.8.2Object model")) it[.](#expected.object.general-1.sentence-1)
Member *has_val* indicates whether the expected<T, E> object
contains an object of type T[.](#expected.object.general-1.sentence-2)
[2](#expected.object.general-2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L8134)
A type T is a [*valid value type for expected*](#def:valid_value_type_for_expected),
if remove_cv_t<T> is void or a complete non-array object type that is not in_place_t,unexpect_t,
or a specialization of unexpected[.](#expected.object.general-2.sentence-1)
A program which instantiates class template expected<T, E> with an argument T that is not a valid value
type for expected is ill-formed[.](#expected.object.general-2.sentence-2)
A program that instantiates
the definition of the template expected<T, E> with a type for the E parameter
that is not a valid template argument for unexpected is ill-formed[.](#expected.object.general-2.sentence-3)
[3](#expected.object.general-3)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L8148)
When T is not cv void, it shall meet
the [*Cpp17Destructible*](utility.arg.requirements#:Cpp17Destructible "16.4.4.2Template argument requirements[utility.arg.requirements]") requirements (Table [35](utility.arg.requirements#tab:cpp17.destructible "Table 35: Cpp17Destructible requirements"))[.](#expected.object.general-3.sentence-1)
E shall meet
the [*Cpp17Destructible*](utility.arg.requirements#:Cpp17Destructible "16.4.4.2Template argument requirements[utility.arg.requirements]") requirements[.](#expected.object.general-3.sentence-2)
#### [22.8.6.2](#expected.object.cons) Constructors [[expected.object.cons]](expected.object.cons)
[1](#expected.object.cons-1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L8156)
The exposition-only variable template *converts-from-any-cvref* defined in [[optional.ctor]](optional.ctor "22.5.3.2Constructors") is used by some constructors for expected[.](#expected.object.cons-1.sentence-1)
[🔗](#lib:expected,constructor)
`constexpr expected();
`
[2](#expected.object.cons-2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L8167)
*Constraints*: is_default_constructible_v<T> is true[.](#expected.object.cons-2.sentence-1)
[3](#expected.object.cons-3)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L8171)
*Effects*: Value-initializes *val*[.](#expected.object.cons-3.sentence-1)
[4](#expected.object.cons-4)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L8175)
*Postconditions*: has_value() is true[.](#expected.object.cons-4.sentence-1)
[5](#expected.object.cons-5)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L8179)
*Throws*: Any exception thrown by the initialization of *val*[.](#expected.object.cons-5.sentence-1)
[🔗](#lib:expected,constructor_)
`constexpr expected(const expected& rhs);
`
[6](#expected.object.cons-6)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L8190)
*Effects*: If rhs.has_value() is true,
direct-non-list-initializes *val* with *rhs[.](#expected.object.cons-6.sentence-1)
Otherwise, direct-non-list-initializes *unex* with rhs.error()[.](#expected.object.cons-6.sentence-2)
[7](#expected.object.cons-7)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L8196)
*Postconditions*: rhs.has_value() == this->has_value()[.](#expected.object.cons-7.sentence-1)
[8](#expected.object.cons-8)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L8200)
*Throws*: Any exception thrown by the initialization of *val* or *unex*[.](#expected.object.cons-8.sentence-1)
[9](#expected.object.cons-9)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L8204)
*Remarks*: This constructor is defined as deleted unless
- [(9.1)](#expected.object.cons-9.1)
is_copy_constructible_v<T> is true and
- [(9.2)](#expected.object.cons-9.2)
is_copy_constructible_v<E> is true[.](#expected.object.cons-9.sentence-1)
[10](#expected.object.cons-10)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L8214)
This constructor is trivial if
- [(10.1)](#expected.object.cons-10.1)
is_trivially_copy_constructible_v<T> is true and
- [(10.2)](#expected.object.cons-10.2)
is_trivially_copy_constructible_v<E> is true[.](#expected.object.cons-10.sentence-1)
[🔗](#lib:expected,constructor__)
`constexpr expected(expected&& rhs) noexcept(see below);
`
[11](#expected.object.cons-11)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L8230)
*Constraints*:
- [(11.1)](#expected.object.cons-11.1)
is_move_constructible_v<T> is true and
- [(11.2)](#expected.object.cons-11.2)
is_move_constructible_v<E> is true[.](#expected.object.cons-11.sentence-1)
[12](#expected.object.cons-12)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L8239)
*Effects*: If rhs.has_value() is true,
direct-non-list-initializes *val* with std::move(*rhs)[.](#expected.object.cons-12.sentence-1)
Otherwise,
direct-non-list-initializes *unex* with std::move(rhs.error())[.](#expected.object.cons-12.sentence-2)
[13](#expected.object.cons-13)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L8246)
*Postconditions*: rhs.has_value() is unchanged;rhs.has_value() == this->has_value() is true[.](#expected.object.cons-13.sentence-1)
[14](#expected.object.cons-14)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L8251)
*Throws*: Any exception thrown by the initialization of *val* or *unex*[.](#expected.object.cons-14.sentence-1)
[15](#expected.object.cons-15)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L8255)
*Remarks*: The exception specification is equivalent tois_nothrow_move_constructible_v<T> && is_nothrow_move_constructible_v<E>[.](#expected.object.cons-15.sentence-1)
[16](#expected.object.cons-16)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L8261)
This constructor is trivial if
- [(16.1)](#expected.object.cons-16.1)
is_trivially_move_constructible_v<T> is true and
- [(16.2)](#expected.object.cons-16.2)
is_trivially_move_constructible_v<E> is true[.](#expected.object.cons-16.sentence-1)
[🔗](#lib:expected,constructor___)
`template<class U, class G>
constexpr explicit(see below) expected(const expected<U, G>& rhs);
template<class U, class G>
constexpr explicit(see below) expected(expected<U, G>&& rhs);
`
[17](#expected.object.cons-17)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L8280)
Let:
- [(17.1)](#expected.object.cons-17.1)
UF be const U& for the first overload andU for the second overload[.](#expected.object.cons-17.1.sentence-1)
- [(17.2)](#expected.object.cons-17.2)
GF be const G& for the first overload andG for the second overload[.](#expected.object.cons-17.2.sentence-1)
[18](#expected.object.cons-18)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L8291)
*Constraints*:
- [(18.1)](#expected.object.cons-18.1)
is_constructible_v<T, UF> is true; and
- [(18.2)](#expected.object.cons-18.2)
is_constructible_v<E, GF> is true; and
- [(18.3)](#expected.object.cons-18.3)
if T is not cv bool,*converts-from-any-cvref*<T, expected<U, G>> is false; and
- [(18.4)](#expected.object.cons-18.4)
is_constructible_v<unexpected<E>, expected<U, G>&> is false; and
- [(18.5)](#expected.object.cons-18.5)
is_constructible_v<unexpected<E>, expected<U, G>> is false; and
- [(18.6)](#expected.object.cons-18.6)
is_constructible_v<unexpected<E>, const expected<U, G>&> is false; and
- [(18.7)](#expected.object.cons-18.7)
is_constructible_v<unexpected<E>, const expected<U, G>> is false[.](#expected.object.cons-18.sentence-1)
[19](#expected.object.cons-19)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L8311)
*Effects*: If rhs.has_value(),
direct-non-list-initializes *val* with std::forward<UF>(*rhs)[.](#expected.object.cons-19.sentence-1)
Otherwise,
direct-non-list-initializes *unex* with std::forward<GF>(rhs.error())[.](#expected.object.cons-19.sentence-2)
[20](#expected.object.cons-20)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L8318)
*Postconditions*: rhs.has_value() is unchanged;rhs.has_value() == this->has_value() is true[.](#expected.object.cons-20.sentence-1)
[21](#expected.object.cons-21)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L8323)
*Throws*: Any exception thrown by the initialization of *val* or *unex*[.](#expected.object.cons-21.sentence-1)
[22](#expected.object.cons-22)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L8327)
*Remarks*: The expression inside explicit is equivalent to!is_convertible_v<UF, T> || !is_convertible_v<GF, E>[.](#expected.object.cons-22.sentence-1)
[🔗](#lib:expected,constructor____)
`template<class U = remove_cv_t<T>>
constexpr explicit(!is_convertible_v<U, T>) expected(U&& v);
`
[23](#expected.object.cons-23)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L8340)
*Constraints*:
- [(23.1)](#expected.object.cons-23.1)
is_same_v<remove_cvref_t<U>, in_place_t> is false; and
- [(23.2)](#expected.object.cons-23.2)
is_same_v<remove_cvref_t<U>, expected> is false; and
- [(23.3)](#expected.object.cons-23.3)
is_same_v<remove_cvref_t<U>, unexpect_t> is false; and
- [(23.4)](#expected.object.cons-23.4)
remove_cvref_t<U> is not a specialization of unexpected; and
- [(23.5)](#expected.object.cons-23.5)
is_constructible_v<T, U> is true; and
- [(23.6)](#expected.object.cons-23.6)
if T is cv bool,remove_cvref_t<U> is not a specialization of expected[.](#expected.object.cons-23.sentence-1)
[24](#expected.object.cons-24)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L8358)
*Effects*: Direct-non-list-initializes *val* with std::forward<U>(v)[.](#expected.object.cons-24.sentence-1)
[25](#expected.object.cons-25)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L8362)
*Postconditions*: has_value() is true[.](#expected.object.cons-25.sentence-1)
[26](#expected.object.cons-26)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L8366)
*Throws*: Any exception thrown by the initialization of *val*[.](#expected.object.cons-26.sentence-1)
[🔗](#lib:expected,constructor_____)
`template<class G>
constexpr explicit(!is_convertible_v<const G&, E>) expected(const unexpected<G>& e);
template<class G>
constexpr explicit(!is_convertible_v<G, E>) expected(unexpected<G>&& e);
`
[27](#expected.object.cons-27)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L8380)
Let GF be const G& for the first overload andG for the second overload[.](#expected.object.cons-27.sentence-1)
[28](#expected.object.cons-28)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L8384)
*Constraints*: is_constructible_v<E, GF> is true[.](#expected.object.cons-28.sentence-1)
[29](#expected.object.cons-29)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L8388)
*Effects*: Direct-non-list-initializes *unex* with std::forward<GF>(e.error())[.](#expected.object.cons-29.sentence-1)
[30](#expected.object.cons-30)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L8392)
*Postconditions*: has_value() is false[.](#expected.object.cons-30.sentence-1)
[31](#expected.object.cons-31)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L8396)
*Throws*: Any exception thrown by the initialization of *unex*[.](#expected.object.cons-31.sentence-1)
[🔗](#lib:expected,constructor______)
`template<class... Args>
constexpr explicit expected(in_place_t, Args&&... args);
`
[32](#expected.object.cons-32)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L8408)
*Constraints*: is_constructible_v<T, Args...> is true[.](#expected.object.cons-32.sentence-1)
[33](#expected.object.cons-33)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L8412)
*Effects*: Direct-non-list-initializes *val* with std::forward<Args>(args)...[.](#expected.object.cons-33.sentence-1)
[34](#expected.object.cons-34)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L8416)
*Postconditions*: has_value() is true[.](#expected.object.cons-34.sentence-1)
[35](#expected.object.cons-35)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L8420)
*Throws*: Any exception thrown by the initialization of *val*[.](#expected.object.cons-35.sentence-1)
[🔗](#lib:expected,constructor_______)
`template<class U, class... Args>
constexpr explicit expected(in_place_t, initializer_list<U> il, Args&&... args);
`
[36](#expected.object.cons-36)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L8432)
*Constraints*: is_constructible_v<T, initializer_list<U>&, Args...> is true[.](#expected.object.cons-36.sentence-1)
[37](#expected.object.cons-37)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L8436)
*Effects*: Direct-non-list-initializes *val* withil, std::forward<Args>(args)...[.](#expected.object.cons-37.sentence-1)
[38](#expected.object.cons-38)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L8441)
*Postconditions*: has_value() is true[.](#expected.object.cons-38.sentence-1)
[39](#expected.object.cons-39)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L8445)
*Throws*: Any exception thrown by the initialization of *val*[.](#expected.object.cons-39.sentence-1)
[🔗](#lib:expected,constructor________)
`template<class... Args>
constexpr explicit expected(unexpect_t, Args&&... args);
`
[40](#expected.object.cons-40)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L8457)
*Constraints*: is_constructible_v<E, Args...> is true[.](#expected.object.cons-40.sentence-1)
[41](#expected.object.cons-41)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L8461)
*Effects*: Direct-non-list-initializes *unex* withstd::forward<Args>(args)...[.](#expected.object.cons-41.sentence-1)
[42](#expected.object.cons-42)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L8466)
*Postconditions*: has_value() is false[.](#expected.object.cons-42.sentence-1)
[43](#expected.object.cons-43)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L8470)
*Throws*: Any exception thrown by the initialization of *unex*[.](#expected.object.cons-43.sentence-1)
[🔗](#lib:expected,constructor_________)
`template<class U, class... Args>
constexpr explicit expected(unexpect_t, initializer_list<U> il, Args&&... args);
`
[44](#expected.object.cons-44)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L8482)
*Constraints*: is_constructible_v<E, initializer_list<U>&, Args...> is true[.](#expected.object.cons-44.sentence-1)
[45](#expected.object.cons-45)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L8486)
*Effects*: Direct-non-list-initializes *unex* withil, std::forward<Args>(args)...[.](#expected.object.cons-45.sentence-1)
[46](#expected.object.cons-46)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L8491)
*Postconditions*: has_value() is false[.](#expected.object.cons-46.sentence-1)
[47](#expected.object.cons-47)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L8495)
*Throws*: Any exception thrown by the initialization of *unex*[.](#expected.object.cons-47.sentence-1)
#### [22.8.6.3](#expected.object.dtor) Destructor [[expected.object.dtor]](expected.object.dtor)
[🔗](#lib:expected,destructor)
`constexpr ~expected();
`
[1](#expected.object.dtor-1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L8508)
*Effects*: If has_value() is true, destroys *val*,
otherwise destroys *unex*[.](#expected.object.dtor-1.sentence-1)
[2](#expected.object.dtor-2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L8513)
*Remarks*: If is_trivially_destructible_v<T> is true, andis_trivially_destructible_v<E> is true,
then this destructor is a trivial destructor[.](#expected.object.dtor-2.sentence-1)
#### [22.8.6.4](#expected.object.assign) Assignment [[expected.object.assign]](expected.object.assign)
[1](#expected.object.assign-1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L8522)
This subclause makes use of the following exposition-only function template:template<class T, class U, class... Args>constexpr void *reinit-expected*(T& newval, U& oldval, Args&&... args) { // *exposition only*if constexpr (is_nothrow_constructible_v<T, Args...>) { destroy_at(addressof(oldval));
construct_at(addressof(newval), std::forward<Args>(args)...); } else if constexpr (is_nothrow_move_constructible_v<T>) { T tmp(std::forward<Args>(args)...);
destroy_at(addressof(oldval));
construct_at(addressof(newval), std::move(tmp)); } else { U tmp(std::move(oldval));
destroy_at(addressof(oldval)); try { construct_at(addressof(newval), std::forward<Args>(args)...); } catch (...) { construct_at(addressof(oldval), std::move(tmp)); throw; }}}
[🔗](#lib:operator=,expected)
`constexpr expected& operator=(const expected& rhs);
`
[2](#expected.object.assign-2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L8553)
*Effects*:
- [(2.1)](#expected.object.assign-2.1)
If this->has_value() && rhs.has_value() is true,
equivalent to *val* = *rhs[.](#expected.object.assign-2.1.sentence-1)
- [(2.2)](#expected.object.assign-2.2)
Otherwise, if this->has_value() is true, equivalent to:*reinit-expected*(*unex*, *val*, rhs.error())
- [(2.3)](#expected.object.assign-2.3)
Otherwise, if rhs.has_value() is true, equivalent to:*reinit-expected*(*val*, *unex*, *rhs)
- [(2.4)](#expected.object.assign-2.4)
Otherwise, equivalent to *unex* = rhs.error()[.](#expected.object.assign-2.4.sentence-1)
Then, if no exception was thrown,
equivalent to: *has_val* = rhs.has_value(); return *this;
[3](#expected.object.assign-3)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L8575)
*Returns*: *this[.](#expected.object.assign-3.sentence-1)
[4](#expected.object.assign-4)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L8579)
*Remarks*: This operator is defined as deleted unless:
- [(4.1)](#expected.object.assign-4.1)
is_copy_assignable_v<T> is true and
- [(4.2)](#expected.object.assign-4.2)
is_copy_constructible_v<T> is true and
- [(4.3)](#expected.object.assign-4.3)
is_copy_assignable_v<E> is true and
- [(4.4)](#expected.object.assign-4.4)
is_copy_constructible_v<E> is true and
- [(4.5)](#expected.object.assign-4.5)
is_nothrow_move_constructible_v<T> || is_nothrow_move_constructible_v<E> is true[.](#expected.object.assign-4.sentence-1)
[🔗](#lib:operator=,expected_)
`constexpr expected& operator=(expected&& rhs) noexcept(see below);
`
[5](#expected.object.assign-5)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L8603)
*Constraints*:
- [(5.1)](#expected.object.assign-5.1)
is_move_constructible_v<T> is true and
- [(5.2)](#expected.object.assign-5.2)
is_move_assignable_v<T> is true and
- [(5.3)](#expected.object.assign-5.3)
is_move_constructible_v<E> is true and
- [(5.4)](#expected.object.assign-5.4)
is_move_assignable_v<E> is true and
- [(5.5)](#expected.object.assign-5.5)
is_nothrow_move_constructible_v<T> || is_nothrow_move_constructible_v<E> is true[.](#expected.object.assign-5.sentence-1)
[6](#expected.object.assign-6)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L8619)
*Effects*:
- [(6.1)](#expected.object.assign-6.1)
If this->has_value() && rhs.has_value() is true,
equivalent to *val* = std::move(*rhs)[.](#expected.object.assign-6.1.sentence-1)
- [(6.2)](#expected.object.assign-6.2)
Otherwise, if this->has_value() is true, equivalent to:*reinit-expected*(*unex*, *val*, std::move(rhs.error()))
- [(6.3)](#expected.object.assign-6.3)
Otherwise, if rhs.has_value() is true, equivalent to:*reinit-expected*(*val*, *unex*, std::move(*rhs))
- [(6.4)](#expected.object.assign-6.4)
Otherwise, equivalent to *unex* = std::move(rhs.error())[.](#expected.object.assign-6.4.sentence-1)
Then, if no exception was thrown,
equivalent to: has_val = rhs.has_value(); return *this;
[7](#expected.object.assign-7)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L8641)
*Returns*: *this[.](#expected.object.assign-7.sentence-1)
[8](#expected.object.assign-8)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L8645)
*Remarks*: The exception specification is equivalent to:is_nothrow_move_assignable_v<T> && is_nothrow_move_constructible_v<T> && is_nothrow_move_assignable_v<E> && is_nothrow_move_constructible_v<E>
[🔗](#lib:operator=,expected__)
`template<class U = remove_cv_t<T>>
constexpr expected& operator=(U&& v);
`
[9](#expected.object.assign-9)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L8661)
*Constraints*:
- [(9.1)](#expected.object.assign-9.1)
is_same_v<expected, remove_cvref_t<U>> is false; and
- [(9.2)](#expected.object.assign-9.2)
remove_cvref_t<U> is not a specialization of unexpected; and
- [(9.3)](#expected.object.assign-9.3)
is_constructible_v<T, U> is true; and
- [(9.4)](#expected.object.assign-9.4)
is_assignable_v<T&, U> is true; and
- [(9.5)](#expected.object.assign-9.5)
is_nothrow_constructible_v<T, U> || is_nothrow_move_constructible_v<T> ||
is_nothrow_move_constructible_v<E> is true[.](#expected.object.assign-9.sentence-1)
[10](#expected.object.assign-10)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L8678)
*Effects*:
- [(10.1)](#expected.object.assign-10.1)
If has_value() is true,
equivalent to: *val* = std::forward<U>(v);
- [(10.2)](#expected.object.assign-10.2)
Otherwise, equivalent to:*reinit-expected*(*val*, *unex*, std::forward<U>(v));*has_val* = true;
[11](#expected.object.assign-11)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L8692)
*Returns*: *this[.](#expected.object.assign-11.sentence-1)
[🔗](#lib:operator=,expected___)
`template<class G>
constexpr expected& operator=(const unexpected<G>& e);
template<class G>
constexpr expected& operator=(unexpected<G>&& e);
`
[12](#expected.object.assign-12)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L8706)
Let GF be const G& for the first overload andG for the second overload[.](#expected.object.assign-12.sentence-1)
[13](#expected.object.assign-13)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L8710)
*Constraints*:
- [(13.1)](#expected.object.assign-13.1)
is_constructible_v<E, GF> is true; and
- [(13.2)](#expected.object.assign-13.2)
is_assignable_v<E&, GF> is true; and
- [(13.3)](#expected.object.assign-13.3)
is_nothrow_constructible_v<E, GF> || is_nothrow_move_constructible_v<T> ||
is_nothrow_move_constructible_v<E> is true[.](#expected.object.assign-13.sentence-1)
[14](#expected.object.assign-14)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L8722)
*Effects*:
- [(14.1)](#expected.object.assign-14.1)
If has_value() is true, equivalent to:*reinit-expected*(*unex*, *val*, std::forward<GF>(e.error()));*has_val* = false;
- [(14.2)](#expected.object.assign-14.2)
Otherwise, equivalent to:*unex* = std::forward<GF>(e.error());
[15](#expected.object.assign-15)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L8736)
*Returns*: *this[.](#expected.object.assign-15.sentence-1)
[🔗](#lib:emplace,expected)
`template<class... Args>
constexpr T& emplace(Args&&... args) noexcept;
`
[16](#expected.object.assign-16)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L8748)
*Constraints*: is_nothrow_constructible_v<T, Args...> is true[.](#expected.object.assign-16.sentence-1)
[17](#expected.object.assign-17)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L8752)
*Effects*: Equivalent to:if (has_value()) { destroy_at(addressof(*val*));} else { destroy_at(addressof(*unex*)); *has_val* = true;}return *construct_at(addressof(*val*), std::forward<Args>(args)...);
[🔗](#lib:emplace,expected_)
`template<class U, class... Args>
constexpr T& emplace(initializer_list<U> il, Args&&... args) noexcept;
`
[18](#expected.object.assign-18)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L8773)
*Constraints*: is_nothrow_constructible_v<T, initializer_list<U>&, Args...> is true[.](#expected.object.assign-18.sentence-1)
[19](#expected.object.assign-19)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L8778)
*Effects*: Equivalent to:if (has_value()) { destroy_at(addressof(*val*));} else { destroy_at(addressof(*unex*)); *has_val* = true;}return *construct_at(addressof(*val*), il, std::forward<Args>(args)...);
#### [22.8.6.5](#expected.object.swap) Swap [[expected.object.swap]](expected.object.swap)
[🔗](#lib:swap,expected)
`constexpr void swap(expected& rhs) noexcept(see below);
`
[1](#expected.object.swap-1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L8800)
*Constraints*:
- [(1.1)](#expected.object.swap-1.1)
is_swappable_v<T> is true and
- [(1.2)](#expected.object.swap-1.2)
is_swappable_v<E> is true and
- [(1.3)](#expected.object.swap-1.3)
is_move_constructible_v<T> && is_move_constructible_v<E> is true, and
- [(1.4)](#expected.object.swap-1.4)
is_nothrow_move_constructible_v<T> || is_nothrow_move_constructible_v<E> is true[.](#expected.object.swap-1.sentence-1)
[2](#expected.object.swap-2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L8815)
*Effects*: See Table [72](#tab:expected.object.swap "Table 72: swap(expected&amp;) effects")[.](#expected.object.swap-2.sentence-1)
Table [72](#tab:expected.object.swap) — swap(expected&) effects [[tab:expected.object.swap]](./tab:expected.object.swap)
| [🔗](#tab:expected.object.swap-row-1) | **this->has_value()** | **!this->has_value()** |
| --- | --- | --- |
| [🔗](#tab:expected.object.swap-row-2)<br>**rhs.has_value()** | equivalent to: using std::swap; swap(*val*, rhs.*val*); | calls rhs.swap(*this) |
| [🔗](#tab:expected.object.swap-row-3)<br>**!rhs.has_value()** | *see below* | equivalent to: using std::swap; swap(*unex*, rhs.*unex*); |
For the case where rhs.has_value() is false andthis->has_value() is true, equivalent to:if constexpr (is_nothrow_move_constructible_v<E>) { E tmp(std::move(rhs.*unex*));
destroy_at(addressof(rhs.*unex*)); try { construct_at(addressof(rhs.*val*), std::move(*val*));
destroy_at(addressof(*val*));
construct_at(addressof(*unex*), std::move(tmp)); } catch(...) { construct_at(addressof(rhs.*unex*), std::move(tmp)); throw; }} else { T tmp(std::move(*val*));
destroy_at(addressof(*val*)); try { construct_at(addressof(*unex*), std::move(rhs.*unex*));
destroy_at(addressof(rhs.*unex*));
construct_at(addressof(rhs.*val*), std::move(tmp)); } catch (...) { construct_at(addressof(*val*), std::move(tmp)); throw; }}*has_val* = false;
rhs.*has_val* = true;
[3](#expected.object.swap-3)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L8861)
*Throws*: Any exception thrown by the expressions in the *Effects*[.](#expected.object.swap-3.sentence-1)
[4](#expected.object.swap-4)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L8865)
*Remarks*: The exception specification is equivalent to:is_nothrow_move_constructible_v<T> && is_nothrow_swappable_v<T> && is_nothrow_move_constructible_v<E> && is_nothrow_swappable_v<E>
[🔗](#lib:swap,expected_)
`friend constexpr void swap(expected& x, expected& y) noexcept(noexcept(x.swap(y)));
`
[5](#expected.object.swap-5)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L8880)
*Effects*: Equivalent to x.swap(y)[.](#expected.object.swap-5.sentence-1)
#### [22.8.6.6](#expected.object.obs) Observers [[expected.object.obs]](expected.object.obs)
[🔗](#lib:operator-%3e,expected)
`constexpr const T* operator->() const noexcept;
constexpr T* operator->() noexcept;
`
[1](#expected.object.obs-1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L8894)
*Hardened preconditions*: has_value() is true[.](#expected.object.obs-1.sentence-1)
[2](#expected.object.obs-2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L8898)
*Returns*: addressof(*val*)[.](#expected.object.obs-2.sentence-1)
[🔗](#lib:operator*,expected)
`constexpr const T& operator*() const & noexcept;
constexpr T& operator*() & noexcept;
`
[3](#expected.object.obs-3)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L8910)
*Hardened preconditions*: has_value() is true[.](#expected.object.obs-3.sentence-1)
[4](#expected.object.obs-4)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L8914)
*Returns*: *val*[.](#expected.object.obs-4.sentence-1)
[🔗](#lib:operator*,expected_)
`constexpr T&& operator*() && noexcept;
constexpr const T&& operator*() const && noexcept;
`
[5](#expected.object.obs-5)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L8926)
*Hardened preconditions*: has_value() is true[.](#expected.object.obs-5.sentence-1)
[6](#expected.object.obs-6)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L8930)
*Returns*: std::move(*val*)[.](#expected.object.obs-6.sentence-1)
[🔗](#lib:operator_bool,expected)
`constexpr explicit operator bool() const noexcept;
constexpr bool has_value() const noexcept;
`
[7](#expected.object.obs-7)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L8943)
*Returns*: *has_val*[.](#expected.object.obs-7.sentence-1)
[🔗](#lib:value,expected)
`constexpr const T& value() const &;
constexpr T& value() &;
`
[8](#expected.object.obs-8)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L8955)
*Mandates*: is_copy_constructible_v<E> is true[.](#expected.object.obs-8.sentence-1)
[9](#expected.object.obs-9)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L8959)
*Returns*: *val*, if has_value() is true[.](#expected.object.obs-9.sentence-1)
[10](#expected.object.obs-10)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L8963)
*Throws*: bad_expected_access(as_const(error())) if has_value() is false[.](#expected.object.obs-10.sentence-1)
[🔗](#lib:value,expected_)
`constexpr T&& value() &&;
constexpr const T&& value() const &&;
`
[11](#expected.object.obs-11)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L8975)
*Mandates*: is_copy_constructible_v<E> is true andis_constructible_v<E, decltype(std::move(error()))> is true[.](#expected.object.obs-11.sentence-1)
[12](#expected.object.obs-12)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L8980)
*Returns*: std::move(*val*), if has_value() is true[.](#expected.object.obs-12.sentence-1)
[13](#expected.object.obs-13)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L8984)
*Throws*: bad_expected_access(std::move(error())) if has_value() is false[.](#expected.object.obs-13.sentence-1)
[🔗](#lib:error,expected)
`constexpr const E& error() const & noexcept;
constexpr E& error() & noexcept;
`
[14](#expected.object.obs-14)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L8997)
*Hardened preconditions*: has_value() is false[.](#expected.object.obs-14.sentence-1)
[15](#expected.object.obs-15)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L9001)
*Returns*: *unex*[.](#expected.object.obs-15.sentence-1)
[🔗](#lib:error,expected_)
`constexpr E&& error() && noexcept;
constexpr const E&& error() const && noexcept;
`
[16](#expected.object.obs-16)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L9013)
*Hardened preconditions*: has_value() is false[.](#expected.object.obs-16.sentence-1)
[17](#expected.object.obs-17)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L9017)
*Returns*: std::move(*unex*)[.](#expected.object.obs-17.sentence-1)
[🔗](#lib:value_or,expected)
`template<class U = remove_cv_t<T>> constexpr T value_or(U&& v) const &;
`
[18](#expected.object.obs-18)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L9028)
*Mandates*: is_copy_constructible_v<T> is true andis_convertible_v<U, T> is true[.](#expected.object.obs-18.sentence-1)
[19](#expected.object.obs-19)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L9033)
*Returns*: has_value() ? **this : static_cast<T>(std::forward<U>(v))[.](#expected.object.obs-19.sentence-1)
[🔗](#lib:value_or,expected_)
`template<class U = remove_cv_t<T>> constexpr T value_or(U&& v) &&;
`
[20](#expected.object.obs-20)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L9044)
*Mandates*: is_move_constructible_v<T> is true andis_convertible_v<U, T> is true[.](#expected.object.obs-20.sentence-1)
[21](#expected.object.obs-21)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L9049)
*Returns*: has_value() ? std::move(**this) : static_cast<T>(std::forward<U>(v))[.](#expected.object.obs-21.sentence-1)
[🔗](#lib:error_or,expected)
`template<class G = E> constexpr E error_or(G&& e) const &;
`
[22](#expected.object.obs-22)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L9060)
*Mandates*: is_copy_constructible_v<E> is true andis_convertible_v<G, E> is true[.](#expected.object.obs-22.sentence-1)
[23](#expected.object.obs-23)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L9065)
*Returns*: std::forward<G>(e) if has_value() is true,error() otherwise[.](#expected.object.obs-23.sentence-1)
[🔗](#lib:error_or,expected_)
`template<class G = E> constexpr E error_or(G&& e) &&;
`
[24](#expected.object.obs-24)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L9077)
*Mandates*: is_move_constructible_v<E> is true andis_convertible_v<G, E> is true[.](#expected.object.obs-24.sentence-1)
[25](#expected.object.obs-25)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L9082)
*Returns*: std::forward<G>(e) if has_value() is true,std::move(error()) otherwise[.](#expected.object.obs-25.sentence-1)
#### [22.8.6.7](#expected.object.monadic) Monadic operations [[expected.object.monadic]](expected.object.monadic)
[🔗](#lib:and_then,expected)
`template<class F> constexpr auto and_then(F&& f) &;
template<class F> constexpr auto and_then(F&& f) const &;
`
[1](#expected.object.monadic-1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L9097)
Let U be remove_cvref_t<invoke_result_t<F, decltype((*val*))>>[.](#expected.object.monadic-1.sentence-1)
[2](#expected.object.monadic-2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L9100)
*Constraints*: is_constructible_v<E, decltype(error())> is true[.](#expected.object.monadic-2.sentence-1)
[3](#expected.object.monadic-3)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L9104)
*Mandates*: U is a specialization of expected andis_same_v<U::error_type, E> is true[.](#expected.object.monadic-3.sentence-1)
[4](#expected.object.monadic-4)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L9109)
*Effects*: Equivalent to:if (has_value())return invoke(std::forward<F>(f), *val*);elsereturn U(unexpect, error());
[🔗](#lib:and_then,expected_)
`template<class F> constexpr auto and_then(F&& f) &&;
template<class F> constexpr auto and_then(F&& f) const &&;
`
[5](#expected.object.monadic-5)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L9127)
Let U beremove_cvref_t<invoke_result_t<F, decltype(std::move(*val*))>>[.](#expected.object.monadic-5.sentence-1)
[6](#expected.object.monadic-6)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L9131)
*Constraints*: is_constructible_v<E, decltype(std::move(error()))> is true[.](#expected.object.monadic-6.sentence-1)
[7](#expected.object.monadic-7)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L9135)
*Mandates*: U is a specialization of expected andis_same_v<U::error_type, E> is true[.](#expected.object.monadic-7.sentence-1)
[8](#expected.object.monadic-8)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L9140)
*Effects*: Equivalent to:if (has_value())return invoke(std::forward<F>(f), std::move(*val*));elsereturn U(unexpect, std::move(error()));
[🔗](#lib:or_else,expected)
`template<class F> constexpr auto or_else(F&& f) &;
template<class F> constexpr auto or_else(F&& f) const &;
`
[9](#expected.object.monadic-9)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L9158)
Let G be remove_cvref_t<invoke_result_t<F, decltype(error())>>[.](#expected.object.monadic-9.sentence-1)
[10](#expected.object.monadic-10)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L9161)
*Constraints*: is_constructible_v<T, decltype((*val*))> is true[.](#expected.object.monadic-10.sentence-1)
[11](#expected.object.monadic-11)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L9165)
*Mandates*: G is a specialization of expected andis_same_v<G::value_type, T> is true[.](#expected.object.monadic-11.sentence-1)
[12](#expected.object.monadic-12)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L9170)
*Effects*: Equivalent to:if (has_value())return G(in_place, *val*);elsereturn invoke(std::forward<F>(f), error());
[🔗](#lib:or_else,expected_)
`template<class F> constexpr auto or_else(F&& f) &&;
template<class F> constexpr auto or_else(F&& f) const &&;
`
[13](#expected.object.monadic-13)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L9188)
Let G beremove_cvref_t<invoke_result_t<F, decltype(std::move(error()))>>[.](#expected.object.monadic-13.sentence-1)
[14](#expected.object.monadic-14)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L9192)
*Constraints*: is_constructible_v<T, decltype(std::move(*val*))> is true[.](#expected.object.monadic-14.sentence-1)
[15](#expected.object.monadic-15)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L9196)
*Mandates*: G is a specialization of expected andis_same_v<G::value_type, T> is true[.](#expected.object.monadic-15.sentence-1)
[16](#expected.object.monadic-16)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L9201)
*Effects*: Equivalent to:if (has_value())return G(in_place, std::move(*val*));elsereturn invoke(std::forward<F>(f), std::move(error()));
[🔗](#lib:transform,expected)
`template<class F> constexpr auto transform(F&& f) &;
template<class F> constexpr auto transform(F&& f) const &;
`
[17](#expected.object.monadic-17)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L9219)
Let U beremove_cv_t<invoke_result_t<F, decltype((*val*))>>[.](#expected.object.monadic-17.sentence-1)
[18](#expected.object.monadic-18)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L9223)
*Constraints*: is_constructible_v<E, decltype(error())> is true[.](#expected.object.monadic-18.sentence-1)
[19](#expected.object.monadic-19)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L9227)
*Mandates*: U is a valid value type for expected[.](#expected.object.monadic-19.sentence-1)
If is_void_v<U> is false,
the declarationU u(invoke(std::forward<F>(f), *val*)); is well-formed[.](#expected.object.monadic-19.sentence-2)
[20](#expected.object.monadic-20)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L9237)
*Effects*:
- [(20.1)](#expected.object.monadic-20.1)
If has_value() is false, returnsexpected<U, E>(unexpect, error())[.](#expected.object.monadic-20.1.sentence-1)
- [(20.2)](#expected.object.monadic-20.2)
Otherwise, if is_void_v<U> is false, returns anexpected<U, E> object whose *has_val* member is true and *val* member is direct-non-list-initialized withinvoke(std::forward<F>(f), *val*)[.](#expected.object.monadic-20.2.sentence-1)
- [(20.3)](#expected.object.monadic-20.3)
Otherwise, evaluates invoke(std::forward<F>(f), *val*) and then
returns expected<U, E>()[.](#expected.object.monadic-20.3.sentence-1)
[🔗](#lib:transform,expected_)
`template<class F> constexpr auto transform(F&& f) &&;
template<class F> constexpr auto transform(F&& f) const &&;
`
[21](#expected.object.monadic-21)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L9261)
Let U beremove_cv_t<invoke_result_t<F, decltype(std::move(*val*))>>[.](#expected.object.monadic-21.sentence-1)
[22](#expected.object.monadic-22)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L9265)
*Constraints*: is_constructible_v<E, decltype(std::move(error()))> is true[.](#expected.object.monadic-22.sentence-1)
[23](#expected.object.monadic-23)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L9269)
*Mandates*: U is a valid value type for expected[.](#expected.object.monadic-23.sentence-1)
If is_void_v<U> isfalse, the declarationU u(invoke(std::forward<F>(f), std::move(*val*))); is well-formed[.](#expected.object.monadic-23.sentence-2)
[24](#expected.object.monadic-24)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L9278)
*Effects*:
- [(24.1)](#expected.object.monadic-24.1)
If has_value() is false, returnsexpected<U, E>(unexpect, std::move(error()))[.](#expected.object.monadic-24.1.sentence-1)
- [(24.2)](#expected.object.monadic-24.2)
Otherwise, if is_void_v<U> is false, returns anexpected<U, E> object whose *has_val* member is true and *val* member is direct-non-list-initialized withinvoke(std::forward<F>(f), std::move(*val*))[.](#expected.object.monadic-24.2.sentence-1)
- [(24.3)](#expected.object.monadic-24.3)
Otherwise, evaluates invoke(std::forward<F>(f), std::move(*val*)) and
then returns expected<U, E>()[.](#expected.object.monadic-24.3.sentence-1)
[🔗](#lib:transform_error,expected)
`template<class F> constexpr auto transform_error(F&& f) &;
template<class F> constexpr auto transform_error(F&& f) const &;
`
[25](#expected.object.monadic-25)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L9302)
Let G be remove_cv_t<invoke_result_t<F, decltype(error())>>[.](#expected.object.monadic-25.sentence-1)
[26](#expected.object.monadic-26)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L9305)
*Constraints*: is_constructible_v<T, decltype((*val*))> is true[.](#expected.object.monadic-26.sentence-1)
[27](#expected.object.monadic-27)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L9309)
*Mandates*: G is a valid template argument
for unexpected ([[expected.un.general]](expected.un.general "22.8.3.1General")) and the declarationG g(invoke(std::forward<F>(f), error())); is well-formed[.](#expected.object.monadic-27.sentence-1)
[28](#expected.object.monadic-28)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L9318)
*Returns*: If has_value() is true,expected<T, G>(in_place, *val*); otherwise, an expected<T, G> object whose *has_val* member is false and *unex* member
is direct-non-list-initialized with invoke(std::forward<F>(f), error())[.](#expected.object.monadic-28.sentence-1)
[🔗](#lib:transform_error,expected_)
`template<class F> constexpr auto transform_error(F&& f) &&;
template<class F> constexpr auto transform_error(F&& f) const &&;
`
[29](#expected.object.monadic-29)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L9333)
Let G beremove_cv_t<invoke_result_t<F, decltype(std::move(error()))>>[.](#expected.object.monadic-29.sentence-1)
[30](#expected.object.monadic-30)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L9337)
*Constraints*: is_constructible_v<T, decltype(std::move(*val*))> is true[.](#expected.object.monadic-30.sentence-1)
[31](#expected.object.monadic-31)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L9341)
*Mandates*: G is a valid template argument
for unexpected ([[expected.un.general]](expected.un.general "22.8.3.1General")) and the declarationG g(invoke(std::forward<F>(f), std::move(error()))); is well-formed[.](#expected.object.monadic-31.sentence-1)
[32](#expected.object.monadic-32)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L9350)
*Returns*: If has_value() is true,expected<T, G>(in_place, std::move(*val*)); otherwise, anexpected<T, G> object whose *has_val* member is false and *unex* member is direct-non-list-initialized withinvoke(std::forward<F>(f), std::move(error()))[.](#expected.object.monadic-32.sentence-1)
#### [22.8.6.8](#expected.object.eq) Equality operators [[expected.object.eq]](expected.object.eq)
[🔗](#lib:operator==,expected)
`template<class T2, class E2> requires (!is_void_v<T2>)
friend constexpr bool operator==(const expected& x, const expected<T2, E2>& y);
`
[1](#expected.object.eq-1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L9368)
*Constraints*: The expressions *x == *y and x.error() == y.error() are well-formed and their results are convertible to bool[.](#expected.object.eq-1.sentence-1)
[2](#expected.object.eq-2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L9373)
*Returns*: If x.has_value() does not equal y.has_value(), false;
otherwise if x.has_value() is true, *x == *y;
otherwise x.error() == y.error()[.](#expected.object.eq-2.sentence-1)
[🔗](#lib:operator==,expected_)
`template<class T2> friend constexpr bool operator==(const expected& x, const T2& v);
`
[3](#expected.object.eq-3)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L9386)
*Constraints*: T2 is not a specialization of expected[.](#expected.object.eq-3.sentence-1)
The expression *x == v is well-formed and
its result is convertible to bool[.](#expected.object.eq-3.sentence-2)
[*Note [1](#expected.object.eq-note-1)*:
T need not be [*Cpp17EqualityComparable*](utility.arg.requirements#:Cpp17EqualityComparable "16.4.4.2Template argument requirements[utility.arg.requirements]")[.](#expected.object.eq-3.sentence-3)
— *end note*]
[4](#expected.object.eq-4)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L9395)
*Returns*: x.has_value() && static_cast<bool>(*x == v)[.](#expected.object.eq-4.sentence-1)
[🔗](#lib:operator==,expected__)
`template<class E2> friend constexpr bool operator==(const expected& x, const unexpected<E2>& e);
`
[5](#expected.object.eq-5)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L9406)
*Constraints*: The expression x.error() == e.error() is well-formed and
its result is convertible to bool[.](#expected.object.eq-5.sentence-1)
[6](#expected.object.eq-6)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L9411)
*Returns*: !x.has_value() && static_cast<bool>(x.error() == e.error())[.](#expected.object.eq-6.sentence-1)