I am working on a custom FFI framework for a language and am running in to the issue of needing to instantiate templates in every possible branch of a comparison. When this becomes recursive the number of instantiations (and compile time) explodes. The implementation looks like this:
template<template<typename...> class F, typename ... Args>
struct TypeApp{
template<typename ... UArgs>
static auto apply(Type t, UArgs &&... uargs){
// all of the templates in these branches will be instantiated
if(t == type_<void>){ return F<Args..., void>::apply(std::forward<UArgs>(uargs)...); }
else if(t == type_<bool>){ return F<Args..., bool>::apply(std::forward<UArgs>(uargs)...); }
else if(t == type_<int>){ return F<Args..., int>::apply(std::forward<UArgs>(uargs)...); }
// ...
else{ assert(!"unrepresentable type"); }
}
};
template<typename...> struct FFICaller;
template<std::size_t ParamsRem, typename Ret, typename ... Params>
struct FFICaller<std::integral_constant<std::size_t, ParamsRem>, Ret, Params...>{
static auto apply(std::span<Type> params){
return TypeApp<FFICaller, std::integral_constant<std::size_t, ParamsRem-1>, Ret, Params...>
::apply(params[0], params.subspan(1));
}
};
template<typename Ret, typename ... Params>
struct FFICaller<std::integral_constant<std::size_t, 0>, Ret, Params...>{
static FFIFn apply(){
return +[](void *ptr, const std::vector<Value> &args){
// call 'ptr' with 'args'
};
}
};
So when I try to do something like this:
void doFFIStuff(void *ptr, Type result, const std::vector<Type> ¶ms){
FFIFn fn;
switch(params.size()){
case 1: fn = TypeApp<FFICaller, std::integral_constant<std::size_t, 1>>::apply(result, params); break;
case 2: fn = TypeApp<FFICaller, std::integral_constant<std::size_t, 2>>::apply(result, params); break;
case 3: fn = TypeApp<FFICaller, std::integral_constant<std::size_t, 3>>::apply(result, params); break;
case 4: fn = TypeApp<FFICaller, std::integral_constant<std::size_t, 4>>::apply(result, params); break;
default: assert(!"only up to 4 arguments currently supported");
};
}
My compiler freezes in shear terror at the mountain of code it has to process.
Is there some way I can restructure this code so that it isn't instantiating every branch multiple times?
EDIT:
Here is a minimal example on godbolt where if you comment out case 4 and 5 from the switch in getFFIFn
it will compile.