My code:
template <typename T>
void func(T v)
{
func2(v);
}
struct S {};
void func2(int) {}
void func2(S) {}
int main()
{
func(1); // error here
func(S{}); // OK
}
The error:
<source>: In instantiation of 'void func(T) [with T = int]':
<source>:14:9: required from here
14 | func(1); // error here
| ~~~~^~~
<source>:4:10: error: 'func2' was not declared in this scope, and no declarations were found by argument-dependent lookup at the point of instantiation [-fpermissive]
4 | func2(v);
| ~~~~~^~~
<source>:10:6: note: 'void func2(S)' declared here, later in the translation unit
10 | void func2(S) {}
|
Why does the lookup fail for func2
with built in types but not user-defiened?
Fundamental types are not considered for ADL. From cppreference
Otherwise, for every argument in a function call expression its type is examined to determine the associated set of namespaces and classes that it will add to the lookup.
- For arguments of fundamental type, the associated set of namespaces and classes is empty.
So func2(int);
has an empty set and thus the compiler error.
For the class case we have
For arguments of class type (including union), the set consists of:
a) The class itself.
b) If the class is complete, all of its direct and indirect base classes.
c) If the class is a member of another class, the class of which it is a member.
d) The innermost enclosing namespaces of the classes added to the set.
and it is item d that brings in void func2(S) {}
since it is in the same namespace as S
.