Consider the case of a templated function with variadic template arguments:
template Tret func(const T&... t);
Extending on @David's solution, you can write a recursive template that
integer_sequence semanticsint N to count recursive iterationsE.g.:
template
struct static_functor {
template
static inline auto apply(const std::tuple& t, Args_tmp... args)
-> decltype(func(std::declval()...)) {
return static_functor::apply(t, args...,
std::get(t));
}
template
static inline auto apply(const std::tuple& t, T... args)
-> decltype(func(args...)) {
return func(args...);
}
};
static_functor::apply(my_tuple);
Alternatively if your functor is not defined at compile-time (e.g., a non-constexpr functor instance, or a lambda expression), you can use it as a function parameter instead of a class template parameter, and in fact remove the containing class entirely:
template
inline auto apply_functor(F&& func, const std::tuple& t,
Args_tmp... args) -> decltype(func(std::declval()...)) {
return apply_functor(func, t, args..., std::get(t));
}
template
inline auto apply_functor(F&& func, const std::tuple& t,
T... args) -> decltype(func(args...)) {
return func(args...);
}
apply_functor(&myFunc, my_tuple);
For pointer-to-member-function callables, you can adjust either of the above code pieces similarly as in @David's answer.
Explanation
In reference to the second piece of code, there are two template functions: the first one takes the functor func, the tuple t with types T..., and a parameter pack args of types Args_tmp.... When called, it recursively adds the objects from t to the parameter pack one at a time, from beginning (0) to end, and calls the function again with the new incremented parameter pack.
The second function's signature is almost identical to the first, except that it uses type T... for the parameter pack args. Thus, once args in the first function is completely filled with the values from t, it's type will be T... (in psuedo-code, typeid(T...) == typeid(Args_tmp...)), and thus the compiler will instead call the second overloaded function, which in turn calls func(args...).
The code in the static functor example works identically, with the functor instead used as a class template argument.