Improve compile-time safety of coral::callable
continuous-integration/drone/push Build is failing Details

This commit is contained in:
kayomn 2023-02-22 22:59:33 +00:00
parent 02d4d56f35
commit f9ac5831cf
1 changed files with 11 additions and 9 deletions

View File

@ -426,12 +426,12 @@ export namespace coral {
* Type-erasing wrapper for functor types that have a call operator with a return value * Type-erasing wrapper for functor types that have a call operator with a return value
* matching `return_value` and arguments matching `argument_values`. * matching `return_value` and arguments matching `argument_values`.
*/ */
template<typename return_value, typename... argument_values> struct callable<return_value(argument_values...)> { template<typename returns, typename... arguments> struct callable<returns(arguments...)> {
using function = return_value(*)(argument_values...); using function = returns(*)(arguments...);
callable(function callable_function) { callable(function callable_function) {
this->dispatcher = [](u8 const * userdata, argument_values... arguments) -> return_value { this->dispatcher = [](u8 const * context, arguments... dispatch_arguments) -> returns {
return (*reinterpret_cast<function const *>(userdata))(arguments...); return (*reinterpret_cast<function const *>(context))(dispatch_arguments...);
}; };
new (this->capture) function{callable_function}; new (this->capture) function{callable_function};
@ -440,21 +440,23 @@ export namespace coral {
callable(callable const &) = delete; callable(callable const &) = delete;
template<typename functor> callable(functor const & callable_functor) { template<typename functor> callable(functor const & callable_functor) {
this->dispatcher = [](u8 const * userdata, argument_values... arguments) -> return_value { static_assert(sizeof(functor) < capture_size);
return (*reinterpret_cast<functor const*>(userdata))(arguments...);
this->dispatcher = [](u8 const * context, arguments... dispatch_arguments) -> returns {
return (*reinterpret_cast<functor const*>(context))(dispatch_arguments...);
}; };
new (this->capture) functor{callable_functor}; new (this->capture) functor{callable_functor};
} }
return_value operator()(argument_values const &... arguments) const { returns operator()(arguments const &... call_arguments) const {
return this->dispatcher(this->capture, arguments...); return this->dispatcher(this->capture, call_arguments...);
} }
private: private:
static constexpr usize capture_size = 24; static constexpr usize capture_size = 24;
return_value(* dispatcher)(u8 const * userdata, argument_values... arguments); returns(* dispatcher)(u8 const *, arguments...);
u8 capture[capture_size]; u8 capture[capture_size];
}; };