Skip to content

Commit b272152

Browse files
committed
execution: stopped_as_{error,optional} (#1384)
1 parent d6addf6 commit b272152

File tree

3 files changed

+336
-2
lines changed

3 files changed

+336
-2
lines changed

reference/execution/execution.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -126,8 +126,8 @@ namespace std::execution {
126126
| [`execution::when_all`](execution/when_all.md) | 全ての入力Sender完了を待機 (customization point object) | C++26 |
127127
| [`execution::when_all_with_variant`](execution/when_all_with_variant.md) | 複数の値完了シグネチャをもつ全ての入力Sender完了を待機 (customization point object) | C++26 |
128128
| [`execution::into_variant`](execution/into_variant.md) | 複数の値完了シグネチャを単一[`variant`](/reference/variant/variant.md)型の値完了シグネチャに変換 (customization point object) | C++26 |
129-
| [`execution::stopped_as_optional`](execution/stopped_as_optional.md.nolink) | 入力Senderの停止完了を[`optional`](/reference/optional/optional.md)型の値完了に変換 (customization point object) | C++26 |
130-
| [`execution::stopped_as_error`](execution/stopped_as_error.md.nolink) | 入力Senderの停止完了をエラー完了に変換 (customization point object) | C++26 |
129+
| [`execution::stopped_as_optional`](execution/stopped_as_optional.md) | 入力Senderの停止完了を空の[`optional`](/reference/optional/optional.md)値完了に変換 (customization point object) | C++26 |
130+
| [`execution::stopped_as_error`](execution/stopped_as_error.md) | 入力Senderの停止完了をエラー完了に変換 (customization point object) | C++26 |
131131
132132
### Senderコンシューマ
133133
Lines changed: 167 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,167 @@
1+
# stopped_as_error
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 stopped_as_error_t { unspecified };
10+
inline constexpr stopped_as_error_t stopped_as_error{};
11+
}
12+
```
13+
* unspecified[italic]
14+
15+
## 概要
16+
`stopped_as_error`は、入力[Sender](sender.md)の[停止完了](set_stopped.md)をカスタムエラー型の[エラー完了](set_error.md)にマップするSenderアダプタである。
17+
18+
`stopped_as_error`は[パイプ可能Senderアダプタオブジェクト](sender_adaptor_closure.md)であり、パイプライン記法をサポートする。
19+
20+
21+
## 効果
22+
説明用の式`sndr`と`err`に対して、型`Sndr`を`decltype((sndr))`、型`Err`を`decltype((err))`とする。`Sndr`が[`sender`](sender.md)を満たさない、もしくは`Err`が[`moveable-value`](../movable-value.md)を満たさないとき、呼び出し式`stopped_as_error(sndr, err)`は不適格となる。
23+
24+
そうでなければ、呼び出し式`stopped_as_error(sndr, err)`は`sndr`が1回だけ評価されることを除いて、下記と等価。
25+
26+
```cpp
27+
transform_sender(get-domain-early(sndr), make-sender(stopped_as_error, err, 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アルゴリズムタグ `stopped_as_error`
35+
説明用の式`sndr``env`に対して、型`Sndr``decltype((sndr))`、型`Env``decltype((env))`とする。[`sender-for`](sender-for.md)`<Sndr, stopped_as_error_t> == false`、もしくは[`single-sender-value-type`](single-sender-value-type.md.nolink)`<Sndr, Env>`が不適格または`void`のとき、式`stopped_as_error.transform_sender(sndr, env)`は不適格となる。
36+
37+
そうでなければ、式`stopped_as_error.transform_sender(sndr, env)`は下記と等価。
38+
39+
```cpp
40+
auto&& [_, err, child] = sndr;
41+
using E = decltype(auto(err));
42+
return let_stopped(
43+
std::forward_like<Sndr>(child),
44+
[err = std::forward_like<Sndr>(err)]() mutable noexcept(is_nothrow_move_constructible_v<E>) {
45+
return just_error(std::move(err));
46+
});
47+
```
48+
* let_stopped[link let_stopped.md.nolink]
49+
* just_error[link just_error.md]
50+
* is_nothrow_move_constructible_v[link /reference/type_traits/is_nothrow_move_constructible.md]
51+
* std::move[link /reference/utility/move.md]
52+
53+
54+
## カスタマイゼーションポイント
55+
Senderアルゴリズム構築時に、[Sender](sender.md)`sndr`に[関連付けられた実行ドメイン](get-domain-early.md)に対して[`execution::transform_sender`](transform_sender.md)経由でSender変換が行われる。
56+
[デフォルト実行ドメイン](default_domain.md)では無変換。
57+
58+
[Receiver](receiver.md)との[接続(connect)](connect.md)時に、[関連付けられた実行ドメイン](get-domain-late.md)に対して[`execution::transform_sender`](transform_sender.md)経由でSender変換が行われる。
59+
[デフォルト実行ドメイン](default_domain.md)では`stopped_as_error.transform_sender(sndr, env)`が呼ばれ、前述仕様通りのSenderへと変換される。
60+
61+
62+
## 例
63+
```cpp example
64+
#include <cassert>
65+
#include <execution>
66+
namespace ex = std::execution;
67+
68+
// MySenderは下記いずれかの完了操作を行う
69+
// 値完了 set_value(int)
70+
// 停止完了 set_stopped()
71+
struct MySender {
72+
using sender_concept = ex::sender_t;
73+
using completion_signatures = ex::completion_signatures<
74+
ex::set_value_t(int),
75+
ex::set_stopped_t()
76+
>;
77+
78+
template <typename Rcvr>
79+
struct state {
80+
using operation_state_concept = ex::operation_state_t;
81+
82+
state(Rcvr rcvr, int val)
83+
: rcvr_{std::move(rcvr)}, val_{val} {}
84+
85+
void start() noexcept {
86+
if (0 < val_) {
87+
ex::set_value(std::move(rcvr_), val_);
88+
} else {
89+
ex::set_stopped(std::move(rcvr_));
90+
}
91+
}
92+
93+
Rcvr rcvr_;
94+
int val_;
95+
};
96+
97+
template <typename Rcvr>
98+
auto connect(Rcvr rcvr) noexcept {
99+
return state{std::move(rcvr), val_};
100+
}
101+
102+
int val_;
103+
};
104+
105+
int main()
106+
{
107+
{ // 関数呼び出し
108+
ex::sender auto snd0 = MySender{-1};
109+
ex::sender auto snd1 = ex::stopped_as_error(snd0, MyStoppedError{});
110+
try {
111+
auto result = std::this_thread::sync_wait(snd1).value();
112+
std::println("(int) {}", result);
113+
} catch (MyStoppedError) {
114+
std::println("stopped");
115+
}
116+
}
117+
118+
{ // パイプライン記法
119+
ex::sender auto sndr =
120+
MySender{-1}
121+
| ex::stopped_as_error(MyStoppedError{});
122+
try {
123+
auto result = std::this_thread::sync_wait(sndr).value();
124+
std::println("(int) {}", result);
125+
} catch (MyStoppedError) {
126+
std::println("stopped");
127+
}
128+
}
129+
}
130+
```
131+
* ex::stopped_as_error[color ff0000]
132+
* ex::sender_t[link sender.md]
133+
* ex::sender[link sender.md]
134+
* ex::completion_signatures[link completion_signatures.md]
135+
* ex::set_value_t[link set_value.md]
136+
* ex::set_value[link set_value.md]
137+
* ex::set_stopped_t[link set_stopped.md]
138+
* ex::set_stopped[link set_stopped.md]
139+
* ex::operation_state_t[link operation_state.md]
140+
* std::this_thread::sync_wait[link ../this_thread/sync_wait.md]
141+
* std::move[link /reference/utility/move.md]
142+
143+
### 出力
144+
```
145+
stopped
146+
stopped
147+
```
148+
149+
150+
## バージョン
151+
### 言語
152+
- C++26
153+
154+
### 処理系
155+
- [Clang](/implementation.md#clang): ??
156+
- [GCC](/implementation.md#gcc): ??
157+
- [ICC](/implementation.md#icc): ??
158+
- [Visual C++](/implementation.md#visual_cpp): ??
159+
160+
161+
## 関連項目
162+
- [`execution::stopped_as_optional`](stopped_as_optional.md)
163+
164+
165+
## 参照
166+
- [P2999R3 Sender Algorithm Customization](https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2023/p2999r3.html)
167+
- [P2300R10 `std::execution`](https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2024/p2300r10.html)
Lines changed: 167 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,167 @@
1+
# stopped_as_optional
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 stopped_as_optional_t { unspecified };
10+
inline constexpr stopped_as_optional_t stopped_as_optional{};
11+
}
12+
```
13+
* unspecified[italic]
14+
15+
## 概要
16+
`stopped_as_optional`は、入力[Sender](sender.md)の[停止完了](set_stopped.md)を空の[`optional`](/reference/optional/optional.md)による[値完了](set_value.md)にマップするSenderアダプタである。入力Senderの値完了操作も[`optional`](/reference/optional/optional.md)へと変換される。
17+
18+
`stopped_as_optional`は[パイプ可能Senderアダプタオブジェクト](sender_adaptor_closure.md)であり、パイプライン記法をサポートする。
19+
20+
21+
## 効果
22+
説明用の式`sndr`に対して、型`Sndr`を`decltype((sndr))`とする。呼び出し式`stopped_as_optional(sndr)`は`sndr`が1回だけ評価されることを除いて、下記と等価。
23+
24+
```cpp
25+
transform_sender(get-domain-early(sndr), make-sender(stopped_as_optional, {}, sndr))
26+
```
27+
* transform_sender[link transform_sender.md]
28+
* get-domain-early[link get-domain-early.md]
29+
* make-sender[link make-sender.md]
30+
31+
32+
### Senderアルゴリズムタグ `stopped_as_optional`
33+
説明用の式`sndr``env`に対して、型`Sndr``decltype((sndr))`、型`Env``decltype((env))`とする。[`sender-for`](sender-for.md)`<Sndr, stopped_as_optional_t> == false`、もしくは[`single-sender-value-type`](single-sender-value-type.md.nolink)`<Sndr, Env>`が不適格または`void`のとき、式`stopped_as_optional.transform_sender(sndr, env)`は不適格となる。
34+
35+
そうでなければ、式`stopped_as_optional.transform_sender(sndr, env)`は下記と等価。
36+
37+
```cpp
38+
auto&& [_, _, child] = sndr;
39+
using V = single-sender-value-type<Sndr, Env>;
40+
return let_stopped(
41+
then(std::forward_like<Sndr>(child),
42+
[]<class... Ts>(Ts&&... ts) noexcept(is_nothrow_constructible_v<V, Ts...>) {
43+
return optional<V>(in_place, std::forward<Ts>(ts)...);
44+
}),
45+
[]() noexcept { return just(optional<V>()); });
46+
```
47+
* single-sender-value-type[link single-sender-value-type.md.nolink]
48+
* let_stopped[link let_stopped.md.nolink]
49+
* then[link then.md]
50+
* just[link just.md]
51+
* is_nothrow_constructible_v[link /reference/type_traits/is_nothrow_constructible.md]
52+
* optional[link /reference/optional/optional.md]
53+
* in_place[link /reference/utility/in_place_t.md]
54+
55+
56+
## カスタマイゼーションポイント
57+
Senderアルゴリズム構築時に、[Sender](sender.md)`sndr`に[関連付けられた実行ドメイン](get-domain-early.md)に対して[`execution::transform_sender`](transform_sender.md)経由でSender変換が行われる。
58+
[デフォルト実行ドメイン](default_domain.md)では無変換。
59+
60+
[Receiver](receiver.md)との[接続(connect)](connect.md)時に、[関連付けられた実行ドメイン](get-domain-late.md)に対して[`execution::transform_sender`](transform_sender.md)経由でSender変換が行われる。
61+
[デフォルト実行ドメイン](default_domain.md)では`stopped_as_optional.transform_sender(sndr, env)`が呼ばれ、前述仕様通りのSenderへと変換される。
62+
63+
64+
## 例
65+
```cpp example
66+
#include <cassert>
67+
#include <execution>
68+
namespace ex = std::execution;
69+
70+
// MySenderは下記いずれかの完了操作を行う
71+
// 値完了 set_value(int)
72+
// 停止完了 set_stopped()
73+
struct MySender {
74+
using sender_concept = ex::sender_t;
75+
using completion_signatures = ex::completion_signatures<
76+
ex::set_value_t(int),
77+
ex::set_stopped_t()
78+
>;
79+
80+
template <typename Rcvr>
81+
struct state {
82+
using operation_state_concept = ex::operation_state_t;
83+
84+
state(Rcvr rcvr, int val)
85+
: rcvr_{std::move(rcvr)}, val_{val} {}
86+
87+
void start() noexcept {
88+
if (0 < val_) {
89+
ex::set_value(std::move(rcvr_), val_);
90+
} else {
91+
ex::set_stopped(std::move(rcvr_));
92+
}
93+
}
94+
95+
Rcvr rcvr_;
96+
int val_;
97+
};
98+
99+
template <typename Rcvr>
100+
auto connect(Rcvr rcvr) noexcept {
101+
return state{std::move(rcvr), val_};
102+
}
103+
104+
int val_;
105+
};
106+
107+
int main()
108+
{
109+
{ // 関数呼び出し
110+
ex::sender auto snd0 = MySender{-1};
111+
ex::sender auto snd1 = ex::stopped_as_optional(snd0);
112+
auto [result] = std::this_thread::sync_wait(snd1).value();
113+
if (result) {
114+
std::println("(int) {}", *result);
115+
} else {
116+
std::println("stopped");
117+
}
118+
}
119+
120+
{ // パイプライン記法
121+
ex::sender auto sndr = MySender{-1} | ex::stopped_as_optional();
122+
auto [result] = std::this_thread::sync_wait(sndr).value();
123+
if (result) {
124+
std::println("(int) {}", *result);
125+
} else {
126+
std::println("stopped");
127+
}
128+
}
129+
}
130+
```
131+
* ex::stopped_as_optional[color ff0000]
132+
* ex::sender_t[link sender.md]
133+
* ex::sender[link sender.md]
134+
* ex::completion_signatures[link completion_signatures.md]
135+
* ex::set_value_t[link set_value.md]
136+
* ex::set_value[link set_value.md]
137+
* ex::set_stopped_t[link set_stopped.md]
138+
* ex::set_stopped[link set_stopped.md]
139+
* ex::operation_state_t[link operation_state.md]
140+
* std::this_thread::sync_wait[link ../this_thread/sync_wait.md]
141+
* std::move[link /reference/utility/move.md]
142+
143+
### 出力
144+
```
145+
stopped
146+
stopped
147+
```
148+
149+
150+
## バージョン
151+
### 言語
152+
- C++26
153+
154+
### 処理系
155+
- [Clang](/implementation.md#clang): ??
156+
- [GCC](/implementation.md#gcc): ??
157+
- [ICC](/implementation.md#icc): ??
158+
- [Visual C++](/implementation.md#visual_cpp): ??
159+
160+
161+
## 関連項目
162+
- [`execution::stopped_as_error`](stopped_as_error.md)
163+
164+
165+
## 参照
166+
- [P2999R3 Sender Algorithm Customization](https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2023/p2999r3.html)
167+
- [P2300R10 `std::execution`](https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2024/p2300r10.html)

0 commit comments

Comments
 (0)