Overload resolution behaviour difference between GCC and clang (SFINAE)

人盡茶涼 提交于 2019-11-29 03:11:55

Both Clang and g++ are correct here.

Per Luc Danton's answer, a compiler is permitted to deduce T = int for the foo function template. Then, during the substitution of that value into the declaration of foo, the implicit instantiation of meta<int> is required, and it results in an error outside the immediate context of the substitution (so SFINAE does not apply). So Clang is correct to reject this code.

However, [temp.inst]p7 says:

If the overload resolution process can determine the correct function to call without instantiating a class template definition, it is unspecified whether that instantiation actually takes place.

Because the non-template foo is an exact match for the arguments in the call, a compiler could determine that a function template specialization will never be the best viable function, and so need not perform argument deduction and substitution. Therefore g++ is correct to not reject this code.

C++03 uses this wording as part of the specification for what is usually referred to as SFINAE (14.8.2 Template argument deduction [temp.deduct], paragraph 2):

[...] If a substitution in a template parameter or in the function type of the function template results in an invalid type, type deduction fails. [...]

By contrast, C++11 uses this wording (14.8.2 Template argument deduction [temp.deduct], paragraph 8):

If a substitution results in an invalid type or expression, type deduction fails. [...] Only invalid types and expressions in the immediate context of the function type and its template parameter types can result in a deduction failure. [...]

Emphasis is mine. As I understand it the wording was improved in C++11 to unambiguously outline what should result in SFINAE (so-called soft errors) and what shouldn't (hard errors). This 2008 paper is an example of the discussion that was going on at the time and led to the current rules.

With this in mind it may be the case that according to C++03 an implementation may be right to accept your code (and even perhaps it should). I suspect that a C++11 implementation should reject it however: the error (int::type) is in the context of meta<int>, not of foo<int>.

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