Skip to content

Commit 5ad85cb

Browse files
authored
Merge pull request #23 from beman-project/fix-then-result
fixed then exceptions
2 parents df83e34 + e93c18d commit 5ad85cb

File tree

2 files changed

+80
-26
lines changed

2 files changed

+80
-26
lines changed

include/beman/execution26/detail/then.hpp

+52-12
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
#include <beman/execution26/detail/impls_for.hpp>
1414
#include <beman/execution26/detail/make_sender.hpp>
1515
#include <beman/execution26/detail/meta_transform.hpp>
16+
#include <beman/execution26/detail/meta_combine.hpp>
1617
#include <beman/execution26/detail/meta_unique.hpp>
1718
#include <beman/execution26/detail/movable_value.hpp>
1819
#include <beman/execution26/detail/sender.hpp>
@@ -93,10 +94,17 @@ namespace beman::execution26::detail
9394
}
9495
catch (...)
9596
{
96-
::beman::execution26::set_error(
97-
::std::move(receiver),
98-
::std::current_exception()
99-
);
97+
if constexpr (not noexcept(
98+
::std::invoke(::std::move(fun),
99+
::std::forward<Args>(args)...)
100+
101+
))
102+
{
103+
::beman::execution26::set_error(
104+
::std::move(receiver),
105+
::std::current_exception()
106+
);
107+
}
100108
}
101109
}
102110
else
@@ -123,6 +131,16 @@ namespace beman::execution26::detail
123131
using type = Completion;
124132
};
125133

134+
template <typename Fun, typename Completion, typename... T>
135+
struct then_transform<Fun, Completion, Completion(T...)>
136+
{
137+
using type =
138+
typename ::beman::execution26::detail::then_set_value<
139+
::beman::execution26::detail::call_result_t<Fun, T...>
140+
>::type
141+
;
142+
};
143+
126144
template <typename Fun, typename Replace>
127145
struct then_transform_t
128146
{
@@ -132,12 +150,23 @@ namespace beman::execution26::detail
132150
::type;
133151
};
134152

135-
template <typename Fun, typename Completion, typename... T>
136-
struct then_transform<Fun, Completion, Completion(T...)>
153+
template <typename, typename, typename>
154+
struct then_exception_fun: ::std::false_type {};
155+
template <typename Comp, typename Fun, typename... A>
156+
struct then_exception_fun<Comp, Fun, Comp(A...)>
157+
: ::std::bool_constant<not noexcept(::std::declval<Fun>()(::std::declval<A>()...))>
137158
{
138-
using type = typename ::beman::execution26::detail::then_set_value<
139-
::beman::execution26::detail::call_result_t<Fun, T...>
140-
>::type;
159+
};
160+
161+
template <typename, typename, typename>
162+
struct then_exception: ::std::false_type {};
163+
template <typename Comp, typename Fun, typename Completion, typename... Completions>
164+
struct then_exception<Comp, Fun, ::beman::execution26::completion_signatures<Completion, Completions...>>
165+
{
166+
static constexpr bool value{
167+
then_exception_fun<Comp, Fun, Completion>::value
168+
|| then_exception<Comp, Fun, ::beman::execution26::completion_signatures<Completions...>>::value
169+
};
141170
};
142171

143172
template <typename Completion, typename Fun, typename Sender, typename Env>
@@ -151,9 +180,20 @@ namespace beman::execution26::detail
151180
>
152181
{
153182
using type = ::beman::execution26::detail::meta::unique<
154-
::beman::execution26::detail::meta::transform<
155-
::beman::execution26::detail::then_transform_t<Fun, Completion>::template transform,
156-
::beman::execution26::completion_signatures_of_t<Sender, Env>
183+
::beman::execution26::detail::meta::combine<
184+
::beman::execution26::detail::meta::transform<
185+
::beman::execution26::detail::then_transform_t<Fun, Completion>::template transform,
186+
::beman::execution26::completion_signatures_of_t<Sender, Env>
187+
>,
188+
::std::conditional_t<
189+
::beman::execution26::detail::then_exception<
190+
Completion,
191+
Fun,
192+
::beman::execution26::completion_signatures_of_t<Sender, Env>
193+
>::value,
194+
::beman::execution26::completion_signatures<::beman::execution26::set_error_t(::std::exception_ptr)>,
195+
::beman::execution26::completion_signatures<>
196+
>
157197
>
158198
>;
159199
};

src/beman/execution26/tests/exec-then.pass.cpp

+28-14
Original file line numberDiff line numberDiff line change
@@ -68,19 +68,19 @@ namespace
6868

6969
auto test_then_type() -> void
7070
{
71-
test_then_type< test_std::set_value_t()>(test_std::just(0) | test_std::then([](auto){}));
72-
test_then_type< test_std::set_value_t(int)>(test_std::just() | test_std::then([]{ return 0; }));
73-
test_then_type< test_std::set_error_t(int)>(test_std::just_error(0) | test_std::then([]{ return 0; }));
74-
test_then_type< test_std::set_stopped_t()>(test_std::just_stopped() | test_std::then([]{ return 0; }));
71+
test_then_type< test_std::set_value_t()>(test_std::just(0) | test_std::then([](auto)noexcept{}));
72+
test_then_type< test_std::set_value_t(int)>(test_std::just() | test_std::then([]()noexcept{ return 0; }));
73+
test_then_type< test_std::set_error_t(int)>(test_std::just_error(0) | test_std::then([]()noexcept{ return 0; }));
74+
test_then_type< test_std::set_stopped_t()>(test_std::just_stopped() | test_std::then([]()noexcept{ return 0; }));
7575

76-
test_then_type< test_std::set_value_t()>(test_std::just() | test_std::upon_error([]{ return 0; }));
76+
test_then_type< test_std::set_value_t()>(test_std::just() | test_std::upon_error([]()noexcept{ return 0; }));
7777
test_then_type< test_std::set_value_t(int)>(test_std::just_error(error{})
78-
| test_std::upon_error([](error){ return 0; }));
79-
test_then_type< test_std::set_stopped_t()>(test_std::just_stopped() | test_std::upon_error([]{}));
78+
| test_std::upon_error([](error)noexcept{ return 0; }));
79+
test_then_type< test_std::set_stopped_t()>(test_std::just_stopped() | test_std::upon_error([]()noexcept{}));
8080

81-
test_then_type< test_std::set_value_t(int)>(test_std::just(0) | test_std::upon_stopped([]{}));
82-
test_then_type< test_std::set_error_t(int)>(test_std::just_error(0) | test_std::upon_stopped([]{}));
83-
test_then_type< test_std::set_value_t()>(test_std::just_stopped() | test_std::upon_stopped([]{}));
81+
test_then_type< test_std::set_value_t(int)>(test_std::just(0) | test_std::upon_stopped([]()noexcept{}));
82+
test_then_type< test_std::set_error_t(int)>(test_std::just_error(0) | test_std::upon_stopped([]()noexcept{}));
83+
test_then_type< test_std::set_value_t()>(test_std::just_stopped() | test_std::upon_stopped([]()noexcept{}));
8484
}
8585

8686
auto test_then_multi_type() -> void
@@ -102,7 +102,8 @@ namespace
102102
test_then_type<
103103
test_std::set_value_t(bool),
104104
test_std::set_error_t(error),
105-
test_std::set_stopped_t()
105+
test_std::set_stopped_t(),
106+
test_std::set_error_t(::std::exception_ptr)
106107
>(sender<
107108
test_std::set_value_t(),
108109
test_std::set_value_t(int, int),
@@ -113,7 +114,8 @@ namespace
113114
test_std::set_value_t(),
114115
test_std::set_value_t(int, int),
115116
test_std::set_value_t(bool),
116-
test_std::set_stopped_t()
117+
test_std::set_stopped_t(),
118+
test_std::set_error_t(::std::exception_ptr)
117119
>(sender<
118120
test_std::set_value_t(),
119121
test_std::set_value_t(int, int),
@@ -123,7 +125,8 @@ namespace
123125
test_then_type<
124126
test_std::set_value_t(),
125127
test_std::set_value_t(int, int),
126-
test_std::set_stopped_t()
128+
test_std::set_stopped_t(),
129+
test_std::set_error_t(::std::exception_ptr)
127130
>(sender<
128131
test_std::set_value_t(),
129132
test_std::set_value_t(int, int),
@@ -140,7 +143,7 @@ namespace
140143
test_std::set_value_t(int, int),
141144
test_std::set_error_t(error),
142145
test_std::set_stopped_t()
143-
>() | test_std::upon_stopped([]{}));
146+
>() | test_std::upon_stopped([]()noexcept{}));
144147
test_then_type<
145148
test_std::set_value_t(),
146149
test_std::set_value_t(int, int),
@@ -150,6 +153,17 @@ namespace
150153
test_std::set_value_t(int, int),
151154
test_std::set_error_t(error),
152155
test_std::set_stopped_t()
156+
>() | test_std::upon_stopped([]()noexcept{}));
157+
test_then_type<
158+
test_std::set_value_t(),
159+
test_std::set_value_t(int, int),
160+
test_std::set_error_t(error),
161+
test_std::set_error_t(::std::exception_ptr)
162+
>(sender<
163+
test_std::set_value_t(),
164+
test_std::set_value_t(int, int),
165+
test_std::set_error_t(error),
166+
test_std::set_stopped_t()
153167
>() | test_std::upon_stopped([]{}));
154168
}
155169

0 commit comments

Comments
 (0)