It's definitely possible, but you cannot determine the safety of doing it at compile time. This is, as WhozCraig says, because the vector lacks a compile-time size.
I'm still trying to earn my template meta programming wings, so I may have done things a little unusually. But the core idea here is to have a function template recursively invoke itself with the next item in the vector until it has built up a parameter pack with the desired parameters. Once it has that, it's easy to pass it to the function in question.
The implementation of the core here is in apply_first_n, which accepts a target std::function<R(Ps...)>, and a vector, and a parameter pack of Ts.... When Ts... is shorter than Ps... it builds up the pack; once it's the same size, it passes it to the function.
template <typename R, typename... Ps, typename... Ts>
typename std::enable_if<sizeof...(Ps) == sizeof...(Ts), R>::type
apply_first_n(std::function<R(Ps...)> f, const std::vector<int> &v, Ts&&... ts)
{
if (sizeof...(Ts) > v.size())
throw std::out_of_range("vector too small for function");
return f(std::forward<Ts>(ts)...);
}
template <typename R, typename... Ps, typename... Ts>
typename std::enable_if<sizeof...(Ps) != sizeof...(Ts), R>::type
apply_first_n(std::function<R(Ps...)> f, const std::vector<int> &v, Ts&&... ts)
{
const int index = sizeof...(Ps) - sizeof...(Ts) - 1;
static_assert(index >= 0, "incompatible function parameters");
return apply_first_n(f, v, *(std::begin(v) + index), std::forward<Ts>(ts)...);
}
You call this with, e.g., apply_first_n(std::function<int(int, int)>(f), v);. In the live example, make_fn just makes the conversion to std::function easier, and ProcessInts is a convenient testing function.
I'd love to figure out how to avoid the use of std::function, and to repair any other gross inefficiencies that exist. But I'd say this is proof that it's possible.
For reference, I took the above approach further, handling set, vector, tuple, and initializer_list, as well as others that match the right interfaces. Removing std::function seemed to require the func_info traits class, as well as several overloads. So while this extended live example is definitely more general, I'm not sure I'd call it better.
passfor a reasonable range of numbers offuncarguments - can even be done with the preprocessor. Plenty of examples of this kind of thing in Alexandrescu's Loki library. It does mean you have some arbitrary limit on the number of arguments you support, after which you get a compilation error. - Tony Delroy