Skip to content

Commit ee29d98

Browse files
Added test for noexcept lambda and updated fixed signal to not deduce function signature
1 parent 4468684 commit ee29d98

File tree

2 files changed

+38
-112
lines changed

2 files changed

+38
-112
lines changed

include/beman/execution/detail/bulk.hpp

Lines changed: 22 additions & 112 deletions
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,9 @@
44
#ifndef INCLUDED_BEMAN_EXECUTION_DETAIL_BULK
55
#define INCLUDED_BEMAN_EXECUTION_DETAIL_BULK
66

7-
#include "beman/execution/detail/callable.hpp"
8-
#include "beman/execution/detail/get_completion_signatures.hpp"
9-
#include "beman/execution/detail/nothrow_callable.hpp"
7+
#include <beman/execution/detail/get_completion_signatures.hpp>
8+
#include <beman/execution/detail/meta_combine.hpp>
9+
#include <beman/execution/detail/meta_unique.hpp>
1010
#include <beman/execution/detail/basic_sender.hpp>
1111
#include <beman/execution/detail/completion_signatures.hpp>
1212
#include <beman/execution/detail/completion_signatures_for.hpp>
@@ -69,125 +69,35 @@ struct impls_for<bulk_t> : ::beman::execution::detail::default_impls {
6969
}();
7070

7171
} catch (...) {
72-
73-
::beman::execution::set_error(std::move(rcvr), std::current_exception());
72+
if constexpr (not nothrow) {
73+
::beman::execution::set_error(std::move(rcvr), std::current_exception());
74+
}
7475
}
7576
} else {
7677
Tag()(std::move(rcvr), std::forward<Args>(args)...);
7778
}
7879
};
7980
};
8081

81-
template <typename T>
82-
struct print_type;
83-
84-
// Specialization to trigger a compile-time error and print the type
85-
template <typename T>
86-
struct print_type {
87-
static_assert(sizeof(T) == 0, "Debugging type...");
88-
};
89-
90-
template <typename T>
91-
concept function_constraint = std::is_function_v<T>;
92-
93-
template <typename T, typename... Args>
94-
struct function_type;
95-
96-
template <typename T, typename... Args>
97-
using function_type_t = typename function_type<T, Args...>::type;
98-
99-
template <typename>
100-
struct function_type_basis {};
101-
102-
template <typename T, typename...>
103-
struct function_type : function_type_basis<std::remove_cv_t<T>> {};
104-
105-
template <function_constraint T>
106-
struct function_type_basis<T> {
107-
using type = T;
108-
};
109-
110-
template <function_constraint T>
111-
struct function_type_basis<T*> {
112-
using type = T;
113-
};
114-
115-
template <function_constraint T>
116-
struct function_type_basis<T&> {
117-
using type = T;
118-
};
119-
120-
template <function_constraint T>
121-
struct function_type_basis<T&&> {
122-
using type = T;
123-
};
124-
125-
template <function_constraint T, typename C>
126-
struct function_type_basis<T C::*> {
127-
using type = T;
128-
};
129-
130-
template <typename, typename...>
131-
struct function_object_type {};
132-
133-
template <typename C, typename... Args>
134-
requires(bool(&C::operator()))
135-
struct function_object_type<C, Args...> : function_type_basis<decltype(&C::operator())> {};
136-
137-
template <typename F, typename... Args>
138-
requires std::is_class<std::remove_cvref_t<F>>::value
139-
struct function_type<F, Args...> : function_object_type<F, Args...> {};
140-
141-
template <typename>
142-
struct function_traits;
143-
144-
// Specialization for function types
145-
template <typename R, typename... Args, bool NoExcept>
146-
struct function_traits<R(Args...) noexcept(NoExcept)> {
147-
// The return type
148-
using return_type = R;
149-
// A tuple containing all argument types
150-
using argument_types = std::tuple<Args...>;
151-
152-
// The number of arguments
153-
static constexpr std::size_t arity = sizeof...(Args);
154-
};
155-
156-
template <typename R, typename... Args, bool NoExcept>
157-
struct function_traits<R(Args...) const noexcept(NoExcept)> {
158-
// The return type
159-
using return_type = R;
160-
// A tuple containing all argument types
161-
using argument_types = std::tuple<Args...>;
162-
// The number of arguments
163-
static constexpr std::size_t arity = sizeof...(Args);
164-
};
165-
166-
template <typename F, typename FunctionType>
167-
struct is_invocable_with;
168-
169-
template <typename F, typename... Args>
170-
struct is_invocable_with<F, std::tuple<Args...>> {
171-
static constexpr bool is_invocable = std::is_invocable_v<F, Args...>;
172-
static constexpr bool is_no_throw = ::beman::execution::detail::nothrow_callable<F, Args...>;
173-
};
174-
17582
template <typename, typename, typename>
17683
struct fixed_completions_helper;
17784

17885
template <typename F, typename Shape, typename... Args>
17986
struct fixed_completions_helper<F, Shape, completion_signatures<Args...>> {
180-
// get function signature
181-
using signature = function_type_t<F>;
182-
// break apart return type and args types
183-
using signature_helper = function_traits<signature>;
184-
// get arg types
185-
using function_args_type = signature_helper::argument_types;
186-
// print_type<function_args_type> debug;
187-
// check if function is well form
188-
static_assert(is_invocable_with<F, function_args_type>::is_invocable,
189-
"Error: The function is not callable with the given arguments.");
190-
using type = std::conditional_t<is_invocable_with<F, function_args_type>::is_no_throw,
87+
88+
template <typename, typename>
89+
struct may_throw;
90+
template <typename XF, typename Tag, typename... XArgs>
91+
struct may_throw<XF, Tag(XArgs...)> {
92+
static constexpr bool value = std::same_as<Tag, ::beman::execution::set_value_t> &&
93+
not::std::is_nothrow_invocable<XF, Shape, XArgs...>();
94+
};
95+
template <typename XF, typename... Sigs>
96+
struct may_throw<XF, completion_signatures<Sigs...>> {
97+
static constexpr bool value = (false || ... || may_throw<XF, Sigs>::value);
98+
};
99+
100+
using type = std::conditional_t<!may_throw<F, Args...>::value,
191101
completion_signatures<Args...>,
192102
completion_signatures<Args..., set_error_t(std::exception_ptr)>>;
193103
};
@@ -202,8 +112,8 @@ struct completion_signatures_for_impl<
202112
Env> {
203113

204114
using completions = decltype(get_completion_signatures(std::declval<Sender>(), std::declval<Env>()));
205-
using type = fixed_completions<F, Shape, completions>;
206-
// print_type<F> debug;
115+
using type = ::beman::execution::detail::meta::unique<
116+
::beman::execution::detail::meta::combine<fixed_completions<F, Shape, completions>>>;
207117
};
208118

209119
} // namespace beman::execution::detail

tests/beman/execution/exec-bulk.test.cpp

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
#include <beman/execution/detail/just.hpp>
1111
#include <vector>
1212

13+
namespace {
1314
auto test_bulk() {
1415
auto b0 = test_std::bulk(test_std::just(), 1, [](int) {});
1516

@@ -71,8 +72,23 @@ auto test_bulk_noexept() {
7172
beman::execution::completion_signatures<beman::execution::set_value_t()> >,
7273
"Completion signatures do not match!");
7374
static_assert(test_std::sender<decltype(b0)>);
75+
76+
int counter = 0;
77+
78+
auto b1 = test_std::bulk(test_std::just(), 5, [&](int i) noexcept { counter += i; });
79+
80+
static_assert(test_std::sender<decltype(b1)>);
81+
auto b1_env = test_std::get_env(b0);
82+
auto b1_completions = test_std::get_completion_signatures(b1, b1_env);
83+
static_assert(std::is_same_v<decltype(b1_completions),
84+
beman::execution::completion_signatures<beman::execution::set_value_t()> >,
85+
"Completion signatures do not match!");
86+
test_std::sync_wait(b1);
87+
ASSERT(counter == 10);
7488
}
7589

90+
} // namespace
91+
7692
TEST(exec_bulk) {
7793

7894
try {

0 commit comments

Comments
 (0)