Reputation: 33
template <class T>
void foo(T t) {
t.moo();
}
template <class T>
void f(T t) {
foo(t);
}
struct C {
};
void foo(C) {}
void foo(int) {}
int main() {
C c;
f(c);
return 0;
}
Code above compiles without errors. If line "C c;" is replaced with "int c;", compiler will generate error "no function 'moo' for type 'int'" or something like that (MSVC will compile, but that's another story). If we replace int overload for template specialization, everything will work again. If function "void foo(int)" is moved above template code, that will do, too. What's going on?
Upvotes: 2
Views: 90
Reputation: 171177
What's going on?
Argument-dependent lookup (ADL). When calling a function through an unqualified name with at least one argument of class type, ADL is performed in addition to normal name lookup for the function name. ADL finds functions names within namespaces associated with the class (basically the namespace in which the class is defined).
The important property is that for function templates, unqualified name lookup only considers names visible at the template's definition, but ADL also considers names visible at the template's instantiation. Since the non-template overloads are declared after the templates, they cannot be found by ordinary unqualified name lookup. However, foo(C)
can be (and is) found by ADL, because C
is a class type. int
is not, so ADL is not performed and foo(int)
is not found.
Upvotes: 3