Implement a generic forwarding function that replaces the manually written ones.

This commit is contained in:
King_DuckZ 2020-04-26 10:49:57 +02:00
parent 3142e4c4ce
commit 30975c1405

View file

@ -53,27 +53,21 @@ namespace wren {
define_method_info(resolve_module_fn, resolve_module, const char*, const char*, const char*);
define_method_info(load_module_fn, load_module, char*, VM*, const char*);
namespace fwd {
template <typename T>
inline void write_fn (Configuration& obj, VM* vm, const char* text) {
reinterpret_cast<T&>(obj).write_fn(vm, text);
template <typename T, typename F> struct AnyFunctionWrap;
template <typename T, typename R, typename... Args>
struct AnyFunctionWrap<T, R(T::*)(Args...)> {
template <R(T::*M)(Args...)>
inline static R call(Configuration& obj, Args... args) {
return (reinterpret_cast<T&>(obj).*M)(args...);
}
template <typename T>
inline void error_fn (Configuration& obj, VM* vm, ErrorType et, const char* module, int line, const char* message) {
reinterpret_cast<T&>(obj).error_fn(vm, et, module, line, message);
};
template <typename T, typename R, typename... Args>
struct AnyFunctionWrap<T, R(*)(Args...)> {
template <R(*M)(Args...)>
inline static R call(Configuration&, Args... args) {
return (*M)(args...);
}
template <typename T>
inline const char* resolve_module_fn (Configuration& obj, VM* vm, void* memory, std::size_t new_size) {
return reinterpret_cast<T&>(obj).resolve_module_fn(vm, memory, new_size);
}
template <typename T>
inline char* load_module_fn (Configuration& obj, VM* vm, const char* name) {
return reinterpret_cast<T&>(obj).load_module_fn(vm, name);
}
} //namespace fwd
};
} //namespace detail
template <typename T>
@ -89,12 +83,12 @@ namespace wren {
ret.vm = this;
if constexpr (method_write::exists<T>::value)
ret.write_fn = &detail::fwd::write_fn<T>;
ret.write_fn = &detail::AnyFunctionWrap<T, decltype(&T::write_fn)>::template call<&T::write_fn>;
else
ret.write_fn = nullptr;
if constexpr (method_error::exists<T>::value)
ret.error_fn = &detail::fwd::error_fn<T>;
ret.error_fn = &detail::AnyFunctionWrap<T, decltype(&T::error_fn)>::template call<&T::error_fn>;
else
ret.error_fn = nullptr;
@ -105,12 +99,12 @@ namespace wren {
static_assert(not method_reallocate::exists<T>::value or method_reallocate::is_static<T>::value, "Realloc function must be a static function");
if constexpr (method_resolve_module::exists<T>::value)
ret.resolve_module_fn = &detail::fwd::resolve_module_fn<T>;
ret.resolve_module_fn = &detail::AnyFunctionWrap<T, decltype(&T::resolve_module_fn)>::template call<&T::resolve_module_fn>;
else
ret.resolve_module_fn = nullptr;
if constexpr (method_load_module::exists<T>::value)
ret.load_module_fn = &detail::fwd::load_module_fn<T>;
ret.load_module_fn = &detail::AnyFunctionWrap<T, decltype(&T::load_module_fn)>::template call<&T::load_module_fn>;
else
ret.load_module_fn = nullptr;