[ Web Proxy ]
URL:
Viewing: https://en.cppreference.com/cpp/execution/let_value [Back]  [Original]

std::execution::let_value - cppreference.com
cppreference.com
Namespaces
Variants

std::execution::let_value

From cppreference.com
 
 
Execution control library
Execution concepts
Execution components
Execution contexts
Execution domains
Forward progress guarantee
Environments
    
    
    
Queries
Completion signatures
Sender adaptor closures
Coroutine utility
 
Defined in header <execution>
struct let_value_t { /*unspecified*/ };
(1) (since C++26)
inline constexpr let_value_t let_value{};
(2) (since C++26)
(customization point object)
Call signature
execution::sender auto let_value( execution::sender auto sndr,
                                  /* movable value */ auto f );
(since C++26)

Continues a sender with more asynchronous work that depends on its result: when sndr completes with values, f is called with them, and f returns a sender. That sender is started, and its completion becomes the completion of the returned sender.

This is the asynchronous counterpart of "call a function with the result, and that function does more asynchronous work". Use then when the next step is a plain function that returns a value; use let_value when the next step is itself asynchronous, or when which asynchronous step comes next depends on the value.

let_value is a pipeable sender adaptor: sndr | let_value(f) is equivalent to let_value(sndr, f).

Parameters

sndr - the sender whose values are passed to f
f - a function (or other callable) called with the values sent by sndr, which returns a sender

Return value

A sender that behaves like sndr until sndr completes with values. Then:

  • f is called with the values, and the sender it returns is started.
  • The returned sender completes the way that inner sender does: with its values, with its error, or stopped.
  • If f throws, the returned sender completes with the exception as an error (set_error with a std::exception_ptr).

Error and stopped completions of sndr are forwarded unchanged: f is not called for them. Use let_error and let_stopped to continue with a sender after those.

let_value(sndr, f) is ill-formed if sndr does not satisfy execution::sender or f cannot be copied or moved into the sender (it must be a movable value, and not an array). It is also diagnosed at compile time if, for some value completion of sndr, f cannot be called with the values as lvalues or does not return a sender.

Customization point objects

The name execution::let_value denotes a customization point object, which is a const function object of a literal semiregular class type. The cv-unqualified version of its type is a tag type denoted as execution::let_value_t. See CustomizationPointObject for details.

Details

  • Nothing runs when the sender is built. f is called only after the returned sender has been connected to a receiver and started, and only if sndr completes with values.
  • f is called with the values as lvalues that stay alive until the sender returned by f completes. A parameter of type T&, const T& or T accepts them; a parameter of type T&& does not. Because the values outlive the inner sender, the inner sender may keep references to them, which is not possible with a function that only receives temporaries.
  • f is called on the execution agent on which sndr completed with values, and the sender it returns is started there. The sender returned by f sees that scheduler as its start scheduler (get_start_scheduler).
  • If sndr can complete with several different sets of values, f must be callable with each of them, and must return a sender for each. All of those senders must complete in compatible ways for the result to be useful (for example with the same value type).
  • The function must return a single type of sender for each set of values: a lambda whose return statements return different sender types does not compile. To choose between different senders at run time, return a sender that can represent both, or select within one sender (for example by branching inside a then).

Notes

  • The sender returned by let_value sends what the inner sender sends. Unlike then, whose result is a plain value, let_value does not wrap the result of f: if f returns just(x), the result is x, not a sender.
  • The lifetime guarantee is the main reason to prefer let_value over capturing values yourself: the values sent by sndr stay alive, stored in the operation, until the sender returned by f completes. That is what makes it safe for the inner sender to refer to them. For large values, pass a reference or a handle through the chain instead of copying.

Example

The function gets the id found by the first step and decides what asynchronous work comes next, here a lookup that uses the id. The id stays valid for the whole inner operation. Nothing runs until sync_wait starts the sender. The standard header is not available in the online compilers yet, so this link runs the example on Compiler Explorer with stdexec, the reference implementation.

#include <execution>
#include <print>
#include <string>
#include <thread>

namespace ex = std::execution;

// Stand-ins for asynchronous operations (for example network requests).
ex::sender auto find_user_id(std::string name)
{
    return ex::just(name.size()) | ex::then([](std::size_t n) { return static_cast<int>(n); });
}

ex::sender auto load_profile(int id)
{
    return ex::just() | ex::then([id] { return std::string("profile of user #") + std::to_string(id); });
}

int main()
{
    auto sndr = find_user_id("alice")
              | ex::let_value([](int& id)
                {
                    std::println("found id {}, loading profile", id);
                    return load_profile(id);
                });

    std::println("sender built, nothing has run yet");

    auto [profile] = std::this_thread::sync_wait(std::move(sndr)).value();
    std::println("{}", profile);
}

Output:

sender built, nothing has run yet
found id 5, loading profile
profile of user #5

See also

chains a function onto a sender, calling it with the values the sender sends and sending its result on
(customization point object)[edit]
chains a function onto a sender, calling it with the error if the sender fails and continuing with the sender it returns
(customization point object)[edit]
chains a function onto a sender, calling it if the sender is cancelled and continuing with the sender it returns
(customization point object)[edit]

Web Proxy Viewer  |  New URL  |  Original Page