Is it possible to apply a variadic function to a tuple with std::apply?
For example, the following code works fine with GCC 6.2.1:
void print_t(std::string i, std::string j) {
std::cout << i << " " << j << std::endl;
}
int main() {
std::tuple<std::string, std::string> t{"ab", "cd"};
std::experimental::apply(print_t, t);
return 0;
}
But if I try to apply a variadic function:
template<typename T>
void vprint(T && t) {
std::cout << std::forward<T>(t) << std::endl;
}
template<typename T, typename ... Ts>
void vprint(T && t, Ts ... ts) {
std::cout << std::forward<T>(t) << " ";
vprint<Ts...>(std::forward<Ts>(ts)...);
}
int main() {
std::tuple<std::string, std::string> t{"fd", "ab"};
std::experimental::apply(vprint, t);
return 0;
}
the compiler complains that it cannot deduce template arguments of vprint
. OK, let's write them explicitly:
std::experimental::apply(vprint<std::string, std::string>, t);
Now the compiler ends up with some obscure errors which expose standard library internals.
I wrote my own implementation of std::apply
in C++11 and I understand why it can't deduce arguments of the variadic function template. But, in theory, std::apply
has all the information needed for that deduction.
So is the application of variadic functions a not yet implemented feature in GCC6? Will C++17-compatible compilers allow such application?
If not, will they allow application of instantiated variadic template functions, like vprint<std::string, std::string>
?
Variadic functions are functions (e.g. std::printf) which take a variable number of arguments. To declare a variadic function, an ellipsis appears after the list of parameters, e.g. int printf(const char* format...);, which may be preceded by an optional comma.
Variadic templates are class or function templates, that can take any variable(zero or more) number of arguments. In C++, templates can have a fixed number of parameters only that have to be specified at the time of declaration.
With the variadic templates feature, you can define class or function templates that have any number (including zero) of parameters. To achieve this goal, this feature introduces a kind of parameter called parameter pack to represent a list of zero or more parameters for templates.
With vprint<std::string, std::string>
, you must pass r-value references, so
std::experimental::apply(vprint<std::string, std::string>, std::move(t));
The better way is to use functor (thanks to generic lambda):
std::experimental::apply([](auto&&... args) {
vprint(std::forward<decltype(args)>(args)...);
},
t);
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