[expected.void] # 22 General utilities library [[utilities]](./#utilities) ## 22.8 Expected objects [[expected]](expected#void) ### 22.8.7 Partial specialization of expected for void types [expected.void] #### [22.8.7.1](#general) General [[expected.void.general]](expected.void.general) template requires is_void_vclass expected {public:using [value_type](#lib:expected%3cvoid%3e,value_type "22.8.7.1 General [expected.void.general]") = T; using [error_type](#lib:expected%3cvoid%3e,error_type "22.8.7.1 General [expected.void.general]") = E; using [unexpected_type](#lib:expected%3cvoid%3e,unexpected_type "22.8.7.1 General [expected.void.general]") = unexpected; templateusing [rebind](#lib:expected%3cvoid%3e,rebind "22.8.7.1 General [expected.void.general]") = expected; // [[expected.void.cons]](#cons "22.8.7.2 Constructors"), constructorsconstexpr expected() noexcept; constexpr expected(const expected&); constexpr expected(expected&&) noexcept(*see below*); templateconstexpr explicit(*see below*) expected(const expected&); templateconstexpr explicit(*see below*) expected(expected&&); templateconstexpr explicit(*see below*) expected(const unexpected&); templateconstexpr explicit(*see below*) expected(unexpected&&); constexpr explicit expected(in_place_t) noexcept; templateconstexpr explicit expected(unexpect_t, Args&&...); templateconstexpr explicit expected(unexpect_t, initializer_list, Args&&...); // [[expected.void.dtor]](#dtor "22.8.7.3 Destructor"), destructorconstexpr ~expected(); // [[expected.void.assign]](#assign "22.8.7.4 Assignment"), assignmentconstexpr expected& operator=(const expected&); constexpr expected& operator=(expected&&) noexcept(*see below*); templateconstexpr expected& operator=(const unexpected&); templateconstexpr expected& operator=(unexpected&&); constexpr void emplace() noexcept; // [[expected.void.swap]](#swap "22.8.7.5 Swap"), swapconstexpr void swap(expected&) noexcept(*see below*); friend constexpr void swap(expected& x, expected& y) noexcept(noexcept(x.swap(y))); // [[expected.void.obs]](#obs "22.8.7.6 Observers"), observersconstexpr explicit operator bool() const noexcept; constexpr bool has_value() const noexcept; constexpr void operator*() const noexcept; constexpr void value() const &; // freestanding-deletedconstexpr void value() &&; // freestanding-deletedconstexpr const E& error() const & noexcept; constexpr E& error() & noexcept; constexpr const E&& error() const && noexcept; constexpr E&& error() && noexcept; template constexpr E error_or(G&&) const &; template constexpr E error_or(G&&) &&; // [[expected.void.monadic]](#monadic "22.8.7.7 Monadic operations"), monadic operationstemplate constexpr auto and_then(F&& f) &; template constexpr auto and_then(F&& f) &&; template constexpr auto and_then(F&& f) const &; template constexpr auto and_then(F&& f) const &&; template constexpr auto or_else(F&& f) &; template constexpr auto or_else(F&& f) &&; template constexpr auto or_else(F&& f) const &; template constexpr auto or_else(F&& f) const &&; template constexpr auto transform(F&& f) &; template constexpr auto transform(F&& f) &&; template constexpr auto transform(F&& f) const &; template constexpr auto transform(F&& f) const &&; template constexpr auto transform_error(F&& f) &; template constexpr auto transform_error(F&& f) &&; template constexpr auto transform_error(F&& f) const &; template constexpr auto transform_error(F&& f) const &&; // [[expected.void.eq]](#eq "22.8.7.8 Equality operators"), equality operatorstemplate requires is_void_vfriend constexpr bool operator==(const expected& x, const expected& y); templatefriend constexpr bool operator==(const expected&, const unexpected&); private:bool *has_val*; // *exposition only*union { E *unex*; // *exposition only*};}; [1](#general-1) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L9513) Any object of type expected either represents a value of type T, or contains a value of type E nested within ([[intro.object]](intro.object "6.8.2 Object model")) it[.](#general-1.sentence-1) Member *has_val* indicates whether the expected object represents a value of type T[.](#general-1.sentence-2) [2](#general-2) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L9521) A program that instantiates the definition of the template expected with a type for the E parameter that is not a valid template argument for unexpected is ill-formed[.](#general-2.sentence-1) [3](#general-3) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L9527) E shall meet the requirements of[*Cpp17Destructible*](utility.arg.requirements#:Cpp17Destructible "16.4.4.2 Template argument requirements [utility.arg.requirements]") (Table [35](utility.arg.requirements#tab:cpp17.destructible "Table 35: Cpp17Destructible requirements"))[.](#general-3.sentence-1) #### [22.8.7.2](#cons) Constructors [[expected.void.cons]](expected.void.cons) [🔗](#lib:expected%3cvoid%3e,constructor) `constexpr expected() noexcept; ` [1](#cons-1) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L9539) *Postconditions*: has_value() is true[.](#cons-1.sentence-1) [🔗](#lib:expected%3cvoid%3e,constructor_) `constexpr expected(const expected& rhs); ` [2](#cons-2) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L9550) *Effects*: If rhs.has_value() is false, direct-non-list-initializes *unex* with rhs.error()[.](#cons-2.sentence-1) [3](#cons-3) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L9555) *Postconditions*: rhs.has_value() == this->has_value()[.](#cons-3.sentence-1) [4](#cons-4) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L9559) *Throws*: Any exception thrown by the initialization of *unex*[.](#cons-4.sentence-1) [5](#cons-5) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L9563) *Remarks*: This constructor is defined as deleted unless is_copy_constructible_v is true[.](#cons-5.sentence-1) [6](#cons-6) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L9568) This constructor is trivial if is_trivially_copy_constructible_v is true[.](#cons-6.sentence-1) [🔗](#lib:expected%3cvoid%3e,constructor__) `constexpr expected(expected&& rhs) noexcept(is_nothrow_move_constructible_v); ` [7](#cons-7) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L9579) *Constraints*: is_move_constructible_v is true[.](#cons-7.sentence-1) [8](#cons-8) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L9583) *Effects*: If rhs.has_value() is false, direct-non-list-initializes *unex* with std​::​move(rhs.error())[.](#cons-8.sentence-1) [9](#cons-9) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L9588) *Postconditions*: rhs.has_value() is unchanged;rhs.has_value() == this->has_value() is true[.](#cons-9.sentence-1) [10](#cons-10) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L9593) *Throws*: Any exception thrown by the initialization of *unex*[.](#cons-10.sentence-1) [11](#cons-11) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L9597) *Remarks*: This constructor is trivial if is_trivially_move_constructible_v is true[.](#cons-11.sentence-1) [🔗](#lib:expected%3cvoid%3e,constructor___) `template constexpr explicit(!is_convertible_v) expected(const expected& rhs); template constexpr explicit(!is_convertible_v) expected(expected&& rhs); ` [12](#cons-12) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L9612) Let GF be const G& for the first overload andG for the second overload[.](#cons-12.sentence-1) [13](#cons-13) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L9616) *Constraints*: - [(13.1)](#cons-13.1) is_void_v is true; and - [(13.2)](#cons-13.2) is_constructible_v is true; and - [(13.3)](#cons-13.3) is_constructible_v, expected&> is false; and - [(13.4)](#cons-13.4) is_constructible_v, expected> is false; and - [(13.5)](#cons-13.5) is_constructible_v, const expected&> is false; and - [(13.6)](#cons-13.6) is_constructible_v, const expected> is false[.](#cons-13.sentence-1) [14](#cons-14) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L9637) *Effects*: If rhs.has_value() is false, direct-non-list-initializes *unex* with std​::​forward(rhs.error())[.](#cons-14.sentence-1) [15](#cons-15) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L9643) *Postconditions*: rhs.has_value() is unchanged;rhs.has_value() == this->has_value() is true[.](#cons-15.sentence-1) [16](#cons-16) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L9648) *Throws*: Any exception thrown by the initialization of *unex*[.](#cons-16.sentence-1) [🔗](#lib:expected%3cvoid%3e,constructor____) `template constexpr explicit(!is_convertible_v) expected(const unexpected& e); template constexpr explicit(!is_convertible_v) expected(unexpected&& e); ` [17](#cons-17) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L9662) Let GF be const G& for the first overload andG for the second overload[.](#cons-17.sentence-1) [18](#cons-18) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L9666) *Constraints*: is_constructible_v is true[.](#cons-18.sentence-1) [19](#cons-19) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L9670) *Effects*: Direct-non-list-initializes *unex* with std​::​forward(e.error())[.](#cons-19.sentence-1) [20](#cons-20) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L9675) *Postconditions*: has_value() is false[.](#cons-20.sentence-1) [21](#cons-21) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L9679) *Throws*: Any exception thrown by the initialization of *unex*[.](#cons-21.sentence-1) [🔗](#lib:expected%3cvoid%3e,constructor_____) `constexpr explicit expected(in_place_t) noexcept; ` [22](#cons-22) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L9690) *Postconditions*: has_value() is true[.](#cons-22.sentence-1) [🔗](#lib:expected%3cvoid%3e,constructor______) `template constexpr explicit expected(unexpect_t, Args&&... args); ` [23](#cons-23) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L9702) *Constraints*: is_constructible_v is true[.](#cons-23.sentence-1) [24](#cons-24) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L9706) *Effects*: Direct-non-list-initializes *unex* with std​::​forward(args)...[.](#cons-24.sentence-1) [25](#cons-25) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L9711) *Postconditions*: has_value() is false[.](#cons-25.sentence-1) [26](#cons-26) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L9715) *Throws*: Any exception thrown by the initialization of *unex*[.](#cons-26.sentence-1) [🔗](#lib:expected%3cvoid%3e,constructor_______) `template constexpr explicit expected(unexpect_t, initializer_list il, Args&&... args); ` [27](#cons-27) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L9727) *Constraints*: is_constructible_v&, Args...> is true[.](#cons-27.sentence-1) [28](#cons-28) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L9731) *Effects*: Direct-non-list-initializes *unex* with il, std​::​forward(args)...[.](#cons-28.sentence-1) [29](#cons-29) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L9736) *Postconditions*: has_value() is false[.](#cons-29.sentence-1) [30](#cons-30) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L9740) *Throws*: Any exception thrown by the initialization of *unex*[.](#cons-30.sentence-1) #### [22.8.7.3](#dtor) Destructor [[expected.void.dtor]](expected.void.dtor) [🔗](#lib:expected%3cvoid%3e,destructor) `constexpr ~expected(); ` [1](#dtor-1) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L9753) *Effects*: If has_value() is false, destroys *unex*[.](#dtor-1.sentence-1) [2](#dtor-2) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L9757) *Remarks*: If is_trivially_destructible_v is true, then this destructor is a trivial destructor[.](#dtor-2.sentence-1) #### [22.8.7.4](#assign) Assignment [[expected.void.assign]](expected.void.assign) [🔗](#lib:operator=,expected%3cvoid%3e) `constexpr expected& operator=(const expected& rhs); ` [1](#assign-1) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L9771) *Effects*: - [(1.1)](#assign-1.1) If this->has_value() && rhs.has_value() is true, no effects[.](#assign-1.1.sentence-1) - [(1.2)](#assign-1.2) Otherwise, if this->has_value() is true, equivalent to: construct_at(addressof(*unex*), rhs.*unex*); *has_val* = false; - [(1.3)](#assign-1.3) Otherwise, if rhs.has_value() is true, destroys *unex* and sets *has_val* to true[.](#assign-1.3.sentence-1) - [(1.4)](#assign-1.4) Otherwise, equivalent to *unex* = rhs.error()[.](#assign-1.4.sentence-1) [2](#assign-2) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L9786) *Returns*: *this[.](#assign-2.sentence-1) [3](#assign-3) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L9790) *Remarks*: This operator is defined as deleted unlessis_copy_assignable_v is true andis_copy_constructible_v is true[.](#assign-3.sentence-1) [🔗](#lib:operator=,expected%3cvoid%3e_) `constexpr expected& operator=(expected&& rhs) noexcept(see below); ` [4](#assign-4) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L9803) *Constraints*: is_move_constructible_v is true andis_move_assignable_v is true[.](#assign-4.sentence-1) [5](#assign-5) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L9808) *Effects*: - [(5.1)](#assign-5.1) If this->has_value() && rhs.has_value() is true, no effects[.](#assign-5.1.sentence-1) - [(5.2)](#assign-5.2) Otherwise, if this->has_value() is true, equivalent to:construct_at(addressof(*unex*), std::move(rhs.*unex*));*has_val* = false; - [(5.3)](#assign-5.3) Otherwise, if rhs.has_value() is true, destroys *unex* and sets *has_val* to true[.](#assign-5.3.sentence-1) - [(5.4)](#assign-5.4) Otherwise, equivalent to *unex* = std​::​move(rhs.error())[.](#assign-5.4.sentence-1) [6](#assign-6) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L9826) *Returns*: *this[.](#assign-6.sentence-1) [7](#assign-7) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L9830) *Remarks*: The exception specification is equivalent tois_nothrow_move_constructible_v && is_nothrow_move_assignable_v[.](#assign-7.sentence-1) [🔗](#lib:operator=,expected%3cvoid%3e__) `template constexpr expected& operator=(const unexpected& e); template constexpr expected& operator=(unexpected&& e); ` [8](#assign-8) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L9845) Let GF be const G& for the first overload andG for the second overload[.](#assign-8.sentence-1) [9](#assign-9) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L9849) *Constraints*: is_constructible_v is true andis_assignable_v is true[.](#assign-9.sentence-1) [10](#assign-10) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L9854) *Effects*: - [(10.1)](#assign-10.1) If has_value() is true, equivalent to:construct_at(addressof(*unex*), std::forward(e.error()));*has_val* = false; - [(10.2)](#assign-10.2) Otherwise, equivalent to:*unex* = std​::​forward(e.error()); [11](#assign-11) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L9868) *Returns*: *this[.](#assign-11.sentence-1) [🔗](#lib:emplace,expected%3cvoid%3e) `constexpr void emplace() noexcept; ` [12](#assign-12) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L9879) *Effects*: If has_value() is false, destroys *unex* and sets *has_val* to true[.](#assign-12.sentence-1) #### [22.8.7.5](#swap) Swap [[expected.void.swap]](expected.void.swap) [🔗](#lib:swap,expected%3cvoid%3e) `constexpr void swap(expected& rhs) noexcept(see below); ` [1](#swap-1) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L9893) *Constraints*: is_swappable_v is true andis_move_constructible_v is true[.](#swap-1.sentence-1) [2](#swap-2) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L9898) *Effects*: See Table [73](#tab:expected.void.swap "Table 73: swap(expected&) effects")[.](#swap-2.sentence-1) Table [73](#tab:expected.void.swap) — swap(expected&) effects [[tab:expected.void.swap]](./tab:expected.void.swap) | [🔗](#tab:expected.void.swap-row-1) | **this->has_value()** | **!this->has_value()** | | --- | --- | --- | | [🔗](#tab:expected.void.swap-row-2)
**rhs.has_value()** | no effects | calls rhs.swap(*this) | | [🔗](#tab:expected.void.swap-row-3)
**!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:construct_at(addressof(*unex*), std::move(rhs.*unex*)); destroy_at(addressof(rhs.*unex*));*has_val* = false; rhs.*has_val* = true; [3](#swap-3) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L9923) *Throws*: Any exception thrown by the expressions in the *Effects*[.](#swap-3.sentence-1) [4](#swap-4) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L9927) *Remarks*: The exception specification is equivalent tois_nothrow_move_constructible_v && is_nothrow_swappable_v[.](#swap-4.sentence-1) [🔗](#lib:swap,expected%3cvoid%3e_) `friend constexpr void swap(expected& x, expected& y) noexcept(noexcept(x.swap(y))); ` [5](#swap-5) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L9939) *Effects*: Equivalent to x.swap(y)[.](#swap-5.sentence-1) #### [22.8.7.6](#obs) Observers [[expected.void.obs]](expected.void.obs) [🔗](#lib:operator_bool,expected%3cvoid%3e) `constexpr explicit operator bool() const noexcept; constexpr bool has_value() const noexcept; ` [1](#obs-1) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L9954) *Returns*: *has_val*[.](#obs-1.sentence-1) [🔗](#lib:operator*,expected%3cvoid%3e) `constexpr void operator*() const noexcept; ` [2](#obs-2) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L9965) *Hardened preconditions*: has_value() is true[.](#obs-2.sentence-1) [🔗](#lib:value,expected%3cvoid%3e) `constexpr void value() const &; ` [3](#obs-3) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L9976) *Mandates*: is_copy_constructible_v is true[.](#obs-3.sentence-1) [4](#obs-4) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L9980) *Throws*: bad_expected_access(error()) if has_value() is false[.](#obs-4.sentence-1) [🔗](#lib:value,expected%3cvoid%3e_) `constexpr void value() &&; ` [5](#obs-5) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L9991) *Mandates*: is_copy_constructible_v is true andis_move_constructible_v is true[.](#obs-5.sentence-1) [6](#obs-6) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L9996) *Throws*: bad_expected_access(std​::​move(error())) if has_value() is false[.](#obs-6.sentence-1) [🔗](#lib:error,expected%3cvoid%3e) `constexpr const E& error() const & noexcept; constexpr E& error() & noexcept; ` [7](#obs-7) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L10009) *Hardened preconditions*: has_value() is false[.](#obs-7.sentence-1) [8](#obs-8) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L10013) *Returns*: *unex*[.](#obs-8.sentence-1) [🔗](#lib:error,expected%3cvoid%3e_) `constexpr E&& error() && noexcept; constexpr const E&& error() const && noexcept; ` [9](#obs-9) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L10025) *Hardened preconditions*: has_value() is false[.](#obs-9.sentence-1) [10](#obs-10) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L10029) *Returns*: std​::​move(*unex*)[.](#obs-10.sentence-1) [🔗](#lib:error_or,expected%3cvoid%3e) `template constexpr E error_or(G&& e) const &; ` [11](#obs-11) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L10040) *Mandates*: is_copy_constructible_v is true andis_convertible_v is true[.](#obs-11.sentence-1) [12](#obs-12) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L10045) *Returns*: std​::​forward(e) if has_value() is true,error() otherwise[.](#obs-12.sentence-1) [🔗](#lib:error_or,expected%3cvoid%3e_) `template constexpr E error_or(G&& e) &&; ` [13](#obs-13) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L10057) *Mandates*: is_move_constructible_v is true andis_convertible_v is true[.](#obs-13.sentence-1) [14](#obs-14) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L10062) *Returns*: std​::​forward(e) if has_value() is true,std​::​move(error()) otherwise[.](#obs-14.sentence-1) #### [22.8.7.7](#monadic) Monadic operations [[expected.void.monadic]](expected.void.monadic) [🔗](#lib:and_then,expected%3cvoid%3e) `template constexpr auto and_then(F&& f) &; template constexpr auto and_then(F&& f) const &; ` [1](#monadic-1) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L10077) Let U be remove_cvref_t>[.](#monadic-1.sentence-1) [2](#monadic-2) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L10080) *Constraints*: is_constructible_v> is true[.](#monadic-2.sentence-1) [3](#monadic-3) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L10084) *Mandates*: U is a specialization of expected andis_same_v is true[.](#monadic-3.sentence-1) [4](#monadic-4) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L10089) *Effects*: Equivalent to:if (has_value())return invoke(std::forward(f));elsereturn U(unexpect, error()); [🔗](#lib:and_then,expected%3cvoid%3e_) `template constexpr auto and_then(F&& f) &&; template constexpr auto and_then(F&& f) const &&; ` [5](#monadic-5) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L10107) Let U be remove_cvref_t>[.](#monadic-5.sentence-1) [6](#monadic-6) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L10110) *Constraints*: is_constructible_v is true[.](#monadic-6.sentence-1) [7](#monadic-7) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L10114) *Mandates*: U is a specialization of expected andis_same_v is true[.](#monadic-7.sentence-1) [8](#monadic-8) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L10119) *Effects*: Equivalent to:if (has_value())return invoke(std::forward(f));elsereturn U(unexpect, std::move(error())); [🔗](#lib:or_else,expected%3cvoid%3e) `template constexpr auto or_else(F&& f) &; template constexpr auto or_else(F&& f) const &; ` [9](#monadic-9) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L10137) Let G be remove_cvref_t>[.](#monadic-9.sentence-1) [10](#monadic-10) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L10140) *Mandates*: G is a specialization of expected andis_same_v is true[.](#monadic-10.sentence-1) [11](#monadic-11) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L10145) *Effects*: Equivalent to:if (has_value())return G();elsereturn invoke(std::forward(f), error()); [🔗](#lib:or_else,expected%3cvoid%3e_) `template constexpr auto or_else(F&& f) &&; template constexpr auto or_else(F&& f) const &&; ` [12](#monadic-12) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L10163) Let G beremove_cvref_t>[.](#monadic-12.sentence-1) [13](#monadic-13) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L10167) *Mandates*: G is a specialization of expected andis_same_v is true[.](#monadic-13.sentence-1) [14](#monadic-14) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L10172) *Effects*: Equivalent to:if (has_value())return G();elsereturn invoke(std::forward(f), std::move(error())); [🔗](#lib:transform,expected%3cvoid%3e) `template constexpr auto transform(F&& f) &; template constexpr auto transform(F&& f) const &; ` [15](#monadic-15) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L10190) Let U be remove_cv_t>[.](#monadic-15.sentence-1) [16](#monadic-16) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L10193) *Constraints*: is_constructible_v is true[.](#monadic-16.sentence-1) [17](#monadic-17) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L10197) *Mandates*: U is a valid value type for expected[.](#monadic-17.sentence-1) If is_void_v isfalse, the declarationU u(invoke(std::forward(f))); is well-formed[.](#monadic-17.sentence-2) [18](#monadic-18) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L10206) *Effects*: - [(18.1)](#monadic-18.1) If has_value() is false, returnsexpected(unexpect, error())[.](#monadic-18.1.sentence-1) - [(18.2)](#monadic-18.2) Otherwise, if is_void_v is false, returns anexpected object whose *has_val* member is true and*val* member is direct-non-list-initialized withinvoke(std​::​forward(f))[.](#monadic-18.2.sentence-1) - [(18.3)](#monadic-18.3) Otherwise, evaluates invoke(std​::​forward(f)) and then returnsexpected()[.](#monadic-18.3.sentence-1) [🔗](#lib:transform,expected%3cvoid%3e_) `template constexpr auto transform(F&& f) &&; template constexpr auto transform(F&& f) const &&; ` [19](#monadic-19) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L10230) Let U be remove_cv_t>[.](#monadic-19.sentence-1) [20](#monadic-20) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L10233) *Constraints*: is_constructible_v is true[.](#monadic-20.sentence-1) [21](#monadic-21) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L10237) *Mandates*: U is a valid value type for expected[.](#monadic-21.sentence-1) If is_void_v isfalse, the declarationU u(invoke(std::forward(f))); is well-formed[.](#monadic-21.sentence-2) [22](#monadic-22) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L10246) *Effects*: - [(22.1)](#monadic-22.1) If has_value() is false, returnsexpected(unexpect, std​::​move(error()))[.](#monadic-22.1.sentence-1) - [(22.2)](#monadic-22.2) Otherwise, if is_void_v is false, returns anexpected object whose *has_val* member is true and*val* member is direct-non-list-initialized withinvoke(std​::​forward(f))[.](#monadic-22.2.sentence-1) - [(22.3)](#monadic-22.3) Otherwise, evaluates invoke(std​::​forward(f)) and then returnsexpected()[.](#monadic-22.3.sentence-1) [🔗](#lib:transform_error,expected%3cvoid%3e) `template constexpr auto transform_error(F&& f) &; template constexpr auto transform_error(F&& f) const &; ` [23](#monadic-23) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L10270) Let G be remove_cv_t>[.](#monadic-23.sentence-1) [24](#monadic-24) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L10273) *Mandates*: G is a valid template argument for unexpected ([[expected.un.general]](expected.un.general "22.8.3.1 General")) and the declarationG g(invoke(std::forward(f), error())); is well-formed[.](#monadic-24.sentence-1) [25](#monadic-25) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L10282) *Returns*: If has_value() is true, expected(); otherwise, anexpected object whose *has_val* member is false and *unex* member is direct-non-list-initialized withinvoke(std​::​forward(f), error())[.](#monadic-25.sentence-1) [🔗](#lib:transform_error,expected%3cvoid%3e_) `template constexpr auto transform_error(F&& f) &&; template constexpr auto transform_error(F&& f) const &&; ` [26](#monadic-26) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L10297) Let G beremove_cv_t>[.](#monadic-26.sentence-1) [27](#monadic-27) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L10301) *Mandates*: G is a valid template argument for unexpected ([[expected.un.general]](expected.un.general "22.8.3.1 General")) and the declarationG g(invoke(std::forward(f), std::move(error()))); is well-formed[.](#monadic-27.sentence-1) [28](#monadic-28) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L10310) *Returns*: If has_value() is true, expected(); otherwise, anexpected object whose *has_val* member is false and *unex* member is direct-non-list-initialized withinvoke(std​::​forward(f), std​::​move(error()))[.](#monadic-28.sentence-1) #### [22.8.7.8](#eq) Equality operators [[expected.void.eq]](expected.void.eq) [🔗](#lib:operator==,expected%3cvoid%3e) `template requires is_void_v friend constexpr bool operator==(const expected& x, const expected& y); ` [1](#eq-1) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L10327) *Constraints*: The expression x.error() == y.error() is well-formed and its result is convertible to bool[.](#eq-1.sentence-1) [2](#eq-2) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L10332) *Returns*: If x.has_value() does not equal y.has_value(), false; otherwise x.has_value() || static_cast(x.error() == y.error())[.](#eq-2.sentence-1) [🔗](#lib:operator==,expected%3cvoid%3e_) `template friend constexpr bool operator==(const expected& x, const unexpected& e); ` [3](#eq-3) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L10345) *Constraints*: The expression x.error() == e.error() is well-formed and its result is convertible to bool[.](#eq-3.sentence-1) [4](#eq-4) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L10350) *Returns*: !x.has_value() && static_cast(x.error() == e.error())[.](#eq-4.sentence-1)