Reputation: 1548
The following code produces a compile error (on a recent version of gcc at least):
namespace a {
class X { friend void ::foo(); };
}
The error is:
'void foo()' should have been declared inside '::'
If we remove ::
from the declaration, according to the standard, foo
will be introduced into the namespace a
(although it won't be visible). Predeclaring foo inside of a
is not required.
My question is, given the above, why is predeclaring within the global namespace a requirement? Why doesn't the name foo
become a member of the global namespace? I couldn't find any paragraph in the standard that would explicitly forbid that either, so I'm curious to know.
Upvotes: 2
Views: 123
Reputation: 44043
The paragraph you're looking for is [dcl.meaning] (8.3 (1) in C++11):
(...) A declarator-id shall not be qualified except for the definition of a member function or static data member outside of its class, the definition or explicit instantiation of a function or variable of a namespace outside of its namespace, or the definition of an explicit specialization outside of its namespace, or the declaration of a friend function that is a member of another class or namespace. When the declarator-id is qualified, the declaration shall refer to a previously declared member of the class or namespace to which the qualifier refers (or, in the case of a namespace, of an element of the inline namespace set of that namespace).
(emphasis mine) What this means is that you cannot write
namespace a { }
void a::foo() { }
unless a::foo
is already declared with an unqualified declarator inside the namespace. And since there is no exception for friends, you cannot do this for friends either.
A footnote in [namespace.memdef] (7.3.1.2 (3) in C++11) mentions this even more explicitly for the special case of friends:
(...) If a friend declaration in a non-local class first declares a class or function95 the friend class or function is a member of the innermost enclosing namespace. (...)
95) This implies that the name of the class or function is unqualified.
Upvotes: 2