Background: ADL (Argument Dependent Lookup), also known as Koenig lookup, was introduced in C++ to support operator overloading (especially operator<< and operator>> for user-defined types). The goal is to correctly find functions when mixing namespaces and user-defined types.
Problem: The standard function lookup mechanism may "overlook" a function if it is declared in a different namespace than the point of the call. ADL resolves this issue: the compiler considers the namespace of the function argument types to resolve names. This same mechanism can sometimes lead to unexpected overload choices or ambiguities.
Solution: When a function is called whose arguments are objects from user-defined namespaces, the compiler searches for suitable overloaded functions not only in the current scope but also in all namespaces associated with the types of the arguments.
Example code:
namespace lib { struct Widget {}; void do_something(const Widget&) { std::cout << "Widget" << std::endl; } } using lib::Widget; void call(const Widget& w) { do_something(w); // do_something is found via ADL }
Key features:
If a function with the same name is declared in two namespaces and an object of the second one is passed, which one will be called?
The function from the argument namespace, if it matches the arguments, will be chosen due to ADL:
namespace A { struct S {}; void f(const S&) { std::cout << "A!"; } } namespace B { struct S {}; void f(const S&) { std::cout << "B!"; } } A::S a; B::S b; f(a); // calls A::f via ADL f(b); // calls B::f via ADL
Does ADL work with template functions?
Yes, if a template function is defined in a namespace that matches the argument type, ADL will find it when called with that type.
Will ADL work for function pointers?
No, ADL does not apply when obtaining a function pointer (e.g., when taking its address). Only during the direct function call.
The project linked several external libraries, where each namespace had its own print(). The main code used print() with objects of different classes. Due to ADL, the compiler started to "pick" a function from the wrong namespace.
Pros:
Cons:
Using qualified call (specifying the namespace explicitly):
lib::do_something(w); // Explicitly!
Pros:
Cons: