Given:
A structure that stores information in order to construct any necessary type:
struct SomeThing{ //... };
A function that is capable of constructing any type required:
template<class T> T unpack(const SomeThing &){ std::cout << typeid(T).name() << std::endl; return T(); }
By the way, if you add the template<class T> operator T() const method to the structure with data, then this function will be static_cast
The function to call:
struct Bar{ }; int foo(int, double, const Bar &){ return 42; }
Call
int main(){ SomeThing params[10]; int answer = call(foo, params); std::cout << answer << std::endl; }
Decision:
Using std::index_sequence_for generate a sequence of indices (1, 2, 3 ...) equal in length to the list of arguments. And with the help of the design
foo(unpack<std::decay_t<Args>>(params[indexes])...);
force the compiler to generate something like this:
foo(unpack<std::decay_t<Arg1>>(params[1]), std::decay_t<Arg2>>(params[2]), ...);
Full code:
template<class Ret, class ...Args, std::size_t ...indexes> Ret call(Ret(*func)(Args...), SomeThing *params, const std::index_sequence<indexes...> &){ return func(unpack<std::decay_t<Args>>(params[indexes])...); } template<class Ret, class... Args> Ret call(Ret(*func)(Args...), SomeThing *params ){ return call(func, params, std::index_sequence_for<Args...>()); }
In the code there is a risk to fly beyond the bounds of the array, which, in fact, is an indefinite behavior. In my example, the size of the array is known at compile time, so you can pass the array by reference, and screw static_assert inside the call . But in general, prams can be allocated in a heap, so I did not add this check.
An example of checking the output of the array:
template<class Ret, class ...Args, std::size_t ...indexes, std::size_t size> Ret call(Ret(*func)(Args...), SomeThing (¶ms)[size], const std::index_sequence<indexes...> &){ static_assert(sizeof...(indexes) <= size, "array \"params\" is too small"); return func(unpack<std::decay_t<Args>>(params[indexes])...); } template<class Ret, class... Args, std::size_t size> Ret call(Ret(*func)(Args...), SomeThing (¶ms)[size]){ return call(func, params, std::index_sequence_for<Args...>()); }
Such code is more secure, but it won't work with dynamic arrays.
void* paramsand thenparams[0]? But the operator[]not applicable to a pointer of typevoid *. - AnTProxyClassZhbannikov: Give the definition ofProxyClass. If you can doProxyClass<&foo>, then it is completely incomprehensible how and where the unknownRetandArgs...will come fromArgs...- AnT