Reputation: 1971
In the current draft of the C++ standard (march 2019) [class.friend] p.6 states (emphasis mine):
A function can be defined in a friend declaration of a class if and only if the class is a non-local class ([class.local]), the function name is unqualified, and the function has namespace scope. [...]
What does "the function has namespace scope" mean?
The only situation that I could come up with in which the function does not have namespace scope is the following:
struct A
{
static void f();
struct B
{
friend void f() {};
};
};
However both clang and gcc do not associate the friend definition inside B
to the static method inside A
, but to a function that belongs to the global namespace.
Are there other situations I am missing?
Upvotes: 6
Views: 556
Reputation: 72431
Looking for the relevant rule that says a friend
definition of an unqualified function name is always a namespace member, I found that's not quite the case. [namespace.memdef]/3:
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 the name in afriend
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.
The requirement in question applies only to function definitions, and rules out a local befriending class or a qualified friend name. But that leaves the possibility of a template-id as the function name.
So the wording seems to make a difference in this code:
struct A {
template <typename T>
static void f();
template <typename T>
struct B {
friend void f<T>() {}
};
};
Here the name in the friend declaration is a template-id, so the rule about skipping non-namespace scopes does not apply, and f
really names the function template A::f
. So [class.friend]/6 says this is ill-formed, though if the friend
declaration were not a definition, it would be well-formed.
Upvotes: 0
Reputation: 1571
I think that you have actually answered your own question, but without realizing it.
"The function has namespace scope" means that it is part of a namespace, not part of a class or struct. So the function A::B::f() doesn't exist. And it doesn't refer to A::f() either. Instead, the function you have defined as the friend is actually the function ::f(), since that is the namespace that it resides in (the global namespace).
I suspect (but have not tried), that if you wrap all of this in a namespace, then the f() you are defining would be a part of that namespace. So, for example,
namespace ns {
struct A
{
static void f();
struct B
{
friend void f() {};
};
};
}
would define the friend function as the function ns::f().
Upvotes: 3