Greg Herlihy wrote:
Quote:
Originally Posted by
>
Quote:
Originally Posted by
>Consider the following code fragment
>>
> namespace N {
> struct S {
> void foo();
> };
> }
>>
> using namespace N; // 1
>>
> class C {
> friend struct S; // 2
> C() {}
> };
>>
> void N::S::foo() {
> C c; // 3 Is C's constructor accessible here???
> }
>>
>According to what I can see in the standard, friend declaration at point
>2 is supposed to perform name lookup for unqualified name 'S' in order
>to determine whether this is the first declaration of 'S'. According to
>7.3.1.2/3, the lookup goes up to the innermost enclosing namespace scope
>(which happens to be the global scope in this case). According to
>3.4.1/2, name 'S' introduced by a using directive at point 1 is
>considered to be a member of global namespace for the purposes of
>unqualified name lookup. This makes me to conclude that the friend
>declaration at 2 is supposed to refer to 'N::S' instead of introducing a
>new [hidden] declaration of 'struct S' into the global namespace. I.e.
>the constructor of 'C' is supposed to be accessible at point 3.
>
A using directive like the one above ("using namespace N") does not
"introduce" any names into the declarative region in which the directive
appears.
Yes, it does "virtually" introduce the names into the region
("virtually" here means that the names are introduced for the purpose of
name lookup only). That is exactly what 3.4.1/2 says:
"For the purpose of of the unqualified name lookup rules described in
3.4.1, the declarations from the namespace nominated by the
'using-directive' are considered members of that enclosing namespace."
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Quote:
Originally Posted by
Instead, a using directive merely affects how names are looked up
within that declarative region.
Well, that is exactly _how_ in affects the lookup process. By
introducing the names into the region _as_ _members_ (for the purposes
of unqualified name lookup only).
Quote:
Originally Posted by
Since a friend declaration requires that the named friend (S in this case)
be a member of the enclosing declarative region (if the friend is to be
found there), a using directive is not enough in this case for the compiler
to find the intended friend class: N::S.
The standard does not agree with you on that. Once again, it literally
says that in the above example for the purposes of unqualified name
lookup name 'S' (standing for 'N::S') is considered a member of global
namespace.
Quote:
Originally Posted by
Since a using declaration does introduce a name into its enclosing region,
it is possible to fix this problem by using a using declaration instead of
using a using directive to bring the name S into the proper declarative
region. For example:
>
using N::S; // 1
>
class C
{
friend struct S; // 2
C() {}
};
This will cause at least Comeau Online to issue a different error - at
point 2 it will say that name 'S' has already been declared in this
scope. It is the same problem as in
namespace N { struct S {}; }
using N::S;
struct S {}; // ERROR: 'S' has already been declared
Apparently, in your modified example Comeau still refuses to link friend
declaration to 'N::S'. I might look into that separately later, but at
this time I'm primarily interested in the original version with using
directive.
--
Best regards,
Andrey Tarasevich