Reputation: 25
I'd like to send the two overloaded fun()
s to one template that handles them plus their arguments. This is my attempt so far:
#include <vector>
#include <iostream>
using namespace std;
class Demo
{};
template<typename Function, typename... Args>
void call(Function func(Args...), Args &&...args)
{
func(forward<Args>(args)...); // execute function with args
}
void fun(int first, int second, int third)
{
cout << "fun with ints\n";
}
void fun(Demo &&dem1, Demo &&dem2) // adding overload causes the ambiguity
{
cout << "fun with Demos\n";
}
int main()
{
call(fun, 1, 2, 3);
call(fun, Demo{}, Demo{});
}
The compiler complains that it can't find a matching function for the calls in main():
main.cc: In function ‘int main()’:
main.cc:27:22: error: no matching function for call to ‘call(<unresolved overloaded function type>, int, int, int)’
27 | call(fun, 1, 2, 3);
| ^
main.cc:10:6: note: candidate: ‘template<class Function, class ... Args> void call(Function (*)(Args ...), Args&& ...)’
10 | void call(Function func(Args...), Args &&...args)
| ^~~~
main.cc:10:6: note: template argument deduction/substitution failed:
main.cc:27:22: note: couldn’t deduce template parameter ‘Function’
27 | call(fun, 1, 2, 3);
| ^
main.cc:29:29: error: no matching function for call to ‘call(<unresolved overloaded function type>, Demo, Demo)’
29 | call(fun, Demo{}, Demo{});
| ^
main.cc:10:6: note: candidate: ‘template<class Function, class ... Args> void call(Function (*)(Args ...), Args&& ...)’
10 | void call(Function func(Args...), Args &&...args)
| ^~~~
main.cc:10:6: note: template argument deduction/substitution failed:
main.cc:29:29: note: couldn’t deduce template parameter ‘Function’
29 | call(fun, Demo{}, Demo{});
|
Any ideas to find a solution to this puzzle would be highly appreciated! (the solution at C++ overloaded function as template argument did not solve my problem because I cannot change the way that call() is called in main() )
Upvotes: 1
Views: 644
Reputation: 12253
The reason for compilation error is that the compiler does not know which fun
overload you are actually going to use.
To resolve this error, you just need to cast your function parameter to the right overload like:
int main()
{
call( static_cast< void(*)(int, int, int) >( fun ), 1, 2, 3 );
call( static_cast< void(*)(Demo&&, Demo&&) >( fun ), Demo{}, Demo{} );
return 0;
}
FYI, what your call
function is trying to do is actually defined by the standard. It is std::invoke
function and it comes with C++17 standard.
Upvotes: 1