I was reading this blog post section, and I tried to play around with the snippet that was provided.
namespace N {
// 2
class A {
friend void f(A) {} // 1
};
}
If I understood correctly, the definition in // 1
will inject the name f
where // 2
is located.
However it will only be available via argument-dependent lookup. Fine.
There is a sentence in the post that caught my attention:
7.3.1.2/3 Namespace member definitions [namespace.memdef]p3
Every name first declared in a namespace is a member of that namespace. 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. The friend declaration does not by itself make the name visible to unqualified lookup (3.4.1) or qualified lookup (3.4.3).
Notice that nowhere is it stated that the name introduced by a friend-declaration must have any particular relation to name of the class it is declared and/or defined in, or any particular relation to the class at all (for that matter).
From this, I thought the following snippet would have been valid:
namespace N {
struct A {
};
struct B {
friend void f(A) {
}
};
int main() {
N::A a;
f(a);
}
But it's rejected by both GCC7 and Clang 4.
t.cpp:19:3: error: ‘f’ was not declared in this scope
The funny thing is that, when I try to call f
with a N::B
object, I get the following error:
t.cpp:12:6: error: could not convert ‘b’ from ‘N::B’ to ‘N::A’
So here's my question:
Shouldn't f(A)
be detected via ADL? Since both classes are in the namespace I don't see why this fails. I looked in the standard the section about friends, but failed to find a relevant section.
I wonder in which scope f(A)
was injected, since GCC is able to find it when I try to give the wrong argument type via calling f(B)
.
From
cppreference/cpp/language/friend
:From
cppreference/cpp/language/namespace
:This is consistent with your example -
f
takes anA
, which is not the same type as the enclosing class.If you change your example to...
...it will compile.
Related standard quote: