std::optional::transform(3)

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

🌸 NAME 🌸

okay bestie, this is std::optional::transform(3) from the C++ Standard Libary β€” it’s the monadic glow-up your optional has been waiting for ✨


✨ Synopsis ✨

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

If *this contains a value, it invokes f with the contained value as an argument, and returns an std::optional that contains the result of that invocation; otherwise, it returns an empty std::optional. πŸ’…

The type of contained value in the result (we’re calling it U below) must be a non-array object type, and must not be std::in_place_t or std::nullopt_t). Otherwise, the program is ill-formed. no cap, that’s a hard error.

  1. Let U be std::remove_cv_t<std::invoke_result_t<F, T&>>. If *this contains a value, returns a std::optional<U> whose contained value is direct-initialized from std::invoke(std::forward<F>(f), **this) (unlike and_then(), which must return an std::optional directly). Otherwise, returns an empty std::optional<U>. The program is ill-formed if the variable definition U x(std::invoke(std::forward<F>(f), **this)); is ill-formed. 😭
  2. Same as (1), except that U is std::remove_cv_t<std::invoke_result_t<F, const T&>>.
  3. Let U be std::remove_cv_t<std::invoke_result_t<F, T>>. If *this contains a value, returns a std::optional<U> whose contained value is direct-initialized from std::invoke(std::forward<F>(f), std::move(**this)). Otherwise, returns an empty std::optional<U>. The program is ill-formed if the variable definition U x(std::invoke(std::forward<F>(f), std::move(**this))); is ill-formed. πŸ’€
  4. Same as (3), except that U is std::remove_cv_t<std::invoke_result_t<F, const T>>.

πŸŽ€ Parameters πŸŽ€

  • f β€” a suitable function or Callable object whose call signature returns a non-reference type. literally the callable bestie you’re handing the value to 🫢

πŸ’– Return value πŸ’–

An std::optional containing the result of f or an empty std::optional, as described above. yep, that’s the whole vibe check βœ…

πŸ¦‹ Notes πŸ¦‹

  • Because transform directly constructs a U object at the right location, rather than passing it to a constructor, std::is_move_constructible_v<U> can be false. not me side-eyeing that but ok
  • As the callable f can’t return a reference type, it cannot be a pointer to data member.
  • Some languages call this operation map. iykyk πŸ—ΊοΈ
  • Feature-test macro: __cpp_lib_optional
  • Value: 202110L
  • Std: (C++23)
  • Feature: Monadic operations in std::optional

🌈 Example 🌈

run this code and watch the chain go off πŸ”₯

// Run this code

#include <iostream>
#include <optional>

struct A { /* ... */ };
struct B { /* ... */ };
struct C { /* ... */ };
struct D { /* ... */ };

auto A_to_B(A) -> B { /* ... */ std::cout << "A => B \n"; return {}; }
auto B_to_C(B) -> C { /* ... */ std::cout << "B => C \n"; return {}; }
auto C_to_D(C) -> D { /* ... */ std::cout << "C => D \n"; return {}; }

void try_transform_A_to_D(std::optional<A> o_A)
{
    std::cout << (o_A ? "o_A has a value\n" : "o_A is empty\n");

    std::optional<D> o_D = o_A.transform(A_to_B)
                              .transform(B_to_C)
                              .transform(C_to_D);

    std::cout << (o_D ? "o_D has a value\n\n" : "o_D is empty\n\n");
};

int main()
{
    try_transform_A_to_D( A{} );
    try_transform_A_to_D( {} );
}

πŸ–₯️ Output

o_A has a value
A => B
B => C
C => D
o_D has a value

o_A is empty
o_D is empty

πŸ‘‘ See also πŸ‘‘

  • value_or β€” returns the contained value if available, another value otherwise (public member function). πŸ’–
  • and_then β€” (C++23) returns the result of the given function on the contained value if it exists, or an empty optional otherwise (public member function). πŸ¦‹
  • or_else β€” (C++23) returns the optional itself if it contains a value, or the result of the given function otherwise (public member function). ✨

mwah πŸ’‹ this page is from http://cppreference.com, dated 2024.06.10, and it’s std::optional::transform(3). bye bestie, go transform something iconic 🫢

πŸ“¦ where this page comes from