I have two functions f
and g
. f
calculates it's return value asynchronously and returns a future. Now, based on several return values of f
, I want to call g
, but I want to make sure that the computations of the values of f
happen in parallel.
Consider the following code:
template <typename T>
std::future<T> f(T& t);
template <typename... T>
void g(T&&... t)
template <typename... T>
void call_wrapper(T&&... t) {
auto f1 = f(t1); // How do I set the values of f1... fn
auto f2 = f(t2);
...
g(f1.get(), f2.get()....); // How do I call g
}
How can I unpack the types from the variadic template T
of the call_wrapper
function?
Parameter pack. (since C++11) sizeof... (C++11) A template parameter pack is a template parameter that accepts zero or more template arguments (non-types, types, or templates). A function parameter pack is a function parameter that accepts zero or more function arguments. A template with at least one parameter pack is called a variadic template .
In a primary class template, the template parameter pack must be the final parameter in the template parameter list. In a function template, the template parameter pack may appear earlier in the list provided that all following parameters can be deduced from the function arguments, or have default arguments:
A function parameter pack is a function parameter that accepts zero or more function arguments. A template with at least one parameter pack is called a variadic template . Template parameter pack (appears in alias template, class template, variable template and function template parameter lists) type ... Args(optional) typename|class ...
We can use * to unpack the list so that all elements of it can be passed as different parameters.
[Edit2: I guess i misunderstood the question, i forgot subzero wanted to return std::future
s and simply thought that the only problem was the parameter pack syntax.
Hopefully, using an helper function as in my first edit should work though]
You can simply do:
template <typename... T>
void call_wrapper(T&&... t) {
g(f(std::forward<T>(t)).get()...);
}
Unless i misunderstood what you want to do.
Edit1: if you want to do something else, you can divide the function in two calls, like this:
template<typename... T>
void helper(T&&... t) {
// ...
g(std::forward<T>(t).get()...);
}
template <typename... T>
void call_wrapper(T&&... t) {
helper(f(std::forward<T>(t))...);
}
Here's a quick solution storing the std::future
s in a std::tuple
:
template <class T, std::size_t... Idx>
void callG(T &tuple, std::index_sequence<Idx...>) {
g(std::get<Idx>(tuple).get()...);
}
template <typename... T>
void call_wrapper(T&&... t) {
auto results = std::make_tuple(f(std::forward<T>(t))...);
callG(results, std::index_sequence_for<T...>{});
}
Live on Coliru
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With