On Mar 23, 2:50 pm, Victor Bazarov <v.Abaza...@comAcast.net> wrote:
John wrote:
Victor Bazarov wrote:
[...]
No, it wouldn't. First off, you can always test your code without
splitting it into headers and sources. Just put the contents of your
header in your source, verbatim:
namespace A {} // instead of explaining what blah.hpp does
class A::X;
namespace B
{
class Y
{
A::X* x;
};
}
Second, there are other compilers available for testing some concepts
which you are investigating. There is GCC (in MinGW form), there is
Comeau online.
Note that both G++ (4.1.0) and Sun CC (5.8) also accept this
code. (Unless I've misread, I don't think they should: ?3.4.4/3
seems pretty clear: "If the name is a qualified-id, the name is
looked up according its qualifications, as described in 3.4.3,
but ignoring any non-type names that have been declared. If this
name lookup finds a typedef-name, the elaborated-type-specifier
is ill-formed. If this name lookup does not find a previously
declared class-name or enum-name, the elaborated-type-specifier
is ill-formed." Especially the last sentence.
In this particular case, the declaration of 'A::X' still looks
'X' up in the namespace A (which it finds), and *fails* since
there is no 'X' in 'A'. The reason it tries to find 'X' is
because when it sees the name (once the token 'X' has been
read from the stream, just before processing the semicolon),
it doesn't know that you're *not* trying to *define* the
class, but merely to declare it (well, that's what you hope to
accomplish, isn't it?). So, it looks the name up, can't find
it, and ought to complain.
I'm not sure that's really clear. Basically, in an elaborated
type specifier (i.e. after the keyword class, struct, union or
enum), if the compiler doesn't find a simple identifier, the
elaborated type specifier is a declaration which introduces the
name; if the identifier is qualified, however, the rules are
different.
The rule is simple: declarations are declarations (whether you
prepend them with "forward" or "backward" or "sideways").
They *declare* a name (and that's why the name should appear
by itself in the declaration, naked, without qualifications).
And the declarations are only therefore valid at the exact
point where the name should originally be declared, so to
speak. IOW if you intend for 'X' to be declared in 'A',
declare it *there*.
Yes, but the whole point is that the elaborated type specifier
can be a declaration. Just not if the name is a qualified name.
Now, I don't know why VC++ compiles erroneous code. IME VC++
is too lax WRT to language rules about what is and what isn't
legal code (something about the level of the users of that
compiler, I am guessing, on average). Try disabling
extensions (/Za option, IIRC). Further inquiries about VC++
specifics should be made in the VC++ newsgroup
(microsoft.public.vc.langauge).
Given that g++ and Sun CC also compile it, it does seem
reasonable to ask why the restriction. Are there special cases
where allowing it would cause problems?
That's a good question; I don't know the answer, though. Let's hope
chimes in.