When I try to compile this code
// void foobar(int);
template
struct Foo {
void bar(T t) { foobar(t); };
};
void foobar(int);
template clas
Phase two lookup only includes name lookup rules that can't be applied in phase one- ADL, for example. Two-phase lookup is exactly that- some names are looked up in phase one, and some are looked up in phase two. This particular kind of name is a phase one name, as the compiler is perfectly capable of looking for foobar
in the namespace(s) of the function during phase one.
Visual C++ does not implement two-phase name lookup.
tl;dr Foo<int>
doesn't invoke any ADL, but Foo<X>
would (where X
is a class type).
First of all, in this code foobar
is a dependent name because of (C++14/N3936) [temp.dep]/1
In an expression of the form:
postfix-expression ( expression-list opt )
where the postfix-expression is an unqualified-id, the unqualified-id denotes a dependent name if [...]
- any of the expressions in the expression-list is a type-dependent expression (14.6.2.2), or
and t
is a dependent name because it is part of a declaration T t
where T
is a template parameter and thus a dependent type.
Moving onto dependent name resolution, there is [temp.dep.res]/1
which introduces the fact that names can be both looked up in the definition context, and the instantiation context, and defines where the instantiation context is. I have omitted that for brevity, but in this example template class Foo<int>;
is the point of instantiation.
The next bit is [temp.dep.candidate]/1
:
For a function call where the postfix-expression is a dependent name, the candidate functions are found using the usual lookup rules (3.4.1, 3.4.2) except that:
- For the part of the lookup using unqualified name lookup (3.4.1), only function declarations from the template definition context are found.
- For the part of the lookup using associated namespaces (3.4.2), only function declarations found in either the template definition context or the template instantiation context are found.
Those last two parts are the "two phases" of two-phase lookup. (Note - this section changed in wording from C++11 to C++14, but the effect in the same).
In the first phase, 3.4.1, no names are found for foobar
.
So we move onto the second phase. The actual places that names are looked up as described in 3.4.2. The text is long but the here are two of the relevant rules:
If T is a fundamental type, its associated sets of namespaces and classes are both empty.
If T is a class type (including unions), its associated classes are: the class itself; the class of which it is a member, if any; and its direct and indirect base classes. Its associated namespaces are the innermost enclosing namespaces of its associated classes. [...]
So when you instantiate Foo<int>
, then the second phase of lookup does not introduce any additional namespaces to search.
However, if you change your example to have struct X {};
and then change int
to X
everywhere, then the code does compile. This is because of the latter bullet point: ADL for an argument of class type does search the enclosing namespace of that class (which is the global namespace now), however ADL for an argument of built-in type does not search the global namespace.
Looks correct to me. While overload resolution is done only in phase 2, in phase 1 you already have to know that foobar(t)
is a function call expression. If foobar
names a type, t
wouldn't even be a dependent name.