expected

Header file expected.hpp

#define TL_EXPECTED_HPP

#define TL_EXPECTED_VERSION_MAJOR

#define TL_EXPECTED_VERSION_MINOR

#define TL_MONOSTATE_INPLACE_MUTEX

#define TL_TRAITS_MUTEX

#define TL_OPTIONAL_EXPECTED_MUTEX

namespace tl
{
    class monostate;
    
    struct in_place_t;
    
    constexpr in_place_t{} in_place;
    
    template <class E>
    class unexpected;
    
    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);
    
    template <class E>
    unexpected<E> make_unexpected(E&& e);
    
    struct unexpect_t;
    
    constexpr unexpect_t{} unexpect;
    
    template <class E>
    class bad_expected_access;
    
    template <class T, class E>
    class expected;
    
    template <class T, class E, class U, class F>
    constexpr bool operator==(const expected<T, E>& lhs, const expected<U, F>& rhs);
    
    template <class T, class E, class U, class F>
    constexpr bool operator!=(const expected<T, E>& lhs, const expected<U, F>& rhs);
    
    template <class T, class E, class U, class F>
    constexpr bool operator<(const expected<T, E>& lhs, const expected<U, F>& rhs);
    
    template <class T, class E, class U, class F>
    constexpr bool operator>(const expected<T, E>& lhs, const expected<U, F>& rhs);
    
    template <class T, class E, class U, class F>
    constexpr bool operator<=(const expected<T, E>& lhs, const expected<U, F>& rhs);
    
    template <class T, class E, class U, class F>
    constexpr bool operator>=(const expected<T, E>& lhs, const expected<U, F>& rhs);
    
    template <class T, class E, class U>
    constexpr bool operator==(const expected<T, E>& x, const U& v);
    
    template <class T, class E, class U>
    constexpr bool operator==(const U& v, const expected<T, E>& x);
    
    template <class T, class E, class U>
    constexpr bool operator!=(const expected<T, E>& x, const U& v);
    
    template <class T, class E, class U>
    constexpr bool operator!=(const U& v, const expected<T, E>& x);
    
    template <class T, class E, class U>
    constexpr bool operator<(const expected<T, E>& x, const U& v);
    
    template <class T, class E, class U>
    constexpr bool operator<(const U& v, const expected<T, E>& x);
    
    template <class T, class E, class U>
    constexpr bool operator<=(const expected<T, E>& x, const U& v);
    
    template <class T, class E, class U>
    constexpr bool operator<=(const U& v, const expected<T, E>& x);
    
    template <class T, class E, class U>
    constexpr bool operator>(const expected<T, E>& x, const U& v);
    
    template <class T, class E, class U>
    constexpr bool operator>(const U& v, const expected<T, E>& x);
    
    template <class T, class E, class U>
    constexpr bool operator>=(const expected<T, E>& x, const U& v);
    
    template <class T, class E, class U>
    constexpr bool operator>=(const U& v, const expected<T, E>& x);
    
    template <class T, class E>
    constexpr bool operator==(const expected<T, E>& x, const unexpected<E>& e);
    
    template <class T, class E>
    constexpr bool operator==(const unexpected<E>& e, const expected<T, E>& x);
    
    template <class T, class E>
    constexpr bool operator!=(const expected<T, E>& x, const unexpected<E>& e);
    
    template <class T, class E>
    constexpr bool operator!=(const unexpected<E>& e, const expected<T, E>& x);
    
    template <class T, class E>
    constexpr bool operator<(const expected<T, E>& x, const unexpected<E>& e);
    
    template <class T, class E>
    constexpr bool operator<(const unexpected<E>& e, const expected<T, E>& x);
    
    template <class T, class E>
    constexpr bool operator<=(const expected<T, E>& x, const unexpected<E>& e);
    
    template <class T, class E>
    constexpr bool operator<=(const unexpected<E>& e, const expected<T, E>& x);
    
    template <class T, class E>
    constexpr bool operator>(const expected<T, E>& x, const unexpected<E>& e);
    
    template <class T, class E>
    constexpr bool operator>(const unexpected<E>& e, const expected<T, E>& x);
    
    template <class T, class E>
    constexpr bool operator>=(const expected<T, E>& x, const unexpected<E>& e);
    
    template <class T, class E>
    constexpr bool operator>=(const unexpected<E>& e, const expected<T, E>& x);
    
    template <class T, class E, 'hidden'>
    void swap(expected<T, E>& lhs, expected<T, E>& rhs) noexcept(noexcept(lhs.swap(rhs)));
}

Class tl::monostate

class monostate
{
};

Used to represent an expected with no data

Struct tl::in_place_t

struct in_place_t
{
    in_place_t() = default;
};

A tag type to tell expected to construct its value in-place

Variable tl::in_place

constexpr in_place_t{} in_place;

A tag to tell expected to construct its value in-place

Class template tl::unexpected

template <class E>
class unexpected
{
public:
    unexpected() = delete;
    
    constexpr unexpected(const E& e);
    
    constexpr unexpected(E&& e);
    
    constexpr const E& value() const &;
    E& value() &;
    E&& value() &&;
};

Used as a wrapper to store the unexpected value

Function tl::unexpected::value

(1)  constexpr const E& value() const &;

(2)  E& value() &;

(3)  E&& value() &&;

Returns: the contained value


Comparison operator tl::operator==

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

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

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

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

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

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

Compares two unexpected objects

Simply compares lhs.value() to rhs.value()

Function template tl::make_unexpected

template <class E>
unexpected<E> make_unexpected(E&& e);

Create an unexpected from e, deducing the return type

Example: auto e1 = tl::make_unexpected(42); unexpected<int> e2 (42); //same semantics

Struct tl::unexpect_t

struct unexpect_t
{
    unexpect_t() = default;
};

A tag type to tell expected to construct the unexpected value

Variable tl::unexpect

constexpr unexpect_t{} unexpect;

A tag to tell expected to construct the unexpected value

Class template tl::expected

template <class T, class E>
class expected
{
public:
    using value_type = T;
    
    using error_type = E;
    
    using unexpected_type = unexpected<E>;
    
    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 map(F &&f) &;
    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) const &&;
    
    template <class F> constexpr auto map_error(F &&f) &;
    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) const &&;
    
    template <class F>
    expected or_else(F&& f) &;
    
    template <class F>
    expected or_else(F&& f) &&;
    
    template <class F>
    constexpr expected or_else(F&& f) const &;
    
    template <class F>
    constexpr expected or_else(F&& f) const &&;
    
    constexpr expected() = default;
    
    constexpr expected(const expected& rhs) = default;
    
    constexpr expected(expected&& rhs) = default;
    
    expected& operator=(const expected& rhs) = default;
    
    expected& operator=(expected&& rhs) = default;
    
    template <class ... Args, 'hidden' ... = nullptr>
    constexpr expected(in_place_t, Args&&... args);
    
    template <class U, class ... Args, 'hidden' ... = nullptr>
    constexpr expected(in_place_t, std::initializer_list<U> il, Args&&... args);
    
    EXPLICIT constexpr expected(const unexpected<G> &e);
    EXPLICIT constexpr expected(unexpected<G> &&e);
    
    template <class ... Args, 'hidden' ... = nullptr>
    constexpr expected(unexpect_t, Args&&... args);
    
    template <class U, class G, 'hidden', 'hidden'>
    expected(const expected<U, G>& rhs);
    
    template <class U, class G, 'hidden', 'hidden'>
    expected(expected<U, G>&& rhs);
    
    template <class U = T, 'hidden', 'hidden'>
    constexpr expected(U&& v);
    
    template <class U = T, 'hidden', 'hidden'>
    expected& operator=(U&& v);
    
    template <class G = E, 'hidden'>
    expected& operator=(const unexpected<G>& rhs);
    
    template <class G = E, 'hidden'>
    expected& operator=(unexpected<G>&& rhs) noexcept;
    
    template <class ... Args, 'hidden' ... = nullptr>
    void emplace(Args&&... args);
    
    template <class U, class ... Args, 'hidden' ... = nullptr>
    void emplace(std::initializer_list<U> il, Args&&... args);
    
    void swap(expected& rhs) noexcept(std::is_nothrow_move_constructible<T>::value&&noexcept(swap(std::declval<T&>(), std::declval<T&>()))&&std::is_nothrow_move_constructible<E>::value&&noexcept(swap(std::declval<E&>(), std::declval<E&>())));
    
    constexpr const T* operator->() const;
    T* operator->();
    
    constexpr const T& operator*() const &;
    T& operator*() &;
    constexpr const T&& operator*() const &&;
    T&& operator*() &&;
    
    constexpr bool has_value() const noexcept;
    constexpr operator bool() const noexcept;
    
    constexpr const T& value() const &;
    T& value() &;
    constexpr const T&& value() const &&;
    T&& value() &&;
    
    constexpr const E& error() const &;
    E& error() &;
    constexpr const E&& error() const &&;
    E&& error() &&;
    
    template <class U>
    constexpr T value_or(U&& v) const &;
    template <class U>
    T value_or(U&& v) &&;
};

An 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.

Function template tl::expected::and_then

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

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

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

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

Carries out some operation which returns an expected on the stored object if there is one. \requires std::invoke(std::forward<F>(f), value()) returns a std::expected<U> for some U. \returns Let U be the result of std::invoke(std::forward<F>(f), value()). Returns a std::expected<U>. The return value is empty if *this is empty, otherwise the return value of std::invoke(std::forward<F>(f), value()) is returned.

Function template tl::expected::map

(1)  template <class F> constexpr auto map(F &&f) &;

(2)  template <class F> constexpr auto map(F &&f) &&;

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

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

Carries out some operation on the stored object if there is one.

Returns: Let U be the result of std::invoke(std::forward<F>(f), value()). Returns a std::expected<U,E>. If *this is unexpected, the result is *this, otherwise an expected<U,E> is constructed from the return value of std::invoke(std::forward<F>(f), value()) and is returned.

Function template tl::expected::map_error

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

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

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

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

Carries out some operation on the stored unexpected object if there is one.

Returns: Let U be the result of std::invoke(std::forward<F>(f), value()). Returns a std::expected<T,U>. If *this has an expected value, the result is *this, otherwise an expected<T,U> is constructed from make_unexpected(std::invoke(std::forward<F>(f), value())) and is returned.

Function template tl::expected::or_else

(1)  template <class F>
     expected or_else(F&& f) &;

Calls f if the expectd is in the unexpected state

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

Effects: If *this has a value, returns *this. Otherwise, if f returns void, calls std::forward<F>(f) and returns std::nullopt. Otherwise, returns std::forward<F>(f)().

Function template tl::expected::expected

(1)  EXPLICIT constexpr expected(const unexpected<G> &e);

(2)  EXPLICIT constexpr expected(unexpected<G> &&e);

Operator tl::expected::operator->

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

(2)  T* operator->();

Returns: a pointer to the stored value

Requires: a value is stored

Operator tl::expected::operator*

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

(2)  T& operator*() &;

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

(4)  T&& operator*() &&;

Returns: the stored value

Requires: a value is stored

Function tl::expected::has_value

(1)  constexpr bool has_value() const noexcept;

(2)  constexpr operator bool() const noexcept;

Returns: whether or not the optional has a value

Function tl::expected::value

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

(2)  T& value() &;

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

(4)  T&& value() &&;

Returns: the contained value if there is one, otherwise throws [bad_expected_access]

Function tl::expected::error

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

(2)  E& error() &;

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

(4)  E&& error() &&;

Returns: the unexpected value

Requires: there is an unexpected value

Function template tl::expected::value_or

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

(2)  template <class U>
     T value_or(U&& v) &&;

Returns: the stored value if there is one, otherwise returns u