std::expected::or_else(3)

πŸ“¦ version 2024.07.05, in nixpkgs unstable, opensuse-leap 16.0

πŸ’– NAME πŸ’–

Okay bestie, this page is from the C++ Standard Libary manual, and it's all about std::expected::or_else. The NAME line is literally std::expected::or_else - std::expected::or_else β€” that's it, that's the name, we move πŸ’….


✨ Synopsis ✨

The synopsis is giving overload buffet: four constexpr versions, all since C++23, and the ref-qualifiers are doing main character work. Copy-paste exact, bestie:

template< class F >                      (1) (since C++23)
constexpr auto or_else( F&& f ) &;
template< class F >                      (2) (since C++23)
constexpr auto or_else( F&& f ) const&;
template< class F >                      (3) (since C++23)
constexpr auto or_else( F&& f ) &&;
template< class F >                      (4) (since C++23)
constexpr auto or_else( F&& f ) const&&;

If *this contains an unexpected value, invokes f with the argument error() and returns its result; otherwise, returns a std::expected object that contains a copy of the contained expected value (obtained from operator*).

πŸŒ€ overloads (1) and (2) β€” the & / const& girlies

Given type G as std::remove_cvref_t<std::invoke_result_t<F, decltype(error())>>.

If G is not a specialization of std::expected, or std::is_same_v<G::value_type, T> is false, the program is ill-formed. Not cute, not allowed.

The effect is equivalent to:

if (has_value())
{
    if constexpr (std::is_void_v<T>)
        return G();
    else
        return G(std::in_place, **this);
}
else
    return std::invoke(std::forward<F>(f), error());

These overloads participate in overload resolution only if std::is_void_v<T> or std::is_constructible_v<T, decltype(**this)> is true.

🌈 overloads (3) and (4) β€” the && / const&& girlies

Given type G as std::remove_cvref_t<std::invoke_result_t<F, decltype(std::move(error()))>>.

If G is not a specialization of std::expected, or std::is_same_v<G::value_type, T> is false, the program is ill-formed. Same energy: illegal, bestie.

The effect is equivalent to:

if (has_value())
{
    if constexpr (std::is_void_v<T>)
        return G();
    else
        return G(std::in_place, std::move(**this));
}
else
    return std::invoke(std::forward<F>(f), std::move(error()));

These overloads participate in overload resolution only if std::is_void_v<T> or std::is_constructible_v<T, decltype(std::move(**this))> is true.


πŸŽ€ Parameters πŸŽ€

  • f β€” a suitable function or Callable object that returns a std::expected.

πŸ¦‹ Return value πŸ¦‹

The result of f, or a std::expected object that contains a copy of the expected value, as described above.


🌸 Notes 🌸

Feature-test macro tea β˜•: __cpp_lib_expected has value 202211L, std (C++23), feature Monadic functions for std::expected.


πŸ“ Example πŸ“

This section is incomplete. Reason: no example 😭 (yes, the page really says that, and we respect the honesty).


🩹 Defect reports 🩹

The following behavior-changing defect reports were applied retroactively to previously published C++ standards.

The table labels were DR, Applied to, Behavior as published, Correct behavior β€” and the one report was:

  • LWG 3938 β€” Applied to: C++23. Behavior as published: or_else was ill-formed if T is not (possibly cv-qualified) void and E is not copyable. Correct behavior: made well-formed.

πŸ‘‘ See also πŸ‘‘

  • transform_error (public member function) β€” returns the expected itself if it contains an expected value; otherwise, returns an expected containing the transformed unexpected value.

Category: * Todo no example


Okay that's the whole page, bestie 🫢 source: http://cppreference.com, version/date: 2024.06.10, and the manual page is std::expected::or_else(3). Slay responsibly πŸ’…βœ¨

πŸ“¦ where this page comes from