Topic: Is this a Bug in Comeau? (aka befriending classes in anonymous namespaces)
Author: johnchx2@yahoo.com (johnchx)
Date: Thu, 2 Oct 2003 22:14:43 +0000 (UTC) Raw View
fvali@kumc.edu ("Faisal Vali") wrote
> The following did not work either (trying to use Qualified Name lookup
> to prevent the auto-declaration 'feature' of friend declarations)
This seems to be a common confusion. There is no "auto-declaration
'feature'" and you can't disable it. A friend declaration *is* a
declaration, always and everywhere. Put another way, the name
declared as a friend is never "looked up," it is simply declared.
So the problem with this code ...
namespace { class M; }
class RD { friend class M; typedef int Q; };
namespace { class M { RD::Q i; }; }
is that the friend declaration introduces a new class named M, and
there's no way rewrite the friend declaration to explicitly refer to
<unnamed>::M because <unnamed> is...well...unnamed.
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html ]
Author: velco@fadata.bg (Momchil Velikov)
Date: Sat, 4 Oct 2003 09:05:45 +0000 (UTC) Raw View
johnchx2@yahoo.com (johnchx) wrote in message news:<4fb4137d.0310010935.542ed05a@posting.google.com>...
> fvali@kumc.edu ("Faisal Vali") wrote
>
> > The following did not work either (trying to use Qualified Name lookup
> > to prevent the auto-declaration 'feature' of friend declarations)
>
> This seems to be a common confusion. There is no "auto-declaration
> 'feature'" and you can't disable it. A friend declaration *is* a
> declaration, always and everywhere. Put another way, the name
> declared as a friend is never "looked up," it is simply declared.
>
> So the problem with this code ...
>
> namespace { class M; }
>
> class RD { friend class M; typedef int Q; };
>
> namespace { class M { RD::Q i; }; }
>
> is that the friend declaration introduces a new class named M, and
> there's no way rewrite the friend declaration to explicitly refer to
> <unnamed>::M because <unnamed> is...well...unnamed.
Doesn't make sense. A "friend" declaration is a friend declaration,
not class declaration. It does not introduce a new class, it refers
to a class specified by 1ISO/IEC 14882:1998(E) 11.4 "Friends"
"7 A name nominated by a friend declaration shall be accessible in
the scope of the class containing the friend declaration."
Thus in the above example "friend class M", refers to a class accessible at
namespace scope, and according to the definition of unnamed namespaces this
class is <unnamed>::M.
~velco
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html ]
Author: johnchx2@yahoo.com (johnchx)
Date: Sun, 5 Oct 2003 18:54:50 +0000 (UTC) Raw View
velco@fadata.bg (Momchil Velikov) wrote
> johnchx2@yahoo.com (johnchx) wrote
> > So the problem with this code ...
> >
> > namespace { class M; }
> >
> > class RD { friend class M; typedef int Q; };
> >
> > namespace { class M { RD::Q i; }; }
> >
> > is that the friend declaration introduces a new class named M, and
> > there's no way rewrite the friend declaration to explicitly refer to
> > <unnamed>::M because <unnamed> is...well...unnamed.
>
> Doesn't make sense. A "friend" declaration is a friend declaration,
> not class declaration. It does not introduce a new class, it refers
> to a class
Yep, that's the confusion I'm talking about. ;-)
The statement
friend class C;
does indeed declare a class. Let's see if we can prove that from the
standard.
According to the grammar, the statement above is indeed a declaration,
in particular a simple-declaration, composed of a decl-spec-seq
containing the the specifier "friend" and the
elaborated-type-specifier "class C". 7.1.5.3/2 tells us that the
identifier C is looked up and "If name lookup does not find a
declaration for the name, the elatorated-type-specifier is ill-formed
unless it is of the simple form class-key identifier [ which it is, in
our example ] in which case the identifier is declared as described in
3.3.1."
So it seems clear that a friend declaration *can* declare a previously
undeclared class. Whether it *does* depends on whether name lookup
finds an existing declaration for the identifier. Here things become
more murky.
7.3.1.2/3 says, in part:
When looking for a prior declaration of a class or a function
declared as a friend, scopes outside the innermost enclosing
namespace scope are not considered.
Let's apply this to the original example which started this
thread, but using a named namespace instead of the unnamed
namespace -- just to clarify what's going on a little.
7.3.1.1/1 tells us that "An unnamed-namespace-definition behaves
as if it were replaced by
namespace unique { /* empty body */ }
using namespace unique;
namepace unique { namespace-body } "
So we can re-write the original example thus:
namespace X {}
using namespace X;
namespace X { class M; }
class RD { friend class M; typedef int Q; };
namespace X { class M { RD::Q i; }; }
The big question is this: when the compiler looks up the idenfifier M
in the friend delcaration, will it find X::M?
If this were ordinary name lookup, there's no question -- the
using-directive guarantees that "the names appear as if they were
declared in the nearest enclosing namespace" (7.3.4/1), i.e. the
global namespace in this example.
However, the standard also makes it clear that this appearance is an
illusion: "A using-directive does not add any members to the
declarative region in which it appears." (ibid). In other words,
although name lookup might find the declaration of X::M, X::M has not
become a member of the global namespace.
So, what is supposed to happen? It's not entirely clear, and I can
see reasonable arguments on both sides. But since class X::M isn't
actually declared in the global namespace (only visible there as if it
were), I'm inclined to the view that X::M is not considered and that
the friend declaration declares a new class M in the global namespace.
Clarification in the standard is eagerly awaited. :-)
> specified by 1ISO/IEC 14882:1998(E) 11.4 "Friends"
>
> "7 A name nominated by a friend declaration shall be accessible in
> the scope of the class containing the friend declaration."
>
Accessibility is a different issue (and remember that access control
is applied only after names are resolved). This simply means that
class B cannot declare an inaccessible (e.g. private) member of class
A to be its friend (unless B is already a friend of A).
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html ]