Is this program ill-formed despite SFINAE?

2019-02-27 03:09发布

问题:

template <typename T> void f() {
    return 0;  // returning value from function returning `void`
}

int main()
{
    // Not instantiating or calling any f<T>()
}

In comments to this answer, David asserts that a function template that contains a semantic error and is not instantiated causes a program to be ill-formed:

Whether the template is used or not does not matter, the program is ill-formed even with no instantiation but the compiler is not required to diagnose it.

Conversely, I am quite sure that SFINAE, as well as preventing type deduction and therefore instantiation of the function template per [C++11: 14.8.2/8], allows the program to remain well-formed. however I cannot find any text in this standard paragraph that explicitly says so.

Who is correct?


Wikipedia, which I shall not consider authoritative for this question, says about a slightly different case:

[..] SFINAE was introduced to avoid creating ill-formed programs when unrelated template declarations were visible [..]

(emphasis mine)

回答1:

The program is ill-formed as per 14.6/8:

If no valid specialization can be generated for a template definition, and that template is not instantiated, the template definition is ill-formed, no diagnostic required.

That is whether you instantiate the template or not, the template definition is ill-formed as there is no possible instantiation that will succeed.

Note that this is completely unrelated to SFINAE: Substitution Failure is not an Error is part of the substitution process, and never takes into account the contents of the template.



回答2:

Reading more closely, that standard passage says:

If a substitution results in an invalid type or expression, type deduction fails. An invalid type or expression is one that would be ill-formed if written using the substituted arguments. [..]

return 0 is not an expression, so SFINAE does not apply.

The passage goes on:

Only invalid types and expressions in the immediate context of the function type and its template parameter types can result in a deduction failure.

return 0 has nothing to do with the function type or its template parameter types, so SFINAE still does not apply.