Skip to content

Commit 250f357

Browse files
authored
Merge pull request #1728 from RobertLeahy/repeat_effect_20260102
exec::repeat_effect: No set_value Completion Signature
2 parents c03da7a + f2449df commit 250f357

File tree

2 files changed

+35
-8
lines changed

2 files changed

+35
-8
lines changed

include/exec/repeat_effect_until.hpp

Lines changed: 21 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,9 @@ namespace exec {
6464
};
6565
};
6666

67+
template <typename _T, bool _B>
68+
concept __compile_time_bool_of = std::remove_cvref_t<_T>::value == _B;
69+
6770
STDEXEC_PRAGMA_PUSH()
6871
STDEXEC_PRAGMA_IGNORE_GNU("-Wtsan")
6972

@@ -120,10 +123,15 @@ namespace exec {
120123
if constexpr (same_as<_Tag, set_value_t>) {
121124
// If the sender completed with true, we're done
122125
STDEXEC_TRY {
123-
const bool __done = (static_cast<bool>(static_cast<_Args &&>(__args)) && ...);
124-
if (__done) {
126+
if constexpr ((__compile_time_bool_of<_Args, true> && ...)) {
125127
stdexec::set_value(static_cast<_Receiver &&>(this->__receiver()));
126128
return;
129+
} else if constexpr (!(__compile_time_bool_of<_Args, false> && ...)) {
130+
const bool __done = (static_cast<bool>(static_cast<_Args &&>(__args)) && ...);
131+
if (__done) {
132+
stdexec::set_value(static_cast<_Receiver &&>(this->__receiver()));
133+
return;
134+
}
127135
}
128136
__destroy();
129137
STDEXEC_TRY {
@@ -163,16 +171,23 @@ namespace exec {
163171
// There's something funny going on with __if_c here. Use std::conditional_t instead. :-(
164172
std::conditional_t<
165173
((sizeof...(_Args) == 1) && (convertible_to<_Args, bool> && ...)),
166-
completion_signatures<>,
174+
std::conditional_t<
175+
(__compile_time_bool_of<_Args, false> && ...),
176+
completion_signatures<>,
177+
completion_signatures<set_value_t()>>,
167178
__mexception<_INVALID_ARGUMENT_TO_REPEAT_EFFECT_UNTIL_<>, _WITH_SENDER_<_Sender>>
168179
>;
169180

181+
template <class...>
182+
using __delete_set_value_t = completion_signatures<>;
183+
170184
template <class _Sender, class... _Env>
171185
using __completions_t = stdexec::transform_completion_signatures<
172186
__completion_signatures_of_t<__decay_t<_Sender> &, _Env...>,
173187
stdexec::transform_completion_signatures<
174188
__completion_signatures_of_t<stdexec::schedule_result_t<exec::trampoline_scheduler>, _Env...>,
175-
__eptr_completion
189+
__eptr_completion,
190+
__delete_set_value_t
176191
>,
177192
__mbind_front_q<__values_t, _Sender>::template __f
178193
>;
@@ -222,8 +237,8 @@ namespace exec {
222237
struct _never {
223238
template <class... _Args>
224239
STDEXEC_ATTRIBUTE(host, device, always_inline)
225-
constexpr auto operator()(_Args &&...) const noexcept -> bool {
226-
return false;
240+
constexpr std::false_type operator()(_Args &&...) const noexcept {
241+
return {};
227242
}
228243
};
229244

test/exec/test_repeat_effect_until.cpp

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -189,11 +189,23 @@ namespace {
189189
REQUIRE(called);
190190
}
191191

192+
template <typename Receiver>
193+
struct no_set_value_receiver : Receiver {
194+
explicit no_set_value_receiver(Receiver r) noexcept
195+
: Receiver(std::move(r)) {
196+
}
197+
void set_value() && noexcept = delete;
198+
};
199+
192200
TEST_CASE("repeat_effect repeats until an error is encountered", "[adaptors][repeat_effect]") {
193201
int counter = 0;
194202
ex::sender auto snd = exec::repeat_effect(
195203
succeed_n_sender(10, ex::set_error, std::string("error")) | ex::then([&] { ++counter; }));
196-
auto op = ex::connect(std::move(snd), expect_error_receiver{std::string("error")});
204+
static_assert(!all_contained_in<
205+
ex::completion_signatures<ex::set_value_t()>,
206+
ex::completion_signatures_of_t<decltype(snd), ex::env<>>>);
207+
auto op = ex::connect(
208+
std::move(snd), no_set_value_receiver(expect_error_receiver{std::string("error")}));
197209
ex::start(op);
198210
REQUIRE(counter == 10);
199211
}
@@ -202,7 +214,7 @@ namespace {
202214
int counter = 0;
203215
ex::sender auto snd = exec::repeat_effect(
204216
succeed_n_sender(10, ex::set_stopped) | ex::then([&] { ++counter; }));
205-
auto op = ex::connect(std::move(snd), expect_stopped_receiver{});
217+
auto op = ex::connect(std::move(snd), no_set_value_receiver(expect_stopped_receiver{}));
206218
ex::start(op);
207219
REQUIRE(counter == 10);
208220
}

0 commit comments

Comments
 (0)