The following program compiles (live demo), but I don't understand, why.
namespace N {
struct S {};
}
void Foo(N::S);
namespace Lib {
template <class T>
void Call() { Foo(T{}); }
void Foo();
}
int main()
{
Lib::Call<N::S>();
}
Shouldn't Lib::Foo
hide ::Foo
? Foo
in Call
is a dependent name, and evaluation of dependent names are supposed to be postponed until the instantiation of the template. How does name lookup work in this case?
In namespace Lib
Foo(N::S{})
can be called before the declaration of void Foo();
, but it cannot be called after the declaration, because Lib::Foo
hides ::Foo
. Lib::Call<N::S>();
is after the declaration, so when binding the name Foo
here, hiding should be in effect, shouldn't it?
All non-ADL lookup for a name used in a template is from the template definition, even though the results are not used until instantiation in cases where ADL might contribute declarations found from the instantiation context.
You can think of this in a “spatial” sense—the two parts of the dependent lookup happen from different places (limiting what they find) at the same time—or in a “temporal” sense—the non-dependent-ADL lookup happens while parsing the template, and the results are saved and later merged with the dependent ADL results during instantiation. The former is how the standard describes it (to avoid describing compilation as a time-dependent process), but the latter intuitively accounts for the treatment of dependent names for parsing purposes (and thus when typename
and template
are required).
The standard rules for this are scattered across several cases for different kinds of names ([temp.res]/1.3, [temp.nondep]/1, and [temp.dep.candidate]/1 in C++20).