According to clang, gcc and vs2013, the function Outer::f
is not a friend of the class Outer::Inner
.
struct Outer {
void f() {}
class Inner {
friend void f();
static const int i = 0;
};
};
void f() { int i = Outer::Inner::i; }
From [namespace.memdef]/3 I would expect the function Outer::f
to be a friend of Outer::Inner
, instead of ::f
, because the friend declaration is not the first in its namespace containing the name f
.
[namespace,memdef]/3 (emphasis is mine):
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 template97 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). [ Note: The name of the friend will be visible in its namespace if a matching declaration is provided at namespace scope (either before or after the class definition granting friendship). — end note ] 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). If the name in a friend declaration is neither qualified nor a template-id and the declaration is a function or an elaborated-type-specifier, the lookup to determine whether the entity has been previously declared shall not consider any scopes outside the innermost enclosing namespace.
struct Outer
from lookup. – AnTIf the name in a friend declaration is neither qualified nor a template-id and the declaration is a function or an elaborated-type-specifier, the lookup to determine whether the entity has been previously declared shall not consider any scopes outside the innermost enclosing namespace.
, where the innermost enclosing namespace, in this case, is the global namespace. – Belloc[namespace.memdef]/3
byfriend void h(int);
declaration. It says thatA::h is a friend, ::h not considered
. The quoted passage explains why::h
is not considered: because::h
is declared in::
scope outside ofA
scope. In your examplestruct Outer
scope is not outside of::
scope. – AnTA
, while in the example above, the innermost namespace is the global namespace. As you said, theOuter
scope is not outside of the global scope. Therefore the lookup started in the friend declaration finds the nameOuter::f
which then should be the befriended function, and not::f
. – Belloc