[ACCEPTED]-Overload resolution behaviour difference between GCC and clang (SFINAE)-overload-resolution

Accepted answer
Score: 11

Both Clang and g++ are correct here.

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

However, [temp.inst]p7 says:

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

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

Score: 5

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

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

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

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

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

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

More Related questions