Cannot deduce template argument that is a function

大兔子大兔子 提交于 2019-12-04 05:34:07
vsoftco

The problem is this:

proxy(foo, 5);

The compiler tries to deduce the type of foo, but there are 2 overloads. Of course, it can deduce Args... from 5, but the type of foo 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:

is_same<
    typename result_of<F(Args...)>::type,
    int
>::value,

There is absolutely no way for it to correctly deduce the type of F from the proxy(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)

(6) When P is a function type, pointer to function type, or pointer to member function type:

  • (6.1) If the argument is an overload set containing one or more function templates, the parameter is treated as a non-deduced context.

  • (6.2) If the argument is an overload set (not containing function templates), trial argument deduction is attempted using each of the members of the set. If deduction succeeds for only one of the overload set members, that member is used as the argument value for the deduction. If deduction succeeds for more than one member of the overload set the parameter is treated as a non-deduced context.

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 dropping float foo(float) from the overload resolution set.

Say you renamed the function returning float to foof, then your example would compile. But if you tried calling proxy with foof as the function argument, the code would again fail to compile, this time because of the enable_if constraint.

To get your example to compile in its current state you must disambiguate which foo you are passing to proxy

proxy(static_cast<int(*)(int)>(foo), 5);
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!