Why doesn't the restriction apply to qualified names and template-ids?
Qualified names and template-ids cannot introduce new members into the enclosing namespace, this is what the note in [namespace.memdef]p3 tries to say:
[ Note: The other forms of friend
declarations cannot declare a new
member of the innermost enclosing namespace and thus follow the usual
lookup rules. — end note ]
Therefore, no such restriction is necessary for qualified names and template-ids.
Note that template-ids lack the declaration of the template-parameters, and qualified-ids could introduce names into distant, unrelated namespaces.
Why is there a restriction at all?
This part of the answer is still incomplete, but represents the current state of "research". Feel free to contribute.
The restriction has (probably?) been introduced due to N0783 - Namespace Issues and Proposed Resolutions which "attempts to clarify a number of namespace issues that are currently either undefined or incompletely specified".
This paper from 1995 contains two enlightening discussions of issues related to declarations of entities introduced via friend-declarations. Bear in mind that the name lookup rules back then were different:
- Argument-dependent lookup had not yet been introduced(*)
- Names introduced via friend-declarations are not found via pure unqualified lookup (no ADL) according to current rules, see [namespace.memdef]p3 and CWG 1477. The examples from N0878 suggest that those names could be found via pure unqualified lookup at that time.
(*) The best I could find was N0878 from March 1996, which says "A change was recently made to the working paper to add the “Koenig lookup rule”"
First, the example from N0783 for functions:
void f(char);
namespace A {
class B {
friend void f(char); // ::f(char) is a friend
friend void f(int); // A::f(int) is a friend
void bf();
};
void B::bf()
{
f(1); // calls A::f(int);
f('x'); // also calls A::f(int) because ::f is hidden
}
}
The second friend declaration must introduce a new function. N0783 tries to specify in which scope this declaration is introduced. It suggests
All friend declarations for a given name must declare entities in one
particular scope.
as a general rule, to avoid the surprises of situations such as the above.
So the question is, which scope do they declare entities in? There are
two possibilities, either
- When looking for a previous declaration of the function, look until the nearest enclosing namespace is reached, or
- When looking for a previous declaration, look in all enclosing scopes for the name of the function that was declared. If a previous
use of the name is found, the declaration is injected into that scope.
If no previous use of the name is found the friend is injected into
the nearest enclosing namespace scope.
Rule #2 would mean that the presence of any function called f
in an
enclosing scope, whether or not the types match, would be enough to
cause a friend declaration to inject into that scope.
I believe that rule #2 is clearly unacceptable. A friend declaration
in a namespace would be affected by any global declaration of that
name. Consider what this would mean for operator functions! The
presence of any operator+
function in the global scope would force
all friend operator+
operators to appear in the global scope too!
The presence of a template in the global scope would have the same
effect.
For class types:
namespace N {
class A { void f(); };
}
using namespace N;
namespace M {
class B {
friend class A; // Without this rule
// makes N::A a friend
B();
};
class A { void f(); };
}
void N::A::f() { M::B b; } // A friend under current rules
void M::A::f() { M::B b; } // A friend under proposed rules
Both examples are not as interesting under the current rules because names introduced via friend declarations are only found via ADL. It is possible this restriction is a historical artefact. More "research" is required to follow the development of this restriction after the introduction of ADL.