Expanding an STL container into a variadic template
c++, c++11, stl, templates, variadic-templates
Solution
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.
Problem
To keep things generic and straightforward, say that I have a std::vector of integers, such as: ``` std::vector<int> v; ``` Now, what I am wondering is, is it possible to take n (where n is a constant known at compile time) values from v and pass them to an arbitrary function? I know that this is doable with variadic templates: ``` template<typename... T> void pass(void (*func)(int, int, int), T... t) { func(t...); } ``` And then we hope 'pass' is called with exactly 3 integers. The details don't matter so much. What I am wondering is, is the following somehow doable: ``` void pass(void (*func)(int, int, int), std::vector<int> &t) { auto iter = t.begin(); func((*iter++)...); } ``` Where ... is being used like a variadic template? Essentially, I'm asking if I can - Expand a std::vector or other STL container into a variadic template with n elements - And/or in-order pass these values directly to a function being called Is this possible with C++11? Noting that I need this to work on MSVC v120/VS2013.