expected

Source code

C++11/14/17 std::expected with functional-style extensions and reference support.

tl::expected

template<class T, class E>
class expected

A tl::expected<T, E> object is an object that contains the storage for another object and manages the lifetime of this contained object T. Alternatively it could contain the storage for another unexpected object E. The contained object may not be initialized after the expected object has been initialized, and may not be destroyed before the expected object has been destroyed. The initialization state of the contained object is tracked by the expected object.

T must not be a reference type, but it may be void.

Member Types

using value_type = T
using error_type = E
using unexpected_type = unexpected<E>

Special Members

constexpr expected()

Default-constructs the expected value.

Only available if T is default-constructible.

constexpr expected(expected const&)
constexpr expected(expected&&)
template<class ...Args>
expected(tl::in_place_t, Args&&...)
template<class U, class ...Args>
expected(tl::in_place_t, std::initializer_list<U>, Args&&...)

Constructs the expected value in-place using the given arguments.

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

Constructs the unexpected value.

explicit if e is not implicitly convertible to E.

template<class ...Args>
expected(tl::unexpect_t, Args&&...)
template<class U, class ...Args>
expected(tl::unexpect_t, std::initializer_list<U>, Args&&...)

Constructs the unexpected value in-place using the given arguments.

template<class U, class G>
constexpr expected(expected<U, G> const &rhs)
template<class U, class G>
constexpr expected(expected<U, G> &&rhs)

Converting copy/move constructors.

explicit if U and G are not implicitly convertible to T and E.

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

Constructs the expected value with the given value.

template<class U = T>
explicit expected &operator=(U &&v)

If this* in in the expected state, assigns v to the expected value. Otherwise destructs the unexpected value and constructs the expected value with v.

template<class G = E>
expected &operator=(tl::unexpected<G> const &e)
template<class G = E>
expected &operator=(tl::unexpected<G> &&e)

If this* in in the unexpected state, assigns e to the unexpected value. Otherwise destructs the expected value and constructs the unexpected value with e.

Standard Interface

This part of the interface is based on the proposed std::expected.

template<class ...Args>
void emplace(Args&&... args)
template<class U, class ...Args>
void emplace(std::initializer_list<U>, Args&&... args)

If this* in in the expected state, assigns a T constructed in-place from args… to the expected value. Otherwise destructs the unexpected value and constructs the expected value in-place from args….

void swap(expected &rhs)

Swaps *this with rhs.

noexcept if T and E are nothrow-swappable and -move-constructible.

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

Returns a pointer to the expected value. Undefined behaviour if *this is in the unexpected state. Use tl::expected::value() for checked value retrieval.

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

Returns the expected value. Undefined behaviour if *this is in the unexpected state. Use tl::expected::value() for checked value retrieval.

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

If *this is in the expected state, returns the expected value. Otherwise throws tl::bad_expected_access.

constexpr E &error() &
constexpr E const &error() const &
constexpr E &&error() &&
constexpr E const &&error() const &&

If *this is in the unexpected state, returns the unexpected value. Undefined behaviour if *this is in the expected state. Use tl::expected::has_value() or tl::expected::operator bool() to check the state before calling.

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

Returns whether or not *this is in the expected state.

template<class U>
constexpr T value_or(U &&u) const &
template<class U>
constexpr T value_or(U &&u) &&

If *this is in the expected state, returns the expected value. Otherwise returns u.

Extensions

These functions are all extensions to the proposed std::expected.

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) &&
template<class F>
constexpr auto and_then(F &&f) const &&

Used to compose functions which return a tl::expected. If *this is in the expected state, applies f to the expected value and returns the result. Otherwise returns *this (i.e. the unexpected value bubbles up).

Requires: Calling the given function with the expected value must return a specialization of tl::expected.

template<class F>
constexpr auto map(F &&f) &
template<class F>
constexpr auto map(F &&f) const &
template<class F>
constexpr auto map(F &&f) &&
template<class F>
constexpr auto map(F &&f) const &&
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) &&
template<class F>
constexpr auto transform(F &&f) const &&

Apply a function to change the expected value (and possibly the type). If *this is in the expected state, applies f to the expected value and returns the result wrapped in a tl::expected<ResultType, E>. Otherwise returns *this (i.e. the unexpected value bubbles up).

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

Apply a function to change the unexpected value (and possibly the type). If *this is in the unexpected state, applies f to the unexpected value and returns the result wrapped in a tl::expected<T, ResultType>. Otherwise returns *this (i.e. the expected value bubbles up).

template<class F>
optional<T> constexpr or_else(F &&f) &
template<class F>
optional<T> constexpr or_else(F &&f) const &
template<class F>
optional<T> constexpr or_else(F &&f) &&
template<class F>
optional<T> constexpr or_else(F &&f) const &&

If *this is in the unexpected state, calls f and returns the result. Otherwise returns *this.

Requires: std::invoke_result_t<F> must be void or convertible to tl::expected<T,E>.

template<class T, class E, class U, class F>
constexpr bool operator==(expected<T, E> const &lhs, expected<U, F> const &rhs)
template<class T, class E, class U, class F>
constexpr bool operator!=(expected<T, E> const &lhs, expected<U, F> const &rhs)

Compare two tl::expected objects. They are considered equal if they are both in the same expected/unexpected state and their stored objects are equal.

template<class T, class E, class U>
constexpr bool operator==(expected<T, E> const &e, U const &u)
template<class T, class E, class U>
constexpr bool operator!=(expected<T, E> const &e, U const &u)
template<class T, class E, class U>
constexpr bool operator==(U const &u, expected<T, E> const &e)
template<class T, class E, class U>
constexpr bool operator!=(U const &u, expected<T, E> const &e)

Compare a tl::expected to an expected value. Only true if e stores has an expected value which is equal to u.

template<class T, class E>
constexpr bool operator==(expected<T, E> const &e, tl::unexpected<E> const &u)
template<class T, class E>
constexpr bool operator!=(expected<T, E> const &e, tl::unexpected<E> const &u)
template<class T, class E>
constexpr bool operator==(tl::unexpected<E> const &u, expected<T, E> const &e)
template<class T, class E>
constexpr bool operator!=(tl::unexpected<E> const &u, expected<T, E> const &e)

Compare a tl::expected to an unexpected value. Only true if e stores has an unexpected value which is equal to u.

template<class T, class E>
void swap(tl::expected<T, E> &lhs, tl::expected<T, E> &rhs)

Calls lhs.swap(rhs).

noexcept if lhs.swap(rhs) is noexcept.

tl::unexpected

template<class E>
class tl::unexpected

Used as a wrapper to store the unexpected value.

E must not be void.

unexpected() = delete
explicit constexpr unexpected(E const &e)
explicit constexpr unexpected(E&&)

Copies/moves the stored value.

constexpr E const &value() const &
constexpr E &value() &
constexpr E &&value() &&
constexpr E const &&value() const &&

Returns the contained value.

template<class E>
constexpr bool operator==(const unexpected<E> &lhs, const unexpected<E> &rhs)
template<class E>
constexpr bool operator!=(const unexpected<E> &lhs, const unexpected<E> &rhs)
template<class E>
constexpr bool operator<(const unexpected<E> &lhs, const unexpected<E> &rhs)
template<class E>
constexpr bool operator<=(const unexpected<E> &lhs, const unexpected<E> &rhs)
template<class E>
constexpr bool operator>(const unexpected<E> &lhs, const unexpected<E> &rhs)
template<class E>
constexpr bool operator>=(const unexpected<E> &lhs, const unexpected<E> &rhs)

Compares two unexpected objects by comparing their stored value.

template<class E>
unexpected<std::decay_t<E>> tl::make_unexpected(E &&e)

Create an unexpected from e, deducing the return type

Example:

auto e1 = tl::make_unexpected(42);
tl::unexpected<int> e2 (42); //same semantics
static constexpr unexpect_t tl::unexpect

A tag to tell tl::expected to construct the unexpected value.

Example:

tl::expected<int,int> a(tl::unexpect, 42);