[expected.object.monadic]

# 22 General utilities library [[utilities]](./#utilities)

## 22.8 Expected objects [[expected]](expected#object.monadic)

### 22.8.6 Class template expected [[expected.expected]](expected.expected#expected.object.monadic)

#### 22.8.6.7 Monadic operations [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](#1)

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

Let U be remove_cvref_t<invoke_result_t<F, decltype((*val*))>>[.](#1.sentence-1)

[2](#2)

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

*Constraints*: is_constructible_v<E, decltype(error())> is true[.](#2.sentence-1)

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

[4](#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](#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*))>>[.](#5.sentence-1)

[6](#6)

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

*Constraints*: is_constructible_v<E, decltype(std​::​move(error()))> is true[.](#6.sentence-1)

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

[8](#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](#9)

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

Let G be remove_cvref_t<invoke_result_t<F, decltype(error())>>[.](#9.sentence-1)

[10](#10)

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

*Constraints*: is_constructible_v<T, decltype((*val*))> is true[.](#10.sentence-1)

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

[12](#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](#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()))>>[.](#13.sentence-1)

[14](#14)

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

*Constraints*: is_constructible_v<T, decltype(std​::​move(*val*))> is true[.](#14.sentence-1)

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

[16](#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](#17)

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

Let U beremove_cv_t<invoke_result_t<F, decltype((*val*))>>[.](#17.sentence-1)

[18](#18)

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

*Constraints*: is_constructible_v<E, decltype(error())> is true[.](#18.sentence-1)

[19](#19)

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

*Mandates*: U is a valid value type for expected[.](#19.sentence-1)

If is_void_v<U> is false,
the declarationU u(invoke(std::forward<F>(f), *val*)); is well-formed[.](#19.sentence-2)

[20](#20)

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

*Effects*: 

- [(20.1)](#20.1)

  If has_value() is false, returnsexpected<U, E>(unexpect, error())[.](#20.1.sentence-1)

- [(20.2)](#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*)[.](#20.2.sentence-1)

- [(20.3)](#20.3)

  Otherwise, evaluates invoke(std​::​forward<F>(f), *val*) and then
returns expected<U, E>()[.](#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](#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*))>>[.](#21.sentence-1)

[22](#22)

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

*Constraints*: is_constructible_v<E, decltype(std​::​move(error()))> is true[.](#22.sentence-1)

[23](#23)

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

*Mandates*: U is a valid value type for expected[.](#23.sentence-1)

If is_void_v<U> isfalse, the declarationU u(invoke(std::forward<F>(f), std::move(*val*))); is well-formed[.](#23.sentence-2)

[24](#24)

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

*Effects*: 

- [(24.1)](#24.1)

  If has_value() is false, returnsexpected<U, E>(unexpect, std​::​move(error()))[.](#24.1.sentence-1)

- [(24.2)](#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*))[.](#24.2.sentence-1)

- [(24.3)](#24.3)

  Otherwise, evaluates invoke(std​::​forward<F>(f), std​::​move(*val*)) and
then returns expected<U, E>()[.](#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](#25)

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

Let G be remove_cv_t<invoke_result_t<F, decltype(error())>>[.](#25.sentence-1)

[26](#26)

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

*Constraints*: is_constructible_v<T, decltype((*val*))> is true[.](#26.sentence-1)

[27](#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.1 General")) and the declarationG g(invoke(std::forward<F>(f), error())); is well-formed[.](#27.sentence-1)

[28](#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())[.](#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](#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()))>>[.](#29.sentence-1)

[30](#30)

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

*Constraints*: is_constructible_v<T, decltype(std​::​move(*val*))> is true[.](#30.sentence-1)

[31](#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.1 General")) and the declarationG g(invoke(std::forward<F>(f), std::move(error()))); is well-formed[.](#31.sentence-1)

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