mada
mada

Reputation: 1985

Why this example results in "substitution failure" not "hard error"

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,

  1. If the substitution process has side effects (such as instantiation of a template, etc), invalid types/expressions can result in a hard error.

  2. 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

Answers (1)

user12002570
user12002570

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

Related Questions