Skip to content

Commit 628698f

Browse files
committed
execution: then (#1384)
basic-receiver
1 parent 7baad01 commit 628698f

File tree

9 files changed

+236
-11
lines changed

9 files changed

+236
-11
lines changed

reference/execution/execution.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -115,7 +115,7 @@ namespace std::execution {
115115
| [`execution::continues_on`](execution/continues_on.md.nolink) | 指定Scheduler上で継続する (customization point object) | C++26 |
116116
| [`execution::on`](execution/on.md.nolink) | 指定Scheduler上で実行する (customization point object) | C++26 |
117117
| [`execution::schedule_from`](execution/schedule_from.md.nolink) | Sender完了に依存する作業をスケジュール (customization point object) | C++26 |
118-
| [`execution::then`](execution/then.md.nolink) | 値完了時の継続処理をアタッチ (customization point object) | C++26 |
118+
| [`execution::then`](execution/then.md) | 値完了時の継続処理をアタッチ (customization point object) | C++26 |
119119
| [`execution::upon_error`](execution/upon_error.md.nolink) | エラー完了時の継続処理をアタッチ (customization point object) | C++26 |
120120
| [`execution::upon_stopped`](execution/upon_stopped.md.nolink) | 停止完了時の継続処理をアタッチ (customization point object) | C++26 |
121121
| [`execution::let_value`](execution/let_value.md.nolink) | 値完了の継続にユーザ定義処理を連結 (customization point object) | C++26 |

reference/execution/execution/basic-operation.md

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -105,6 +105,7 @@ using connect-all-result = call-result-t< // exposition only
105105
template<class Sndr>
106106
using indices-for = remove_reference_t<Sndr>::indices-for; // exposition only
107107
```
108+
* call-result-t[link call-result-t.md.nolink]
108109
* impls-for[link impls-for.md]
109110
* tag_of_t[link tag_of_t.md]
110111
* decay_t[link /reference/type_traits/decay.md]
@@ -113,7 +114,7 @@ using indices-for = remove_reference_t<Sndr>::indices-for; // exposition only
113114
114115
説明専用の定数`connect-all`は、下記ラムダ式と等価な関数呼び出し可能なオブジェクトとして初期化される。
115116
116-
- 全ての子Sender`child`とSenderアルゴリズム`sndr`の[Receiver](basic-receiver.md.nolink)を[接続(connect)](connect.md)し、結果の[Operation State](operation_state.md)リストを[`product-type`](product-type.md)型にまとめて返す。
117+
- 全ての子Sender`child`とSenderアルゴリズム`sndr`の[Receiver](basic-receiver.md)を[接続(connect)](connect.md)し、結果の[Operation State](operation_state.md)リストを[`product-type`](product-type.md)型にまとめて返す。
117118
118119
```cpp
119120
[]<class Sndr, class Rcvr, size_t... Is>(
@@ -128,7 +129,7 @@ using indices-for = remove_reference_t<Sndr>::indices-for; // exposition only
128129
* index_sequence[link /reference/utility/index_sequence.md]
129130
* product-type[link product-type.md]
130131
* connect[link connect.md]
131-
* basic-receiver[link basic-receiver.md.nolink]
132+
* basic-receiver[link basic-receiver.md]
132133
* integral_constant[link /reference/type_traits/integral_constant.md]
133134
* see below[italic]
134135

@@ -143,7 +144,7 @@ using indices-for = remove_reference_t<Sndr>::indices-for; // exposition only
143144

144145
## 関連項目
145146
- [`basic-sender`](basic-sender.md)
146-
- [`basic-receiver`](basic-receiver.md.nolink)
147+
- [`basic-receiver`](basic-receiver.md)
147148
- [`execution::operation_state`](operation_state.md)
148149

149150

Lines changed: 94 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,94 @@
1+
# basic-receiver
2+
* execution[meta header]
3+
* class template[meta id-type]
4+
* std::execution[meta namespace]
5+
* cpp26[meta cpp]
6+
7+
```cpp
8+
namespace std::execution {
9+
template<class Sndr, class Rcvr, class Index>
10+
requires valid-specialization<env-type, Index, Sndr, Rcvr>
11+
struct basic-receiver { // exposition only
12+
using receiver_concept = receiver_t;
13+
14+
using tag-t = tag_of_t<Sndr>; // exposition only
15+
using state-t = state-type<Sndr, Rcvr>; // exposition only
16+
static constexpr const auto& complete = impls-for<tag-t>::complete; // exposition only
17+
18+
template<class... Args>
19+
requires callable<decltype(complete), Index, state-t&, Rcvr&, set_value_t, Args...>
20+
void set_value(Args&&... args) && noexcept {
21+
complete(Index(), op->state, op->rcvr, set_value_t(), std::forward<Args>(args)...);
22+
}
23+
24+
template<class Error>
25+
requires callable<decltype(complete), Index, state-t&, Rcvr&, set_error_t, Error>
26+
void set_error(Error&& err) && noexcept {
27+
complete(Index(), op->state, op->rcvr, set_error_t(), std::forward<Error>(err));
28+
}
29+
30+
void set_stopped() && noexcept
31+
requires callable<decltype(complete), Index, state-t&, Rcvr&, set_stopped_t> {
32+
complete(Index(), op->state, op->rcvr, set_stopped_t());
33+
}
34+
35+
auto get_env() const noexcept -> env-type<Index, Sndr, Rcvr> {
36+
return impls-for<tag-t>::get-env(Index(), op->state, op->rcvr);
37+
}
38+
39+
basic-state<Sndr, Rcvr>* op; // exposition only
40+
};
41+
}
42+
```
43+
* receiver_t[link receiver.md]
44+
* tag_of_t[link tag_of_t.md]
45+
* state-type[link basic-operation.md]
46+
* impls-for[link impls-for.md]
47+
* callable[link /reference/functional/callable.md.nolink]
48+
* set_value_t[link set_value.md]
49+
* set_error_t[link set_error.md]
50+
* set_stopped_t[link set_stopped.md]
51+
* basic-state[link basic-operation.md]
52+
53+
54+
## 概要
55+
`basic-receiver`は、Senderアルゴリズム動作仕様定義で用いられる説明専用のクラステンプレートである。
56+
57+
`basic-receiver<Sndr, Rcvr, Index>`は[`receiver`](receiver.md)のモデルであり、SenderアルゴリズムのReceiverとしてして[子Senderとの接続時](basic-operation.md)に利用される。
58+
59+
- `Sndr` : Senderアルゴリズムの[Sender](sender.md)。
60+
- `Rcvr` : Senderアルゴリズムの接続先[Receiver](receiver.md)。Senderアルゴリズム同士を連結する場合は、親Senderアルゴリズム側のReceiver型。
61+
- `Index` : Senderアルゴリズムの子Sender識別用インデクス値。Senderアダプタは通常1個の子Senderと接続され、この場合は`Index()`は定数値`0`となる。
62+
63+
64+
## 説明専用エンティティ
65+
66+
```cpp
67+
template<template<class...> class T, class... Args>
68+
concept valid-specialization = // exposition only
69+
requires { typename T<Args...>; };
70+
71+
template<class Index, class Sndr, class Rcvr> // exposition only
72+
using env-type = call-result-t<
73+
decltype(impls-for<tag_of_t<Sndr>>::get-env), Index,
74+
state-type<Sndr, Rcvr>&, const Rcvr&>;
75+
```
76+
* call-result-t[link call-result-t.md.nolink]
77+
* impls-for[link impls-for.md]
78+
* tag_of_t[link tag_of_t.md]
79+
* state-type[link basic-operation.md]
80+
81+
82+
## バージョン
83+
### 言語
84+
- C++26
85+
86+
87+
## 関連項目
88+
- [`basic-sender`](basic-sender.md)
89+
- [`basic-operation`](basic-operation.md)
90+
- [`execution::receiver`](receiver.md)
91+
92+
93+
## 参照
94+
- [P2300R10 `std::execution`](https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2024/p2300r10.html)

reference/execution/execution/basic-sender.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ namespace std::execution {
4646
4747
`basic-sender<Tag, Data, Child...>`は[`sender`](sender.md)のモデルであり、[Senderアルゴリズム構築](make-sender.md)の結果型として利用される。
4848
49-
- `Tag` : [Senderアルゴリズムタグ](tag_of_t.md)(例:[`just`](just.md), [`then`](then.md.nolink))
49+
- `Tag` : [Senderアルゴリズムタグ](tag_of_t.md)(例:[`just`](just.md), [`then`](then.md))
5050
- `Data` : Senderアルゴリズムに指定された追加の引数。複数個の引数は[`product-type`](product-type.md)型を用いて単一値として保持する。
5151
- `Child` : 子Senderのリスト。Senderファクトリでは0個、Senderアダプタでは通常1個の子Senderを保持する。
5252

reference/execution/execution/get_completion_scheduler.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -82,7 +82,7 @@ int main()
8282
* ex::schedule[link schedule.md]
8383
* ex::set_value_t[link set_value.md]
8484
* ex::get_env[link get_env.md]
85-
* ex::then[link then.md.nolink]
85+
* ex::then[link then.md]
8686

8787
### 出力
8888
```

reference/execution/execution/impls-for.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ namespace std::execution {
4949
* env<>[link env.md]
5050

5151
### `get-env`メンバ
52-
`get-env`は、[`basic-receiver`](basic-receiver.md.nolink)実装におけるReceiver[環境](../queryable.md)取得のカスタマイゼーションポイントとして機能する。
52+
`get-env`は、[`basic-receiver`](basic-receiver.md)実装におけるReceiver[環境](../queryable.md)取得のカスタマイゼーションポイントとして機能する。
5353

5454
`default-impls::get-env`メンバは、下記ラムダ式と等価な関数呼び出し可能なオブジェクトで初期化される。
5555

@@ -92,7 +92,7 @@ namespace std::execution {
9292
* execution::start[link start.md]
9393

9494
### `complete`メンバ
95-
`complete`は、[`basic-receiver`](basic-receiver.md.nolink)実装における各種完了操作のカスタマイゼーションポイントとして機能する。
95+
`complete`は、[`basic-receiver`](basic-receiver.md)実装における各種完了操作のカスタマイゼーションポイントとして機能する。
9696

9797
`default-impls::complete`メンバは、下記ラムダ式と等価な関数呼び出し可能なオブジェクトで初期化される。
9898

@@ -120,7 +120,7 @@ namespace std::execution {
120120
121121
## 関連項目
122122
- [`basic-sender`](basic-sender.md)
123-
- [`basic-receiver`](basic-receiver.md.nolink)
123+
- [`basic-receiver`](basic-receiver.md)
124124
- [`basic-operation`](basic-operation.md)
125125
126126

reference/execution/execution/make-sender.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ constexpr auto make-sender(Tag tag, Data&& data, Child&&... child);
1515
1616
[`sender`](sender.md)のモデルである説明専用クラステンプレート[`basic-sender`](basic-sender.md)のインスタンスを生成する。
1717
18-
- `Tag` : [Senderアルゴリズムタグ](tag_of_t.md)(例:[`just`](just.md), [`then`](then.md.nolink))
18+
- `Tag` : [Senderアルゴリズムタグ](tag_of_t.md)(例:[`just`](just.md), [`then`](then.md))
1919
- `Data` : Senderアルゴリズムに指定された追加の引数。複数個の引数は[`product-type`](product-type.md)型を用いて単一値として保持する。
2020
- `Child` : 子Senderのリスト。Senderファクトリでは0個、Senderアダプタでは通常1個の子Senderを保持する。
2121

reference/execution/execution/schedule.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,7 @@ int main()
6363
* ex::schedule[color ff0000]
6464
* ex::scheduler[link scheduler.md]
6565
* ex::sender[link sender.md]
66-
* ex::then[link then.md.nolink]
66+
* ex::then[link then.md]
6767
* ex::run_loop[link run_loop.md]
6868
* get_scheduler()[link run_loop/get_scheduler.md]
6969
* run()[link run_loop/run.md]
Lines changed: 130 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,130 @@
1+
# then
2+
* execution[meta header]
3+
* cpo[meta id-type]
4+
* std::execution[meta namespace]
5+
* cpp26[meta cpp]
6+
7+
```cpp
8+
namespace std::execution {
9+
struct then_t { unspecified };
10+
inline constexpr then_t then{};
11+
}
12+
```
13+
* unspecified[italic]
14+
15+
## 概要
16+
`then`は、入力[Sender](sender.md)の[値完了操作](set_value.md)の継続として関数呼び出しをアタッチするSenderアダプタである。
17+
18+
`then`はパイプライン記法をサポートする。
19+
20+
21+
## 効果
22+
説明用の式`sndr`と`f`に対して、`decltype((sndr))`が[`sender`](sender.md)を満たさない、もしくは`decltype((f))`が[`movable-value`](../movable-value.md)を満たさないとき、呼び出し式`then(sndr, f)`は不適格となる。
23+
24+
そうでなければ、呼び出し式`then(sndr, f)`は`sndr`が1回だけ評価されることを除いて、下記と等価。
25+
26+
```cpp
27+
transform_sender(get-domain-early(sndr), make-sender(then, f, sndr))
28+
```
29+
* transform_sender[link transform_sender.md]
30+
* get-domain-early[link get-domain-early.md]
31+
* make-sender[link make-sender.md]
32+
33+
34+
### Senderアルゴリズムタグ `then`
35+
Senderアルゴリズム動作説明用のクラステンプレート`impls-for`に対して、下記の特殊化が定義される。
36+
37+
```cpp
38+
namespace std::execution {
39+
template<>
40+
struct impls-for<decayed-typeof<then>> : default-impls {
41+
static constexpr auto complete =
42+
[]<class Tag, class... Args>
43+
(auto, auto& fn, auto& rcvr, Tag, Args&&... args) noexcept -> void {
44+
if constexpr (same_as<Tag, decayed-typeof<set_value>>) {
45+
TRY-SET-VALUE(rcvr,
46+
invoke(std::move(fn), std::forward<Args>(args)...));
47+
} else {
48+
Tag()(std::move(rcvr), std::forward<Args>(args)...);
49+
}
50+
};
51+
};
52+
}
53+
```
54+
* decayed-typeof[link decayed-typeof.md.nolink]
55+
* impls-for[link impls-for.md]
56+
* default-impls[link impls-for.md]
57+
* set_value[link set_value.md]
58+
* invoke[link /reference/functional/invoke.md]
59+
* std::move[link /reference/utility/move.md]
60+
61+
62+
## カスタマイゼーションポイント
63+
[Sender](sender.md)`sndr`に[関連付けられた実行ドメイン](get-domain-early.md)`dom`に対して、[`execution::transform_sender`](transform_sender.md)経由でSender変換が行われる。
64+
[デフォルト実行ドメイン](../execution/default_domain.md)では無変換。
65+
66+
戻り値の[Sender](sender.md)`out_sndr`が下記を満たさない場合、呼び出し式`then(sndr, f)`の動作は未定義となる。
67+
68+
- `then`に対する`sndr`の値結果データで`f`またはそのコピーを呼び出し、`out_sndr`の値完了として`f`の結果値を用いること。
69+
- 他の完了操作では変更なしに転送すること。
70+
71+
72+
## 例
73+
```cpp example
74+
#include <print>
75+
#include <string>
76+
#include <execution>
77+
namespace ex = std::execution;
78+
79+
int main()
80+
{
81+
{ // 関数呼び出し
82+
ex::sender auto snd0 = ex::just('C', 2);
83+
ex::sender auto snd1 = ex::then(snd0, [](char ch, int s){
84+
return ch + std::string(2, '+');
85+
});
86+
auto [s] = std::this_thread::sync_wait(snd1).value();
87+
std::println("{}", s);
88+
}
89+
90+
{ // パイプライン記法
91+
ex::sender auto sndr = ex::just('C', 2);
92+
| ex::then([](char ch, int s){
93+
return ch + std::string(2, '+');
94+
});
95+
auto [s] = std::this_thread::sync_wait(sndr).value();
96+
std::println("{}", s);
97+
}
98+
}
99+
```
100+
* ex::then[color ff0000]
101+
* ex::sender[link sender.md]
102+
* ex::just[link just.md]
103+
* std::this_thread::sync_wait[link ../this_thread/sync_wait.md]
104+
* value()[link /reference/optional/optional/value.md]
105+
106+
### 出力
107+
```
108+
C++
109+
C++
110+
```
111+
112+
113+
## バージョン
114+
### 言語
115+
- C++26
116+
117+
### 処理系
118+
- [Clang](/implementation.md#clang): ??
119+
- [GCC](/implementation.md#gcc): ??
120+
- [ICC](/implementation.md#icc): ??
121+
- [Visual C++](/implementation.md#visual_cpp): ??
122+
123+
124+
## 関連項目
125+
- [`execution::upon_error`](upon_error.md.nolink)
126+
- [`execution::upon_stopped`](upon_stopped.md.nolink)
127+
128+
129+
## 参照
130+
- [P2300R10 `std::execution`](https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2024/p2300r10.html)

0 commit comments

Comments
 (0)