namespace std::execution {
struct then_t { unspecified };
inline constexpr then_t then{};
}
概要
thenは、入力Senderの値完了操作の継続として関数呼び出しをアタッチするSenderアダプタである。
thenはパイプ可能Senderアダプタオブジェクトであり、パイプライン記法をサポートする。
本ページにてSenderアルゴリズムthen/upon_error/upon_stoppedの動作仕様を包括的に説明するため、以降のセクションにおいてはthen-cpo, set-cpoをそれぞれ下記の通りとする。
then-cpo |
set-cpo |
|---|---|
then |
set_value |
upon_error |
set_error |
upon_stopped |
set_stopped |
効果
説明用の式sndrとfに対して、decltype((sndr))がsenderを満たさない、もしくはdecltype((f))がmovable-valueを満たさないとき、呼び出し式then-cpo(sndr, f)は不適格となる。
そうでなければ、呼び出し式then-cpo(sndr, f)はsndrが1回だけ評価されることを除いて、下記と等価。
transform_sender(get-domain-early(sndr), make-sender(then-cpo, f, sndr))
Senderアルゴリズムタグ then-cpo
Senderアルゴリズム動作説明用のクラステンプレートimpls-forに対して、下記の特殊化が定義される。
namespace std::execution {
template<>
struct impls-for<decayed-typeof<then-cpo>> : default-impls {
static constexpr auto complete =
[]<class Tag, class... Args>
(auto, auto& fn, auto& rcvr, Tag, Args&&... args) noexcept -> void {
if constexpr (same_as<Tag, decayed-typeof<set-cpo>>) {
TRY-SET-VALUE(rcvr,
invoke(std::move(fn), std::forward<Args>(args)...));
} else {
Tag()(std::move(rcvr), std::forward<Args>(args)...);
}
};
template<class Sndr, class... Env>
static consteval void check-types();
};
}
メンバ関数impls-for<decayed-typeof<then-cpo>>::check-typesの効果は下記の通り。
auto cs = get_completion_signatures<child-type<Sndr>, FWD-ENV-T(Env)...>();
auto fn = []<class... Ts>(set_value_t(*)(Ts...)) {
if constexpr (!invocable<remove_cvref_t<data-type<Sndr>>, Ts...>)
throw unspecified-exception();
};
cs.for-each(overload-set{fn, [](auto){}});
unspecified-exceptionはexceptionから派生した型となる。
カスタマイゼーションポイント
Senderアルゴリズム構築時およびReceiver接続時に、関連付けられた実行ドメインに対してexecution::transform_sender経由でSender変換が行われる。
デフォルト実行ドメインでは無変換。
戻り値のSenderout_sndrが下記を満たさない場合、呼び出し式then-cpo(sndr, f)の動作は未定義となる。
then-cpoに対するsndrのset-cpo結果データでfまたはそのコピーを呼び出し、out_sndrの値完了としてfの結果値を用いること。- 上記以外の完了操作では変更なしに転送すること。
例
#include <print>
#include <string>
#include <execution>
namespace ex = std::execution;
int main()
{
{ // 関数呼び出し
ex::sender auto snd0 = ex::just('C', 2);
ex::sender auto snd1 = ex::then(snd0, [](char ch, int n) {
return ch + std::string(n, '+');
});
auto [s] = std::this_thread::sync_wait(snd1).value();
std::println("{}", s);
}
{ // パイプライン記法
ex::sender auto sndr = ex::just('C', 2);
| ex::then([](char ch, int n) {
return ch + std::string(n, '+');
});
auto [s] = std::this_thread::sync_wait(sndr).value();
std::println("{}", s);
}
}
出力
C++
C++
バージョン
言語
- C++26
処理系
- Clang: ??
- GCC: ??
- ICC: ??
- Visual C++: ??