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

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

std::execution::then

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 then_t { /*unspecified*/ };
(1) (since C++26)
inline constexpr then_t then{};
(2) (since C++26)
(customization point object)
Call signature
execution::sender auto then( execution::sender auto sndr,
                             /* movable value */ auto f );
(since C++26)

Attaches a function to a sender: when sndr completes with values, f is called with them, and the result of the call becomes the value the returned sender completes with.

then is the basic way to do something with the result of asynchronous work, and the building block of most sender pipelines. It is the sender counterpart of calling a function on a result you already have.

then is a pipeable sender adaptor: sndr | then(f) is equivalent to then(sndr, f), which makes chains read in the order the work happens.

Parameters

sndr - the sender whose values are passed to f
f - the function (or other callable) to call with the values sent by sndr

Return value

A sender that behaves like sndr, except that each value completion of sndr is replaced by a call of f with the values it carries:

  • The result of f is sent as the value of the returned sender. If f returns void, the returned sender completes with no values.
  • 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 upon_error and upon_stopped to handle those.

then(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 f cannot be called with the values of some value completion of sndr.

Customization point objects

The name execution::then 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::then_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 and when sndr completes with values. Building a chain of then calls only describes the work.
  • f runs on the execution agent on which sndr completes, immediately in the completion. then never moves work to another thread; to change where the next step runs, use continues_on or on.
  • If sndr can complete with several different sets of values, f must be callable with each of them (a generic lambda works).

Notes

  • The result of f is a plain value. If f returns a sender, that sender is sent as a value, it is not started and not waited for. To continue with further asynchronous work depending on a result, use let_value.
  • then only handles the value channel. upon_error and upon_stopped do the same for the error and stopped channels; like then, they send the result of the function as a value, which turns a failure into a normal result.
  • Exceptions thrown by f become an error completion of the returned sender, so they are reported through the same channel as errors from sndr. Whoever consumes the sender, for example this_thread::sync_wait, decides what happens to them.

Example

then turns the two values sent by just into one result, and then into text. 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 <iostream>
#include <string>
#include <thread>

namespace ex = std::execution;

int main()
{
    auto sndr = ex::just(6, 7)
              | ex::then([](int a, int b)
                {
                    std::cout << "multiplying\n";
                    return a * b;
                })
              | ex::then([](int product)
                {
                    return "answer: " + std::to_string(product);
                });

    std::cout << "sender built, nothing has run yet\n";

    auto [text] = std::this_thread::sync_wait(std::move(sndr)).value();
    std::cout << text << '\n';
}

Output:

sender built, nothing has run yet
multiplying
answer: 42

An exception thrown by a function becomes an error. The next then is skipped, and upon_error turns the error into a value. 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 <exception>
#include <execution>
#include <iostream>
#include <stdexcept>
#include <thread>

namespace ex = std::execution;

int main()
{
    auto sndr = ex::just(0)
              | ex::then([](int divisor)
                {
                    if (divisor == 0)
                        throw std::runtime_error("division by zero");
                    return 10 / divisor;
                })
              | ex::then([](int quotient)
                {
                    std::cout << "not reached\n";
                    return quotient;
                })
              | ex::upon_error([](std::exception_ptr)
                {
                    return -1;
                });

    auto [result] = std::this_thread::sync_wait(std::move(sndr)).value();
    std::cout << "result: " << result << '\n';
}

Output:

result: -1

See also

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

Web Proxy Viewer  |  New URL  |  Original Page