The wording in the standard regarding the handling of names declared in unqualified friend declarations is unclear and, in certain cases, clearly incorrect. At the Kona meeting (10/99) the core working group agreed that, despite assertions to the contrary, the mechanism used to match a friend function declaration with a possible prior declaration of the class or function is not the normal lookup mechanism. This paper explores the issues involved in this process and proposes changes to the standard to clarify the issue.
This paper makes some assertions about "the way things are". For example, the section below asserts that friend function declarations do not consider declarations from base classes. These assertions are based on both my understanding of how the language has worked over the years and are backed up by verification of the code using several different compilers (EDG, Sun 5.0, g++ 2.95.2, Microsoft 6.0 and Borland 5.4).
In researching this issue I've determined that
iis declared.
N::iis not found (otherwise this code would be invalid).
In the following example, the EDG compiler says that the reference to
A is ambiguous and that
OA refers to
M::OA
.
The other compilers treat the friend declarations as references to
the names made visible by the using-directives. I consider this to
be wrong, but it could be argued that this is the correct behavior for
N::A. It is clearly wrong for
O::OA though
because this is only visible if you look in scopes outside of the
innermost enclosing namespace (for name lookup purposes the members of
namespace
O are treated as members of the global namespace)..
This rule makes the following code ill-formed:
A parallel rule for unqualified names was not added because it was not thought that such a rule was needed under the belief that an unqualified declaration always declares the name in a specified scope. This is not clear in the standard though, so it must be clarified one way or the other.
If an unqualified name can make use of a using-directive, you can actually change which function is defined by adding a using-directive.
I believe this is very undesirable and is one of the reasons tht the rule in 8.3 was added.
Some may object to the proposed difference in handling of friend class declarations and other forms of elaborated type specifiers. But the two kinds of elaborated type specifiers are already handled differently.
A friend class declaration does not look beyond the innermost namespace scope when looking for a prior declaration while a non-friend elaborated type specifier considers all scopes. This indicates that a friend declaration is already more "declaration-like" while other forms of elaborated type specifiers are more "reference-like".