Reputation: 1985
Per [temp.deduct]/8:
[..]
Only invalid types and expressions in the immediate context of the function type, its template parameter types, and its explicit-specifier can result in a deduction failure.
[ Note: The substitution into types and expressions can result in effects such as the instantiation of class template specializations and/or function template specializations, the generation of implicitly-defined functions, etc. Such effects are not in the “immediate context” and can result in the program being ill-formed. — end note ]
What I understand from the bold part is,
If the substitution process has side effects (such as instantiation of a template, etc), invalid types/expressions can result in a hard error.
If the substitution process does not have side effects, invalid types/expressions can result in a deduction failure.
If I right about what I saying above, why this program results in substitution failure and not hard error:
template <class T> struct S { using type = T; };
template <class> void f(...); // "fallback".
template <class T> struct A {};
template <class T> typename S<T>::type::type f(int);
int main(void){
f<A<int>>(0); // calls fallback. Why?
}
The above call substitutes A<int>
with T
. So the function type will be S<int>::type (int)
. Now it has to instantiate the template S<int>
to check the existence of the member type
. And here is the point of my question: The substitution process has side effects that result in an invalid type because S<int>
specialization has no members called type
. So I am expecting that the program is ill-formed instead of calling f(...)
.
I deliberately do not mention anything about the "immediate contexts" because I do not completely understand what this context involves/means even though there's a specific question asked here about it, but neither answer there mentions what exactly this context means. So, if possible, any side note about it will be appreciated.
Upvotes: 0
Views: 114
Reputation: 1
So I am expecting that the program is ill-formed instead of calling f(...).
In the given example, both instantiations A<int>
and S<A<int>>
are well-formed by themselves. Now, even though the instantiation of A<int>
and S<A<int>>
is not in the immediate context of function template's substitution but S<A<int>>::type::type
is.
Thus, we get a deduction failure corresponding to the expression S<A<int>>::type::type
instead of getting a hard error corresponding to the instantiations A<int>
and S<A<int>>
.
If on the other hand, any of the instantiation were ill-formed then we would have gotten a hard error.
Upvotes: 1