Reputation: 6566
Consider this piece of code.
Try to guess the output of the program before reading further:
#include <iostream>
using namespace std;
template <typename T>
void adl(T) {
cout << "T";
}
struct S {
};
template <typename T>
void call_adl(T t) {
adl(S());
adl(t);
}
void adl(S) {
cout << "S";
}
int main() {
call_adl(S());
}
Are you done? OK.
So the output of this program is TS
, which looks counterintuitive (at least for me).
Why is the call adl(S())
inside call_adl
using the template overload instead of the one that takes S?
Upvotes: 1
Views: 40
Reputation: 173044
The behaviors of name lookup are different for dependent name and non-dependent name in templates.
For a non-dependent name used in a template definition, unqualified name lookup takes place when the template definition is examined. The binding to the declarations made at that point is not affected by declarations visible at the point of instantiation. For a dependent name used in a template definition, the lookup is postponed until the template arguments are known, at which time ADL examines function declarations
with external linkage (until C++11)
that are visible from the template definition context as well as in the template instantiation context, while non-ADL lookup only examines function declarationswith external linkage (until C++11)
that are visible from the template definition context (in other words, adding a new function declaration after template definition does not make it visible except via ADL).
That means for adl(S());
, adl(S)
declared after call_adl
is not visible, then the templated adl(T)
is selected. For adl(t);
, t
is a dependent name (depending on the template parameter T
), the lookup is postponed and adl(S)
is found by ADL and it wins against adl(T)
in overload resolution.
Upvotes: 2