@@ -87,30 +87,107 @@ struct print_type {
8787 static_assert (sizeof (T) == 0 , " Debugging type..." );
8888};
8989
90- /* template <typename, typename, typename, typename,typename>
91- struct fixed_completions_helper;
92- template <typename F, typename Shape,typename Sender,typename Env, typename... Args>
93- struct fixed_completions_helper<F, Shape,Sender, Env, completion_signatures<Args...>> {
94- using completions = ::beman::execution::value_types_of_t<Sender,Env>;
95- static_assert(std::is_invocable_v<F, completions>,"Error: The function is not callable with the given arguments.");
96- using type = std::conditional_t<::beman::execution::detail::nothrow_callable<F, Args ...>,
97- completion_signatures<Args...>,
98- completion_signatures<Args..., set_error_t(std::exception_ptr)>>;
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;
99108};
100109
101- template <typename F, typename Shape, typename Sender , typename Env, typename completions>
102- using fixed_completions = typename fixed_completions_helper<F, Shape, Sender , Env, completions>::type;*/
110+ template <function_constraint T>
111+ struct function_type_basis <T*> {
112+ using type = T;
113+ };
103114
115+ template <function_constraint T>
116+ struct function_type_basis <T&> {
117+ using type = T;
118+ };
104119
120+ template <function_constraint T>
121+ struct function_type_basis <T&&> {
122+ using type = T;
123+ };
105124
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+ };
106174
107175template <typename , typename , typename >
108176struct fixed_completions_helper ;
109177
110178template <typename F, typename Shape, typename ... Args>
111179struct fixed_completions_helper <F, Shape, completion_signatures<Args...>> {
112- // static_assert(std::is_invocable_v<F, Shape, Args...>,"Error: The function is not callable with the given arguments.");
113- using type = std::conditional_t <::beman::execution::detail::nothrow_callable<F, 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,
114191 completion_signatures<Args...>,
115192 completion_signatures<Args..., set_error_t (std::exception_ptr)>>;
116193};
@@ -123,11 +200,10 @@ struct completion_signatures_for_impl<
123200 ::beman::execution::detail::
124201 basic_sender<::beman::execution::detail::bulk_t , ::beman::execution::detail::product_type<Shape, F>, Sender>,
125202 Env> {
126-
127203
128204 using completions = decltype (get_completion_signatures(std::declval<Sender>(), std::declval<Env>()));
129205 using type = fixed_completions<F, Shape, completions>;
130- // print_type<type > debug;
206+ // print_type<F > debug;
131207};
132208
133209} // namespace beman::execution::detail
0 commit comments