Why cannot F
be deduced for proxy()
?
It should be possible because I am restricting it - only for functions that return an int
.
#include <utility>
#include <iostream>
#include <type_traits>
using namespace std;
int foo(int bar) {
cout << "int" << endl;
return 2;
}
float foo(float bar) {
cout << "float" << endl;
return 1;
}
template <typename F, typename... Args>
typename enable_if<
is_same<
typename result_of<F(Args...)>::type,
int
>::value,
typename result_of<F(Args...)>::type
>::type
proxy(F func, Args&&... args) {
return func(forward<Args>(args)...);
}
int main() {
proxy(foo, 5);
}
Here is the error:
b.cpp:29:17: error: no matching function for call to 'proxy(<unresolved overloaded function type>, int)'
b.cpp:24:1: note: template argument deduction/substitution failed:
b.cpp:29:17: note: couldn't deduce template parameter 'F'
The problem is this:
The compiler tries to deduce the type of
foo
, but there are 2 overloads. Of course, it can deduceArgs...
from5
, but the type offoo
is still non-deducible, since the compiler doesn't know which overload to pick when doing the type deduction.Note that the compiler needs to know the type of
F
in the signature of the function, i.e. here, so SFINAE do its magic:There is absolutely no way for it to correctly deduce the type of
F
from theproxy(foo, 5)
call, so SFINAE cannot kick in. As a side note, remark that C++ cannot overload based on the return type only. So you won't be able to differentiate two functions with the same name based on the return type alone. You'll need somehow to force a parameter matching which will SFINAE out the non-candidate overloads.Somehow related: Deducing the return type of a standalone function
And a relevant quote from the standard, emphasize mine (thanks to @T.C. for pointing it out):
14.8.2.1 Deducing template arguments from a function call [temp.deduct.call]/(6.2)
In your example
foo
names a set of overloaded functions, and template argument deduction is unable to select one overload over another because they're both matches of equal rank.Your SFINAE constraint check doesn't kick in until after
F
has been deduced, so it's of no help in droppingfloat foo(float)
from the overload resolution set.Say you renamed the function returning
float
tofoof
, then your example would compile. But if you tried callingproxy
withfoof
as the function argument, the code would again fail to compile, this time because of theenable_if
constraint.To get your example to compile in its current state you must disambiguate which
foo
you are passing toproxy