I was trying to write a function to forward arguments for a variadic template function, similar to std::invoke
. Here is the code:
#include <functional>
template<class... Args>
void f(Args&&... args) { }
template<template<class...> class F, class... Args>
void invoke(F<Args...> f, Args&&... args) {
f(std::forward<decltype(args)>(args)...);
}
int main() {
invoke(f, 1, 2, 3);
std::invoke(f, 1, 2, 3);
}
However, both my invoke
and std::invoke
fails to compile.
g++ complains that it couldn't deduce template parameter template<class ...> class F
. So is it possible to invoke a variadic template function without explicit template specialization?
Note that a function template represents a family of functions. When you, say, pass it to a function it needs to resolve to a certain specialization of the template. I understand what you're trying to do with the parameter of your custom invoke
(capture the function template as a template) but sadly this will work only with class templates, never function templates.
You'd need another level of indirection. Namely, passing a functor or lambda that forwards the arguments to f
:
invoke([](auto&&... xs) { f(decltype(xs)(xs)...); }, 1, 2, 3);
The difference is that now the argument is a class non-template so it can be deduced by your invoke
.
With this change comes the additional requirement that you change your function to fully deduce the first parameter:
template<class F, class... Args>
void invoke(F&& f, Args&&... args) {
f(forward<Args>(args)...);
}
If function is wrapped inside of template class then you should be able to pass this template class as template template parameter:
#include <functional>
template<class... Args> struct Wrap
{
static void f(Args&&... args) { }
};
template<template<class...> class F, class... Args>
void invoke(Args&&... args) {
Wrap<Args...>::f(std::forward<Args>(args)...);
}
int main() {
invoke<Wrap>(1, 2, 3);
}
online compiler
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