Skip to content

Commit 0c627cd

Browse files
committed
Implement execution::just_error factory
1 parent 4e95646 commit 0c627cd

File tree

2 files changed

+79
-0
lines changed

2 files changed

+79
-0
lines changed

stl/inc/execution

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5461,6 +5461,56 @@ namespace execution {
54615461
(is_nothrow_constructible_v<remove_cvref_t<_Types>, _Types> && ...)) {
54625462
return {_STD make_tuple(_STD forward<_Types>(_Values)...)};
54635463
}
5464+
5465+
template <class _Error>
5466+
struct _Just_error_sender {
5467+
_Error _Err;
5468+
5469+
template <template <class...> class _Tuple, template <class...> class _Variant>
5470+
using value_types = _Variant<>;
5471+
5472+
template <template <class...> class _Variant>
5473+
using error_types = _Variant<_Error, exception_ptr>;
5474+
5475+
static const constexpr auto sends_done = false;
5476+
5477+
template <receiver _Receiver>
5478+
requires receiver<_Receiver, _Error>
5479+
struct operation_state {
5480+
_Error _Err;
5481+
_Receiver _Rec;
5482+
5483+
friend constexpr void tag_invoke(start_t, operation_state& _State) noexcept {
5484+
_EXEC set_error(_STD move(_State._Rec), _STD move(_State._Err));
5485+
}
5486+
};
5487+
5488+
// clang-format off
5489+
template <receiver _Receiver>
5490+
requires receiver<_Receiver, _Error> && copyable<_Error>
5491+
_NODISCARD friend constexpr auto tag_invoke(connect_t, const _Just_error_sender& _Sender, _Receiver&& _Rec) //
5492+
noexcept(is_nothrow_copy_constructible_v<_Error> //
5493+
&& is_nothrow_constructible_v<remove_cvref_t<_Receiver>, _Receiver>) {
5494+
// clang-format on
5495+
return operation_state<remove_cvref_t<_Receiver>>{_Sender._Err, _STD forward<_Receiver>(_Rec)};
5496+
}
5497+
5498+
// clang-format off
5499+
template <receiver _Receiver>
5500+
requires receiver<_Receiver, _Error>
5501+
_NODISCARD friend constexpr auto tag_invoke(connect_t, _Just_error_sender&& _Sender, _Receiver&& _Rec) noexcept(
5502+
is_nothrow_move_constructible_v<_Error> //
5503+
&& is_nothrow_constructible_v<remove_cvref_t<_Receiver>, _Receiver>) {
5504+
// clang-format on
5505+
return operation_state<remove_cvref_t<_Receiver>>{_STD move(_Sender._Err), _STD forward<_Receiver>(_Rec)};
5506+
}
5507+
};
5508+
5509+
template <_Movable_value _Error>
5510+
_NODISCARD constexpr _Just_error_sender<remove_cvref_t<_Error>> just_error(_Error&& _Err) noexcept(
5511+
is_nothrow_constructible_v<remove_cvref_t<_Error>, _Error>) {
5512+
return {_STD forward<_Error>(_Err)};
5513+
}
54645514
} // namespace execution
54655515
#endif // __cpp_lib_executors
54665516
_STD_END

tests/std/tests/P2300R2_executors_factories/test.cpp

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -98,7 +98,36 @@ constexpr bool test_just() {
9898
return true;
9999
}
100100

101+
constexpr bool test_just_error() {
102+
{
103+
Tracker tracker;
104+
typed_sender auto sender = execution::just_error(CustomError{});
105+
operation_state auto state = connect(sender, nothrow_receiver<>{tracker});
106+
assert(!tracker.set_error_called);
107+
start(state);
108+
assert(tracker.set_error_called);
109+
}
110+
111+
{
112+
Tracker tracker;
113+
operation_state auto state = connect(execution::just_error(CustomError{}), nothrow_receiver<>{tracker});
114+
assert(!tracker.set_error_called);
115+
start(state);
116+
assert(tracker.set_error_called);
117+
}
118+
119+
{ // Ensure that we cannot connect a receiver with the wrong error type
120+
typed_sender auto sender = execution::just_error(Dummy{});
121+
static_assert(!invocable<execution::connect_t, decltype(sender), nothrow_receiver<>>);
122+
}
123+
124+
return true;
125+
}
126+
101127
int main() {
102128
test_just();
103129
static_assert(test_just());
130+
131+
test_just_error();
132+
static_assert(test_just_error());
104133
}

0 commit comments

Comments
 (0)