[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<class T, class E> requires is_void_v<T>class expected<T, E> {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<E>; template<class U>using [rebind](#lib:expected%3cvoid%3e,rebind "22.8.7.1 General [expected.void.general]") = expected<U, error_type>; // [[expected.void.cons]](#cons "22.8.7.2 Constructors"), constructorsconstexpr expected() noexcept; 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 G>constexpr explicit(*see below*) expected(const unexpected<G>&); template<class G>constexpr explicit(*see below*) expected(unexpected<G>&&); constexpr explicit expected(in_place_t) noexcept; template<class... Args>constexpr explicit expected(unexpect_t, Args&&...); template<class U, class... Args>constexpr explicit expected(unexpect_t, initializer_list<U>, 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*); template<class G>constexpr expected& operator=(const unexpected<G>&); template<class G>constexpr expected& operator=(unexpected<G>&&); 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<class G = E> constexpr E error_or(G&&) const &; template<class G = E> constexpr E error_or(G&&) &&; // [[expected.void.monadic]](#monadic "22.8.7.7 Monadic 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.void.eq]](#eq "22.8.7.8 Equality 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 E2>friend constexpr bool operator==(const expected&, const unexpected<E2>&);

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<T, E> 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<T, E> 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<T, E> 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<E> 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<E> is true[.](#cons-6.sentence-1)

[ð](#lib:expected%3cvoid%3e,constructor__)

`constexpr expected(expected&& rhs) noexcept(is_nothrow_move_constructible_v<E>);
`

[7](#cons-7)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L9579)

*Constraints*: is_move_constructible_v<E> 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<E> is true[.](#cons-11.sentence-1)

[ð](#lib:expected%3cvoid%3e,constructor___)

`template<class U, class G>
  constexpr explicit(!is_convertible_v<const G&, E>) expected(const expected<U, G>& rhs);
template<class U, class G>
  constexpr explicit(!is_convertible_v<G, E>) expected(expected<U, G>&& 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<U> is true; and

- [(13.2)](#cons-13.2)

is_constructible_v<E, GF> is true; and

- [(13.3)](#cons-13.3)

is_constructible_v<unexpected<E>, expected<U, G>&> is false; and

- [(13.4)](#cons-13.4)

is_constructible_v<unexpected<E>, expected<U, G>> is false; and

- [(13.5)](#cons-13.5)

is_constructible_v<unexpected<E>, const expected<U, G>&> is false; and

- [(13.6)](#cons-13.6)

is_constructible_v<unexpected<E>, const expected<U, G>> 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<GF>(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<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);
`

[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<E, GF> 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<GF>(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<class... Args>
  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<E, Args...> 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>(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<class U, class... Args>
  constexpr explicit expected(unexpect_t, initializer_list<U> il, Args&&... args);
`

[27](#cons-27)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L9727)

*Constraints*: is_constructible_v<E, initializer_list<U>&, 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>(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<E> 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<E> is true andis_copy_constructible_v<E> 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<E> is true andis_move_assignable_v<E> 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<E> && is_nothrow_move_assignable_v<E>[.](#assign-7.sentence-1)

[ð](#lib:operator=,expected%3cvoid%3e__)

`template<class G>
  constexpr expected& operator=(const unexpected<G>& e);
template<class G>
  constexpr expected& operator=(unexpected<G>&& 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<E, GF> is true andis_assignable_v<E&, GF> 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<GF>(e.error()));*has_val* = false;

- [(10.2)](#assign-10.2)

Otherwise, equivalent to:*unex* = std​::​forward<GF>(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<E> is true andis_move_constructible_v<E> 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&amp;) 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)<br>**rhs.has_value()** | no effects | calls rhs.swap(*this) |
| [ð](#tab:expected.void.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: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<E> && is_nothrow_swappable_v<E>[.](#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<E> 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<E> is true andis_move_constructible_v<E> 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<class G = E> 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<E> is true andis_convertible_v<G, E> is true[.](#obs-11.sentence-1)

[12](#obs-12)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L10045)

*Returns*: std​::​forward<G>(e) if has_value() is true,error() otherwise[.](#obs-12.sentence-1)

[ð](#lib:error_or,expected%3cvoid%3e_)

`template<class G = E> 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<E> is true andis_convertible_v<G, E> is true[.](#obs-13.sentence-1)

[14](#obs-14)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L10062)

*Returns*: std​::​forward<G>(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<class F> constexpr auto and_then(F&& f) &;
template<class F> 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<invoke_result_t<F>>[.](#monadic-1.sentence-1)

[2](#monadic-2)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L10080)

*Constraints*: is_constructible_v<E, decltype(error())>> 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<U​::​error_type, E> 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>(f));elsereturn U(unexpect, error());

[ð](#lib:and_then,expected%3cvoid%3e_)

`template<class F> constexpr auto and_then(F&& f) &&;
template<class F> 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<invoke_result_t<F>>[.](#monadic-5.sentence-1)

[6](#monadic-6)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L10110)

*Constraints*: is_constructible_v<E, decltype(std​::​move(error()))> 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<U​::​error_type, E> 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>(f));elsereturn U(unexpect, std::move(error()));

[ð](#lib:or_else,expected%3cvoid%3e)

`template<class F> constexpr auto or_else(F&& f) &;
template<class F> 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<invoke_result_t<F, decltype(error())>>[.](#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<G​::​value_type, T> 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>(f), error());

[ð](#lib:or_else,expected%3cvoid%3e_)

`template<class F> constexpr auto or_else(F&& f) &&;
template<class F> 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<invoke_result_t<F, decltype(std​::​move(error()))>>[.](#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<G​::​value_type, T> 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>(f), std::move(error()));

[ð](#lib:transform,expected%3cvoid%3e)

`template<class F> constexpr auto transform(F&& f) &;
template<class F> 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<invoke_result_t<F>>[.](#monadic-15.sentence-1)

[16](#monadic-16)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L10193)

*Constraints*: is_constructible_v<E, decltype(error())> 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<U> isfalse, the declarationU u(invoke(std::forward<F>(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<U, E>(unexpect, error())[.](#monadic-18.1.sentence-1)

- [(18.2)](#monadic-18.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))[.](#monadic-18.2.sentence-1)

- [(18.3)](#monadic-18.3)

  Otherwise, evaluates invoke(std​::​forward<F>(f)) and then returnsexpected<U, E>()[.](#monadic-18.3.sentence-1)

[ð](#lib:transform,expected%3cvoid%3e_)

`template<class F> constexpr auto transform(F&& f) &&;
template<class F> 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<invoke_result_t<F>>[.](#monadic-19.sentence-1)

[20](#monadic-20)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L10233)

*Constraints*: is_constructible_v<E, decltype(std​::​move(error()))> 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<U> isfalse, the declarationU u(invoke(std::forward<F>(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<U, E>(unexpect, std​::​move(error()))[.](#monadic-22.1.sentence-1)

- [(22.2)](#monadic-22.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))[.](#monadic-22.2.sentence-1)

- [(22.3)](#monadic-22.3)

  Otherwise, evaluates invoke(std​::​forward<F>(f)) and then returnsexpected<U, E>()[.](#monadic-22.3.sentence-1)

[ð](#lib:transform_error,expected%3cvoid%3e)

`template<class F> constexpr auto transform_error(F&& f) &;
template<class F> 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<invoke_result_t<F, decltype(error())>>[.](#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>(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<T, G>(); otherwise, anexpected<T, G> object whose *has_val* member is false and *unex* member is direct-non-list-initialized withinvoke(std​::​forward<F>(f), error())[.](#monadic-25.sentence-1)

[ð](#lib:transform_error,expected%3cvoid%3e_)

`template<class F> constexpr auto transform_error(F&& f) &&;
template<class F> 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<invoke_result_t<F, decltype(std​::​move(error()))>>[.](#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>(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<T, G>(); 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()))[.](#monadic-28.sentence-1)

#### [22.8.7.8](#eq) Equality operators [[expected.void.eq]](expected.void.eq)

[ð](#lib:operator==,expected%3cvoid%3e)

`template<class T2, class E2> requires is_void_v<T2>
  friend constexpr bool operator==(const expected& x, const expected<T2, E2>& 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<bool>(x.error() == y.error())[.](#eq-2.sentence-1)

[ð](#lib:operator==,expected%3cvoid%3e_)

`template<class E2>
  friend constexpr bool operator==(const expected& x, const unexpected<E2>& 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<bool>(x.error() == e.error())[.](#eq-4.sentence-1)
