Reputation: 605
I'm trying to make a function that takes a variable number of parameters of any type, but even the simple example I made is getting an error
#include <iostream>
#include <functional>
template<class... Ts>
void callFunction(const std::function<void(Ts...)>& function, Ts... parameters)
{
function(parameters...);
}
void myFunc(const std::string& output)
{
std::cout << output << std::endl;
}
int main()
{
callFunction<const std::string&>(&myFunc, "Hello world");
return 0;
}
When I run the above code in Ideone, I get this error:
prog.cpp: In function ‘int main()’:
prog.cpp:17:57: error: no matching function for call to ‘callFunction(void (*)(const string&), const char [12])’
callFunction<const std::string&>(&myFunc, "Hello world");
^
prog.cpp:5:6: note: candidate: template<class ... Ts> void callFunction(const std::function<void(Ts ...)>&, Ts ...)
void callFunction(const std::function<void(Ts...)>& function, Ts... parameters)
^~~~~~~~~~~~
prog.cpp:5:6: note: template argument deduction/substitution failed:
prog.cpp:17:57: note: mismatched types ‘const std::function<void(Ts ...)>’ and ‘void (*)(const string&) {aka void (*)(const std::__cxx11::basic_string<char>&)}’
callFunction<const std::string&>(&myFunc, "Hello world");
Upvotes: 1
Views: 869
Reputation: 66210
A simple suggestion: receive the callable as a deduced typename, not as a std::function
I mean (adding also perfect forwarding)
template <typename F, typename ... Ts>
void callFunction(F const & func, Ts && ... pars)
{ func(std::forward<Ts>(pars)...); }
and, obviously, call it without explicating nothing
callFunction(&myFunc, "Hello world");
This as the additional vantage that avoid the conversion of the callable to a std::function
.
Anyway, I see two problems in your code:
1) if you receive the functional as a std::function
receiving a list ot arguments types (a variadic list in this case, but isn't important for this problem) as a list of argument of the same types, you have to be sure that the types in the two list match exactly.
This isn't your case because the function receive a std::string const &
and you pass as argument a the string literal "Hello world"
that is a char const [12]
that is a different type.
When the types are to be deduced, this cause a compilation error because the compiler can't choose between the two types.
You could solve receiving two list of types
template <typename ... Ts1, typename Ts2>
void callFunction (std::function<void(Ts1...)> const & function,
Ts2 && ... parameters)
{ function(std::forward<Ts2>(parameters)...); }
but now we have the second problem
2) You pass a pointer function (&myFunc
) where callFunction()
wait for a std::function
.
We have a chicken-egg problem because &myFunc
can be converted to a std::function
but isn't a std::function
.
So the compiler can't deduce the Ts...
list of types from &myFunc
because isn't a std::function
and can't convert &myFunc
to a std::function
because doesn't know the Ts...
type list.
I see that you have explicated the first type in the Ts...
list, but isn't enough because the Ts...
list is a variadic one so the compiler doesn't know that there is only a type in the Ts...
list.
A simple solution to this problem is pass the function as a simple deduced F
type.
Otherwise, if you have written callFunction()
with two templates types lists, you can pass a std::function
to the function
std::function<void(std::string const &)> f{&myFunc};
callFunction(f, "Hello world");
but I don't think is a satisfactory solution.
Upvotes: 2