22 General utilities library [utilities] (original) (raw)

22.8.1 General [expected.general]

Subclause [expected] describes the class template expectedthat represents expected objects.

An expected<T, E> object holds an object of type T or an object of type E and manages the lifetime of the contained objects.

22.8.3 Class template unexpected [expected.unexpected]

22.8.3.1 General [expected.un.general]

Subclause [expected.unexpected] describes the class template unexpectedthat represents unexpected objects stored in expected objects.

namespace std { template<class E> class unexpected { public: constexpr unexpected(const unexpected&) = default;constexpr unexpected(unexpected&&) = default;template<class Err = E> constexpr explicit unexpected(Err&&);template<class... Args> constexpr explicit unexpected(in_place_t, Args&&...);template<class U, class... Args> constexpr explicit unexpected(in_place_t, initializer_list<U>, Args&&...);constexpr unexpected& operator=(const unexpected&) = default;constexpr unexpected& operator=(unexpected&&) = default;constexpr const E& error() const & noexcept;constexpr E& error() & noexcept;constexpr const E&& error() const && noexcept;constexpr E&& error() && noexcept;constexpr void swap(unexpected& other) noexcept(see below);template<class E2> friend constexpr bool operator==(const unexpected&, const unexpected<E2>&);friend constexpr void swap(unexpected& x, unexpected& y) noexcept(noexcept(x.swap(y)));private: E unex; };template<class E> unexpected(E) -> unexpected<E>;}

A program that instantiates the definition of unexpected for a non-object type, an array type, a specialization of unexpected, or a cv-qualified type is ill-formed.

22.8.3.2 Constructors [expected.un.cons]

template<class Err = E> constexpr explicit unexpected(Err&& e);

Constraints:

Effects: Direct-non-list-initializes unex with std​::​forward<Err>(e).

Throws: Any exception thrown by the initialization of unex.

template<class... Args> constexpr explicit unexpected(in_place_t, Args&&... args);

Constraints: is_constructible_v<E, Args...> is true.

Effects: Direct-non-list-initializes_unex_ with std​::​forward<Args>(args)....

Throws: Any exception thrown by the initialization of unex.

template<class U, class... Args> constexpr explicit unexpected(in_place_t, initializer_list<U> il, Args&&... args);

Constraints: is_constructible_v<E, initializer_list<U>&, Args...> is true.

Effects: Direct-non-list-initializes_unex_ with il, std​::​forward<Args>(args)....

Throws: Any exception thrown by the initialization of unex.

22.8.3.3 Observers [expected.un.obs]

constexpr const E& error() const & noexcept;constexpr E& error() & noexcept;

constexpr E&& error() && noexcept;constexpr const E&& error() const && noexcept;

Returns: std​::​move(unex).

22.8.3.4 Swap [expected.un.swap]

constexpr void swap(unexpected& other) noexcept(is_nothrow_swappable_v<E>);

Mandates: is_swappable_v<E> is true.

Effects: Equivalent to:using std​::​swap; swap(unex, other.unex);

friend constexpr void swap(unexpected& x, unexpected& y) noexcept(noexcept(x.swap(y)));

Constraints: is_swappable_v<E> is true.

Effects: Equivalent to x.swap(y).

22.8.3.5 Equality operator [expected.un.eq]

template<class E2> friend constexpr bool operator==(const unexpected& x, const unexpected<E2>& y);

Mandates: The expression x.error() == y.error() is well-formed and its result is convertible to bool.

Returns: x.error() == y.error().

22.8.4 Class template bad_expected_access [expected.bad]

namespace std { template<class E> class bad_expected_access : public bad_expected_access<void> { public: constexpr explicit bad_expected_access(E);constexpr const char* what() const noexcept override;constexpr E& error() & noexcept;constexpr const E& error() const & noexcept;constexpr E&& error() && noexcept;constexpr const E&& error() const && noexcept;private: E unex; };}

The class template bad_expected_accessdefines the type of objects thrown as exceptions to report the situation where an attempt is made to access the value of an expected<T, E> object for which has_value() is false.

constexpr explicit bad_expected_access(E e);

Effects: Initializes unex with std​::​move(e).

constexpr const E& error() const & noexcept;constexpr E& error() & noexcept;

constexpr E&& error() && noexcept;constexpr const E&& error() const && noexcept;

Returns: std​::​move(unex).

constexpr const char* what() const noexcept override;

Returns: An implementation-defined ntbs, which during constant evaluation is encoded with the ordinary literal encoding ([lex.ccon]).

22.8.5 Class template specialization bad_expected_access [expected.bad.void]

namespace std { template<> class bad_expected_access<void> : public exception { protected: constexpr bad_expected_access() noexcept;constexpr bad_expected_access(const bad_expected_access&) noexcept;constexpr bad_expected_access(bad_expected_access&&) noexcept;constexpr bad_expected_access& operator=(const bad_expected_access&) noexcept;constexpr bad_expected_access& operator=(bad_expected_access&&) noexcept;constexpr ~bad_expected_access();public: constexpr const char* what() const noexcept override;};}

constexpr const char* what() const noexcept override;

Returns: An implementation-defined ntbs, which during constant evaluation is encoded with the ordinary literal encoding ([lex.ccon]).

22.8.6 Class template expected [expected.expected]

22.8.6.1 General [expected.object.general]

namespace std { template<class T, class E> class expected { public: using value_type = T;using error_type = E;using unexpected_type = unexpected<E>;template<class U> using rebind = expected<U, error_type>;constexpr 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&&...);constexpr ~expected();constexpr 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;constexpr void swap(expected&) noexcept(see below);friend constexpr void swap(expected& x, expected& y) noexcept(noexcept(x.swap(y)));constexpr 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 &; constexpr T& value() &; constexpr const T&& value() const &&; constexpr T&& value() &&; constexpr 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&&) &&;template<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 &&;template<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; union { T val; E unex; };};}

Any object of type expected<T, E> either contains a value of type T or a value of type Enested within ([intro.object]) it.

Member has_val indicates whether the expected<T, E> object contains an object of type T.

A type T is a valid value type for expected, if remove_cv_t<T> is voidor a complete non-array object type that is not in_place_t,unexpect_t, or a specialization of unexpected.

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.

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.

22.8.6.2 Constructors [expected.object.cons]

The exposition-only variable template _converts-from-any-cvref_defined in [optional.ctor]is used by some constructors for expected.

Constraints: is_default_constructible_v<T> is true.

Effects: Value-initializes val.

Postconditions: has_value() is true.

Throws: Any exception thrown by the initialization of val.

constexpr expected(const expected& rhs);

Effects: If rhs.has_value() is true, direct-non-list-initializes val with *rhs.

Otherwise, direct-non-list-initializes unex with rhs.error().

Postconditions: rhs.has_value() == this->has_value().

Throws: Any exception thrown by the initialization of val or unex.

Remarks: This constructor is defined as deleted unless

This constructor is trivial if

constexpr expected(expected&& rhs) noexcept(_see below_);

Constraints:

Effects: If rhs.has_value() is true, direct-non-list-initializes val with std​::​move(*rhs).

Otherwise, direct-non-list-initializes unex with std​::​move(rhs.error()).

Postconditions: rhs.has_value() is unchanged;rhs.has_value() == this->has_value() is true.

Throws: Any exception thrown by the initialization of val or unex.

Remarks: The exception specification is equivalent tois_nothrow_move_constructible_v<T> &&is_nothrow_move_constructible_v<E>.

This constructor is trivial if

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);

Let:

Constraints:

Effects: If rhs.has_value(), direct-non-list-initializes val with std​::​forward<UF>(*rhs).

Otherwise, direct-non-list-initializes unex with std​::​forward<GF>(rhs.error()).

Postconditions: rhs.has_value() is unchanged;rhs.has_value() == this->has_value() is true.

Throws: Any exception thrown by the initialization of val or unex.

Remarks: The expression inside explicit is equivalent to!is_convertible_v<UF, T> || !is_convertible_v<GF, E>.

template<class U = remove_cv_t<T>> constexpr explicit(!is_convertible_v<U, T>) expected(U&& v);

Constraints:

Effects: Direct-non-list-initializes val with std​::​forward<U>(v).

Postconditions: has_value() is true.

Throws: Any exception thrown by the initialization of val.

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);

Let GF be const G& for the first overload andG for the second overload.

Constraints: is_constructible_v<E, GF> is true.

Effects: Direct-non-list-initializes unex with std​::​forward<GF>(e.error()).

Postconditions: has_value() is false.

Throws: Any exception thrown by the initialization of unex.

template<class... Args> constexpr explicit expected(in_place_t, Args&&... args);

Constraints: is_constructible_v<T, Args...> is true.

Effects: Direct-non-list-initializes val with std​::​forward<Args>(args)....

Postconditions: has_value() is true.

Throws: Any exception thrown by the initialization of val.

template<class U, class... Args> constexpr explicit expected(in_place_t, initializer_list<U> il, Args&&... args);

Constraints: is_constructible_v<T, initializer_list<U>&, Args...> is true.

Effects: Direct-non-list-initializes val withil, std​::​forward<Args>(args)....

Postconditions: has_value() is true.

Throws: Any exception thrown by the initialization of val.

template<class... Args> constexpr explicit expected(unexpect_t, Args&&... args);

Constraints: is_constructible_v<E, Args...> is true.

Effects: Direct-non-list-initializes unex withstd​::​forward<Args>(args)....

Postconditions: has_value() is false.

Throws: Any exception thrown by the initialization of unex.

template<class U, class... Args> constexpr explicit expected(unexpect_t, initializer_list<U> il, Args&&... args);

Constraints: is_constructible_v<E, initializer_list<U>&, Args...> is true.

Effects: Direct-non-list-initializes unex withil, std​::​forward<Args>(args)....

Postconditions: has_value() is false.

Throws: Any exception thrown by the initialization of unex.

22.8.6.3 Destructor [expected.object.dtor]

Effects: If has_value() is true, destroys val, otherwise destroys unex.

Remarks: If is_trivially_destructible_v<T> is true, andis_trivially_destructible_v<E> is true, then this destructor is a trivial destructor.

22.8.6.4 Assignment [expected.object.assign]

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) { 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;} } }

constexpr expected& operator=(const expected& rhs);

Effects:

Then, if no exception was thrown, equivalent to: has_val = rhs.has_value(); return *this;

Remarks: This operator is defined as deleted unless:

constexpr expected& operator=(expected&& rhs) noexcept(_see below_);

Constraints:

Effects:

Then, if no exception was thrown, equivalent to: has_val = rhs.has_value(); return *this;

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>

template<class U = remove_cv_t<T>> constexpr expected& operator=(U&& v);

Constraints:

Effects:

template<class G> constexpr expected& operator=(const unexpected<G>& e);template<class G> constexpr expected& operator=(unexpected<G>&& e);

Let GF be const G& for the first overload andG for the second overload.

Constraints:

Effects:

template<class... Args> constexpr T& emplace(Args&&... args) noexcept;

Constraints: is_nothrow_constructible_v<T, Args...> is true.

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)...);

template<class U, class... Args> constexpr T& emplace(initializer_list<U> il, Args&&... args) noexcept;

Constraints: is_nothrow_constructible_v<T, initializer_list<U>&, Args...>is true.

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 Swap [expected.object.swap]

constexpr void swap(expected& rhs) noexcept(_see below_);

Constraints:

Table 70 — swap(expected&) effects [tab:expected.object.swap]

equivalent to: using std​::​swap; swap(val, rhs.val);
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;

Throws: Any exception thrown by the expressions in the Effects.

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>

friend constexpr void swap(expected& x, expected& y) noexcept(noexcept(x.swap(y)));

Effects: Equivalent to x.swap(y).

22.8.6.6 Observers [expected.object.obs]

constexpr const T* operator->() const noexcept;constexpr T* operator->() noexcept;

Hardened preconditions: has_value() is true.

constexpr const T& operator*() const & noexcept;constexpr T& operator*() & noexcept;

Hardened preconditions: has_value() is true.

constexpr T&& operator*() && noexcept;constexpr const T&& operator*() const && noexcept;

Hardened preconditions: has_value() is true.

Returns: std​::​move(val).

constexpr explicit operator bool() const noexcept;constexpr bool has_value() const noexcept;

constexpr const T& value() const &;constexpr T& value() &;

Mandates: is_copy_constructible_v<E> is true.

Returns: val, if has_value() is true.

Throws: bad_expected_access(as_const(error())) if has_value() is false.

constexpr T&& value() &&;constexpr const T&& value() const &&;

Mandates: is_copy_constructible_v<E> is true andis_constructible_v<E, decltype(std​::​move(error()))> is true.

Returns: std​::​move(val), if has_value() is true.

Throws: bad_expected_access(std​::​move(error()))if has_value() is false.

constexpr const E& error() const & noexcept;constexpr E& error() & noexcept;

Hardened preconditions: has_value() is false.

constexpr E&& error() && noexcept;constexpr const E&& error() const && noexcept;

Hardened preconditions: has_value() is false.

Returns: std​::​move(unex).

template<class U = remove_cv_t<T>> constexpr T value_or(U&& v) const &;

Mandates: is_copy_constructible_v<T> is true andis_convertible_v<U, T> is true.

Returns: has_value() ? **this : static_cast<T>(std​::​forward<U>(v)).

template<class U = remove_cv_t<T>> constexpr T value_or(U&& v) &&;

Mandates: is_move_constructible_v<T> is true andis_convertible_v<U, T> is true.

Returns: has_value() ? std​::​move(**this) : static_cast<T>(std​::​forward<U>(v)).

template<class G = E> constexpr E error_or(G&& e) const &;

Mandates: is_copy_constructible_v<E> is true andis_convertible_v<G, E> is true.

Returns: std​::​forward<G>(e) if has_value() is true,error() otherwise.

template<class G = E> constexpr E error_or(G&& e) &&;

Mandates: is_move_constructible_v<E> is true andis_convertible_v<G, E> is true.

Returns: std​::​forward<G>(e) if has_value() is true,std​::​move(error()) otherwise.

22.8.6.7 Monadic operations [expected.object.monadic]

template<class F> constexpr auto and_then(F&& f) &;template<class F> constexpr auto and_then(F&& f) const &;

Let U be remove_cvref_t<invoke_result_t<F, decltype((_val_))>>.

Constraints: is_constructible_v<E, decltype(error())> is true.

Mandates: U is a specialization of expected andis_same_v<U​::​error_type, E> is true.

Effects: Equivalent to:if (has_value()) return invoke(std::forward<F>(f), val);else return U(unexpect, error());

template<class F> constexpr auto and_then(F&& f) &&;template<class F> constexpr auto and_then(F&& f) const &&;

Let U beremove_cvref_t<invoke_result_t<F, decltype(std​::​move(_val_))>>.

Constraints: is_constructible_v<E, decltype(std​::​move(error()))> is true.

Mandates: U is a specialization of expected andis_same_v<U​::​error_type, E> is true.

Effects: Equivalent to:if (has_value()) return invoke(std::forward<F>(f), std::move(val));else return U(unexpect, std::move(error()));

template<class F> constexpr auto or_else(F&& f) &;template<class F> constexpr auto or_else(F&& f) const &;

Let G be remove_cvref_t<invoke_result_t<F, decltype(error())>>.

Constraints: is_constructible_v<T, decltype((_val_))> is true.

Mandates: G is a specialization of expected andis_same_v<G​::​value_type, T> is true.

Effects: Equivalent to:if (has_value()) return G(in_place, val);else return invoke(std::forward<F>(f), error());

template<class F> constexpr auto or_else(F&& f) &&;template<class F> constexpr auto or_else(F&& f) const &&;

Let G beremove_cvref_t<invoke_result_t<F, decltype(std​::​move(error()))>>.

Constraints: is_constructible_v<T, decltype(std​::​move(_val_))> is true.

Mandates: G is a specialization of expected andis_same_v<G​::​value_type, T> is true.

Effects: Equivalent to:if (has_value()) return G(in_place, std::move(val));else return invoke(std::forward<F>(f), std::move(error()));

template<class F> constexpr auto transform(F&& f) &;template<class F> constexpr auto transform(F&& f) const &;

Let U beremove_cv_t<invoke_result_t<F, decltype((_val_))>>.

Constraints: is_constructible_v<E, decltype(error())> is true.

Mandates: U is a valid value type for expected.

If is_void_v<U> is false, the declarationU u(invoke(std::forward<F>(f), val));is well-formed.

Effects:

template<class F> constexpr auto transform(F&& f) &&;template<class F> constexpr auto transform(F&& f) const &&;

Let U beremove_cv_t<invoke_result_t<F, decltype(std​::​move(_val_))>>.

Constraints: is_constructible_v<E, decltype(std​::​move(error()))> is true.

Mandates: U is a valid value type for expected.

If is_void_v<U> isfalse, the declarationU u(invoke(std::forward<F>(f), std::move(val)));is well-formed.

Effects:

template<class F> constexpr auto transform_error(F&& f) &;template<class F> constexpr auto transform_error(F&& f) const &;

Let G be remove_cv_t<invoke_result_t<F, decltype(error())>>.

Constraints: is_constructible_v<T, decltype((_val_))> is true.

Mandates: G is a valid template argument for unexpected ([expected.un.general]) and the declarationG g(invoke(std::forward<F>(f), error()));is well-formed.

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()).

template<class F> constexpr auto transform_error(F&& f) &&;template<class F> constexpr auto transform_error(F&& f) const &&;

Let G beremove_cv_t<invoke_result_t<F, decltype(std​::​move(error()))>>.

Constraints: is_constructible_v<T, decltype(std​::​move(_val_))> is true.

Mandates: G is a valid template argument for unexpected ([expected.un.general]) and the declarationG g(invoke(std::forward<F>(f), std::move(error())));is well-formed.

Returns: If has_value() is true,expected<T, G>(in_place, std​::​move(val)); otherwise, anexpected<T, G> object whose has_val member is falseand unex member is direct-non-list-initialized withinvoke(std​::​forward<F>(f), std​::​move(error())).

22.8.6.8 Equality operators [expected.object.eq]

template<class T2, class E2> requires (!is_void_v<T2>) friend constexpr bool operator==(const expected& x, const expected<T2, E2>& y);

Constraints: The expressions *x == *y and x.error() == y.error()are well-formed and their results are convertible to bool.

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().

template<class T2> friend constexpr bool operator==(const expected& x, const T2& v);

Constraints: T2 is not a specialization of expected.

The expression *x == v is well-formed and its result is convertible to bool.

Returns: x.has_value() && static_cast<bool>(*x == v).

template<class E2> friend constexpr bool operator==(const expected& x, const unexpected<E2>& e);

Constraints: The expression x.error() == e.error() is well-formed and its result is convertible to bool.

Returns: !x.has_value() && static_cast<bool>(x.error() == e.error()).

22.8.7 Partial specialization of expected for void types [expected.void]

22.8.7.1 General [expected.void.general]

template<class T, class E> requires is_void_v<T> class expected<T, E> { public: using value_type = T;using error_type = E;using unexpected_type = unexpected<E>;template<class U> using rebind = expected<U, error_type>;constexpr 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&&...);constexpr ~expected();constexpr 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;constexpr void swap(expected&) noexcept(see below);friend constexpr void swap(expected& x, expected& y) noexcept(noexcept(x.swap(y)));constexpr explicit operator bool() const noexcept;constexpr bool has_value() const noexcept;constexpr void operator*() const noexcept;constexpr void value() const &; constexpr void value() &&; constexpr 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&&) &&;template<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 &&;template<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; union { E unex; };};

Any object of type expected<T, E> either represents a value of type T, or contains a value of type Enested within ([intro.object]) it.

Member has_val indicates whether the expected<T, E> object represents a value of type T.

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.

22.8.7.2 Constructors [expected.void.cons]

constexpr expected() noexcept;

Postconditions: has_value() is true.

constexpr expected(const expected& rhs);

Effects: If rhs.has_value() is false, direct-non-list-initializes unex with rhs.error().

Postconditions: rhs.has_value() == this->has_value().

Throws: Any exception thrown by the initialization of unex.

Remarks: This constructor is defined as deleted unless is_copy_constructible_v<E> is true.

This constructor is trivial if is_trivially_copy_constructible_v<E> is true.

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

Constraints: is_move_constructible_v<E> is true.

Effects: If rhs.has_value() is false, direct-non-list-initializes unex with std​::​move(rhs.error()).

Postconditions: rhs.has_value() is unchanged;rhs.has_value() == this->has_value() is true.

Throws: Any exception thrown by the initialization of unex.

Remarks: This constructor is trivial if is_trivially_move_constructible_v<E> is true.

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);

Let GF be const G& for the first overload andG for the second overload.

Constraints:

Effects: If rhs.has_value() is false, direct-non-list-initializes _unex_with std​::​forward<GF>(rhs.error()).

Postconditions: rhs.has_value() is unchanged;rhs.has_value() == this->has_value() is true.

Throws: Any exception thrown by the initialization of unex.

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);

Let GF be const G& for the first overload andG for the second overload.

Constraints: is_constructible_v<E, GF> is true.

Effects: Direct-non-list-initializes _unex_with std​::​forward<GF>(e.error()).

Postconditions: has_value() is false.

Throws: Any exception thrown by the initialization of unex.

constexpr explicit expected(in_place_t) noexcept;

Postconditions: has_value() is true.

template<class... Args> constexpr explicit expected(unexpect_t, Args&&... args);

Constraints: is_constructible_v<E, Args...> is true.

Effects: Direct-non-list-initializes _unex_with std​::​forward<Args>(args)....

Postconditions: has_value() is false.

Throws: Any exception thrown by the initialization of unex.

template<class U, class... Args> constexpr explicit expected(unexpect_t, initializer_list<U> il, Args&&... args);

Constraints: is_constructible_v<E, initializer_list<U>&, Args...> is true.

Effects: Direct-non-list-initializes _unex_with il, std​::​forward<Args>(args)....

Postconditions: has_value() is false.

Throws: Any exception thrown by the initialization of unex.

22.8.7.3 Destructor [expected.void.dtor]

Effects: If has_value() is false, destroys unex.

Remarks: If is_trivially_destructible_v<E> is true, then this destructor is a trivial destructor.

22.8.7.4 Assignment [expected.void.assign]

constexpr expected& operator=(const expected& rhs);

Effects:

Remarks: This operator is defined as deleted unlessis_copy_assignable_v<E> is true andis_copy_constructible_v<E> is true.

constexpr expected& operator=(expected&& rhs) noexcept(_see below_);

Constraints: is_move_constructible_v<E> is true andis_move_assignable_v<E> is true.

Effects:

Remarks: The exception specification is equivalent tois_nothrow_move_constructible_v<E> && is_nothrow_move_assignable_v<E>.

template<class G> constexpr expected& operator=(const unexpected<G>& e);template<class G> constexpr expected& operator=(unexpected<G>&& e);

Let GF be const G& for the first overload andG for the second overload.

Constraints: is_constructible_v<E, GF> is true andis_assignable_v<E&, GF> is true.

Effects:

constexpr void emplace() noexcept;

Effects: If has_value() is false, destroys unex and sets has_val to true.

22.8.7.5 Swap [expected.void.swap]

constexpr void swap(expected& rhs) noexcept(_see below_);

Constraints: is_swappable_v<E> is true andis_move_constructible_v<E> is true.

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;

Throws: Any exception thrown by the expressions in the Effects.

Remarks: The exception specification is equivalent tois_nothrow_move_constructible_v<E> && is_nothrow_swappable_v<E>.

friend constexpr void swap(expected& x, expected& y) noexcept(noexcept(x.swap(y)));

Effects: Equivalent to x.swap(y).

22.8.7.6 Observers [expected.void.obs]

constexpr explicit operator bool() const noexcept;constexpr bool has_value() const noexcept;

constexpr void operator*() const noexcept;

Hardened preconditions: has_value() is true.

constexpr void value() const &;

Mandates: is_copy_constructible_v<E> is true.

Throws: bad_expected_access(error()) if has_value() is false.

constexpr void value() &&;

Mandates: is_copy_constructible_v<E> is true andis_move_constructible_v<E> is true.

Throws: bad_expected_access(std​::​move(error()))if has_value() is false.

constexpr const E& error() const & noexcept;constexpr E& error() & noexcept;

Hardened preconditions: has_value() is false.

constexpr E&& error() && noexcept;constexpr const E&& error() const && noexcept;

Hardened preconditions: has_value() is false.

Returns: std​::​move(unex).

template<class G = E> constexpr E error_or(G&& e) const &;

Mandates: is_copy_constructible_v<E> is true andis_convertible_v<G, E> is true.

Returns: std​::​forward<G>(e) if has_value() is true,error() otherwise.

template<class G = E> constexpr E error_or(G&& e) &&;

Mandates: is_move_constructible_v<E> is true andis_convertible_v<G, E> is true.

Returns: std​::​forward<G>(e) if has_value() is true,std​::​move(error()) otherwise.

22.8.7.7 Monadic operations [expected.void.monadic]

template<class F> constexpr auto and_then(F&& f) &;template<class F> constexpr auto and_then(F&& f) const &;

Let U be remove_cvref_t<invoke_result_t<F>>.

Constraints: is_constructible_v<E, decltype(error())>> is true.

Mandates: U is a specialization of expected andis_same_v<U​::​error_type, E> is true.

Effects: Equivalent to:if (has_value()) return invoke(std::forward<F>(f));else return U(unexpect, error());

template<class F> constexpr auto and_then(F&& f) &&;template<class F> constexpr auto and_then(F&& f) const &&;

Let U be remove_cvref_t<invoke_result_t<F>>.

Constraints: is_constructible_v<E, decltype(std​::​move(error()))> is true.

Mandates: U is a specialization of expected andis_same_v<U​::​error_type, E> is true.

Effects: Equivalent to:if (has_value()) return invoke(std::forward<F>(f));else return U(unexpect, std::move(error()));

template<class F> constexpr auto or_else(F&& f) &;template<class F> constexpr auto or_else(F&& f) const &;

Let G be remove_cvref_t<invoke_result_t<F, decltype(error())>>.

Mandates: G is a specialization of expected andis_same_v<G​::​value_type, T> is true.

Effects: Equivalent to:if (has_value()) return G();else return invoke(std::forward<F>(f), error());

template<class F> constexpr auto or_else(F&& f) &&;template<class F> constexpr auto or_else(F&& f) const &&;

Let G beremove_cvref_t<invoke_result_t<F, decltype(std​::​move(error()))>>.

Mandates: G is a specialization of expected andis_same_v<G​::​value_type, T> is true.

Effects: Equivalent to:if (has_value()) return G();else return invoke(std::forward<F>(f), std::move(error()));

template<class F> constexpr auto transform(F&& f) &;template<class F> constexpr auto transform(F&& f) const &;

Let U be remove_cv_t<invoke_result_t<F>>.

Constraints: is_constructible_v<E, decltype(error())> is true.

Mandates: U is a valid value type for expected.

If is_void_v<U> isfalse, the declarationU u(invoke(std::forward<F>(f)));is well-formed.

Effects:

template<class F> constexpr auto transform(F&& f) &&;template<class F> constexpr auto transform(F&& f) const &&;

Let U be remove_cv_t<invoke_result_t<F>>.

Constraints: is_constructible_v<E, decltype(std​::​move(error()))> is true.

Mandates: U is a valid value type for expected.

If is_void_v<U> isfalse, the declarationU u(invoke(std::forward<F>(f)));is well-formed.

Effects:

template<class F> constexpr auto transform_error(F&& f) &;template<class F> constexpr auto transform_error(F&& f) const &;

Let G be remove_cv_t<invoke_result_t<F, decltype(error())>>.

Mandates: G is a valid template argument for unexpected ([expected.un.general]) and the declarationG g(invoke(std::forward<F>(f), error()));is well-formed.

Returns: If has_value() is true, expected<T, G>(); otherwise, anexpected<T, G> object whose has_val member is falseand unex member is direct-non-list-initialized withinvoke(std​::​forward<F>(f), error()).

template<class F> constexpr auto transform_error(F&& f) &&;template<class F> constexpr auto transform_error(F&& f) const &&;

Let G beremove_cv_t<invoke_result_t<F, decltype(std​::​move(error()))>>.

Mandates: G is a valid template argument for unexpected ([expected.un.general]) and the declarationG g(invoke(std::forward<F>(f), std::move(error())));is well-formed.

Returns: If has_value() is true, expected<T, G>(); otherwise, anexpected<T, G> object whose has_val member is falseand unex member is direct-non-list-initialized withinvoke(std​::​forward<F>(f), std​::​move(error())).

22.8.7.8 Equality operators [expected.void.eq]

template<class T2, class E2> requires is_void_v<T2> friend constexpr bool operator==(const expected& x, const expected<T2, E2>& y);

Constraints: The expression x.error() == y.error() is well-formed and its result is convertible to bool.

Returns: If x.has_value() does not equal y.has_value(), false; otherwise x.has_value() || static_cast<bool>(x.error() == y.error()).

template<class E2> friend constexpr bool operator==(const expected& x, const unexpected<E2>& e);

Constraints: The expression x.error() == e.error() is well-formed and its result is convertible to bool.

Returns: !x.has_value() && static_cast<bool>(x.error() == e.error()).