Consider the following:
namespace N {
struct A { };
struct B {
B() { }
B(A const&) { }
friend void f(B const& ) { }
};
}
int main() {
f(N::B{}); // ok
f(N::A{}); // error
}
In the first case, the case succeeds - we consider the associated namespaces of N::B
and find N::f(B const&)
. Great.
The second case fails. Why? According to [namespace.memdef]:
If a
friend
declaration in a non-local class first declares a class, function, class template or function template the friend is a member of the innermost enclosing namespace. [...] If a friend function or function template is called, its name may be found by the name lookup that considers functions from namespaces and classes associated with the types of the function arguments (3.4.2).
The associated namespace of N::A
is N
, of which f
is a member, so why is it not found by lookup?
argument-dependent lookup (ADL) These function names are looked up in the namespaces of their arguments in addition to the scopes and namespaces considered by the usual unqualified name lookup. Argument-dependent lookup makes it possible to use operators defined in a different namespace.
In the C++ programming language, argument-dependent lookup (ADL), or argument-dependent name lookup, applies to the lookup of an unqualified function name depending on the types of the arguments given to the function call.
A function call expression such as func(a,b,c) , in which the function is named without the :: scope operator, is called unqualified.
It's because f
is not declared in an associated class. B
is an associated class when the argument is of type B
, but not when the argument is of type A
.
I quote from [basic.lookup.argdep]/4, emphasis mine:
When considering an associated namespace, the lookup is the same as the lookup performed when the associated namespace is used as a qualifier (3.4.3.2) except that:
— Any using-directives in the associated namespace are ignored.
— Any namespace-scope friend functions or friend function templates declared in associated classes are visible within their respective namespaces even if they are not visible during an ordinary lookup (11.3).
— All names except those of (possibly overloaded) functions and function templates are ignored.
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