🐙

CppでCライクなほとんど全ての関数をvoid**引数の形式に変換するメタ関数

に公開
#include <cstring>
#include <tuple>
#include <type_traits>

template <typename T>
struct Func_type : Func_type<decltype(+std::declval<T>())> {};
template <typename R, typename... A> struct Func_type<R (*)(A...)> {
  using Return_type = R;
  using Args_tuple = std::tuple<A...>;
};

template <const auto kernel_impl>
constexpr auto wrap_kernel() -> void (*)(void **) {
  using args_t = typename Func_type<decltype(kernel_impl)>::Args_tuple;
  constexpr size_t nargs = std::tuple_size_v<args_t>;

  return +[](void **args_ptr) {
    args_t args;
    [&]<std::size_t... I>(std::index_sequence<I...>) {
      ((std::memcpy(&std::get<I>(args), args_ptr[I],
                    sizeof(std::tuple_element_t<I, args_t>))),
       ...);
    }(std::make_index_sequence<nargs>{});
    std::apply(kernel_impl, args);
  };
}

// 例
void kernel_X(int n, int *arr, int val) {
  // Do something
}
auto stub_kernel_X = wrap_kernel<kernel_X>();
static_assert(std::is_same<decltype(stub_kernel_X), void (*)(void**)>::value);

Discussion