Consider the following code:
#include <stdio.h>
class A
{
public:
friend void foo(A a){ printf("3\n"); }
};
int main()
{
foo(A());
}
It works. But I thought that this code is invalid. It is because 3.4.1/3:
For purposes of determining (during parsing) whether an expression is a postfix-expression for a function call, the usual name lookup rules apply.
Usual name lookup rules could not find the friend function because name declared by friend is invisible in the global namespace in my case. Actually 3.3.1/4:
friend declarations (11.3) may introduce a (possibly not visible) name into an enclosing namespace
This implies that the programm is ill-formed. It is because that there is no name which found during the determining is the expression foo(A());
is a postfix-expression for a function call.
I'm confusing...
When parsing the following program
the output will be
42
because 3.4.1/3that means: to determine if
foo
is a postfix-expression (e.g. a cast) or a function call, the compiler will first use name lookup and search for it in the global namespace and/or enclosing scopes / base classes (or with fully qualified lookups if available).Now take this code:
The above will output
55
thanks to ADL: foo will be found by searching inside the scopes defined by its potential arguments, i.e. A.A friend declaration introduces a (possibly not visible) name as you posted (3.3.1/4)
that means the following code will not work
You might want to search for "friend name injection" and/or the Barton-Nackman trick. Short story: now ordinary lookups can't find friend declarations.
So the code you posted is well-formed because ADL allows it to run as I explained in the previous passages.