Last active
October 7, 2023 13:20
-
-
Save JohnnyonFlame/ab2eb12654a22e4935715baf2cb997a9 to your computer and use it in GitHub Desktop.
Atuomatic dispatch from variadic/array procedures (from fake_jni).
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Automatic generator for function dispatch | |
template <auto F> | |
struct dispatch | |
{ | |
// The following nested structure does two things: | |
// 1: Unwraps details about the function (e.g. argument type list, | |
// return type) with the template. | |
// 2: Implements the dispatcher as needed (will extract from va_list and push) | |
// into the function call that is being wrapped, taking care to also return | |
// the value if applicable. | |
template<typename S> | |
struct unwrap; | |
template<typename R, typename... Args> | |
struct unwrap<R(Args...)> | |
{ | |
// brace-initialization is necessary to ensure the parameters are | |
// evaluated in left-to-right order on gcc... | |
struct BraceCall | |
{ | |
R ret; | |
template <typename... Arg> | |
BraceCall(Arg... args) : ret( F(args...) ) { }; | |
}; | |
struct BraceCallVoid | |
{ | |
template <typename... Arg> | |
BraceCallVoid(Arg... args) { F(args...); }; | |
}; | |
public: | |
static R dispatch_v(va_list va) | |
{ | |
if constexpr (std::is_same_v<R, void>) { | |
BraceCallVoid{(Args)va_arg(va, Args)...}; | |
} else { | |
return BraceCall{(Args)va_arg(va, Args)...}.ret; | |
} | |
} | |
static R dispatch_a(jvalue *arr) | |
{ | |
auto get = [&]() { return arr++; }; | |
if constexpr (std::is_same_v<R, void>) { | |
BraceCallVoid{(*((Args*)get()))...}; | |
} else { | |
return BraceCall{*((Args*)get())...}.ret; | |
} | |
} | |
}; | |
// Unwrap the function | |
using sig = unwrap<typename std::remove_pointer<decltype(F)>::type>; | |
// Expose the dispatch function :) | |
static constexpr auto vargs = sig::dispatch_v; | |
static constexpr auto aargs = sig::dispatch_a; | |
}; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
usage: