In the following code
template <typename T>
void foo(T) {
bar(T{});
}
class Something {};
void bar(Something) {}
int main() {
foo(Something{});
}
(https://wandbox.org/permlink/l2hxdZofLjZUoH4q)
When we call foo()
with a Something
parameter, everything works as expected, the call dispatches to the bar(Something)
overload.
But when I change the argument to an integer and provide a bar(int)
overload, I get an error
template <typename T>
void foo(T) {
bar(T{});
}
void bar(int) {}
int main() {
foo(int{});
}
Error:
error: call to function 'bar' that is neither visible in the template definition nor found by argument-dependent lookup
(https://wandbox.org/permlink/GI6wGlJYxGO4svEI)
In the class case, I have not defined bar()
in a namespace along with the definition of Something
. Meaning that I am not getting ADL. Then why does the code work with class types?
Then why does the code work with class types?
According to §6.4.2/2.1:
The sets of namespaces and classes are determined in the following way:
- If T is a fundamental type, its associated sets of namespaces and classes are both empty.
So upon writing foo(int)
, the compiler will have an empty set of namespaces and classes to be considered. The call to bar
thus must fail, as it is not declared yet. If you declare foo(int)
on beforehand, your code will compile:
void bar(int);
template <typename T>
void foo(T) {
bar(T{});
}
void bar(int) {}
int main() {
foo(int{});
}
On the other hand, in the case of the foo(Something)
, the (global) namespace will be part of the lookup, so the compiler actively scans the namespace for a function named bar
that can be called with Something
instances.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With