The problem is this:
proxy(foo, 5);
The compiler is trying to infer the type foo , but there are 2 overloads. Of course, it can output Args... from 5 , but the type foo is still not output, since the compiler does not know which overload to choose when performing type inference.
Note that the compiler must know the type F in the function signature, i.e. here, so SFINAE does its magic:
is_same< typename result_of<F(Args...)>::type, int >::value,
There is absolutely no way to correctly deduce type F from a proxy(foo, 5) call proxy(foo, 5) , so SFINAE cannot go into it. As a side note, note that C ++ cannot overload only based on the return type. Thus, you cannot differentiate two functions with the same name, based only on the inverse type. You will need to somehow force the parameter mapping, which is why SFINAE will issue overloads that are not related to the candidate.
Somehow connected: Canceling the return type of an autonomous function
And the corresponding quote from the standard, underline mine (thanks @TC for pointing):
14.8.2.1 Extracting template arguments from a function call [temp.deduct.call] / (6.2)
(6) When P is a function type, a pointer to a function type or a pointer to a member function type:
(6.1) If the argument is an overload set containing one or more function templates, this parameter is considered as an uninduced context.
(6.2) If the argument is an overload set (not containing template functions), an attempted trial argument attempts to use each of the members of the set. If the deduction succeeds only for one of the set overloads, this member is used as the argument value for the deduction. If the deduction succeeds for more than one member, the overload sets the parameter to be treated as an unreduced context .
source share