[Voted into WP at April 2003 meeting.]
Proposed resolution (October 2002): 6.5.6 [basic.lookup.elab] paragraphs 2 and 3:
This sentence is deleted twice:
Note that the above changes are included in
N1376 as part of the resolution of issue 245. _N4567_.5.1.1 [expr.prim.general] paragraph 7:
This is only a note, and it is at least incomplete (and quite possibly
inaccurate), despite (or because of) its complexity.
I propose to delete it.
9.2.4 [dcl.typedef] paragraph 4:
My first choice would have been to make this the primary statement about
the equivalence of typedef-name and class-name,
since the equivalence comes about as a result of a typedef declaration.
Unfortunately, references to class-name point to
11.3 [class.name], so it
would seem that the primary statement should be there instead.
To avoid the possiblity of conflicts in the future, I propose to make
this a note.
9.2.9.5 [dcl.type.elab] paragraph 2:
This is the only remaining (normative) statement that a
typedef-name can't be used in an
elaborated-type-specifier.
The reference to template type-parameter is deleted by the
resolution of issue 283.
9.3 [dcl.decl] grammar rule declarator-id:
When I looked carefully into the statement of the rule prohibiting a
typedef-name in a constructor declaration, it appeared to me
that this grammar rule (inadvertently?) allows something that's always
forbidden semantically.
11.3 [class.name] paragraph 5:
Unlike the prohibitions against appearing in an
elaborated-type-specifier or constructor or destructor
declarator, each of which was expressed more than once, the prohibition
against a typedef-name appearing in a class-head
was previously stated only in 9.2.4 [dcl.typedef].
It seems to me that that prohibition belongs here instead.
Also, it seems to me important to clarify that a typedef-name
that is a class-name is still a typedef-name.
Otherwise, the various prohibitions can be argued around easily, if
perversely ("But that
isn't a typedef-name, it's a class-name; it says
so right there in 11.3 [class.name].")
11.4.5 [class.ctor] paragraph 3:
The new nonterminal references are needed to really nail down what we're
talking about here.
Otherwise, I'm just eliminating redundancy.
(A typedef-name that doesn't name a class type is no more
valid here than one that does.)
11.4.7 [class.dtor] paragraph 1:
The same comments apply here as to 11.4.5 [class.ctor].
...
If this name lookup finds a typedef-name, the
elaborated-type-specifier is ill-formed.
...
...
[Note: a typedef-name that names a class is a
class-name (11.3 [class.name]).
Except as the identifier in the declarator for a constructor
or destructor definition outside of a class
member-specification (11.4.5 [class.ctor],
11.4.7 [class.dtor]), a typedef-name
that names a class may be used in a qualified-id to refer to
a constructor or destructor. ]
[Note:
A typedef-name that names a class type, or a cv-qualified
version thereof, is also a class-name
(11.3 [class.name]).
If a typedef-name is used
following the
class-key in an elaborated-type-specifier
(9.2.9.5 [dcl.type.elab]),
or in the class-head of a class declaration (Clause 11 [class]),
or is used as the identifier in the declarator for a
constructor or destructor declaration (11.4.5 [class.ctor],
11.4.7 [class.dtor]),
to identify the subject of an elaborated-type-specifier
(9.2.9.5 [dcl.type.elab]),
class declaration (Clause 11 [class]),
constructor declaration (11.4.5 [class.ctor]),
or destructor declaration (11.4.7 [class.dtor]),
the program is ill-formed.
]
[Example: ...
...
If the identifier resolves to a typedef-name
or a template type-parameter, the
elaborated-type-specifier is ill-formed.
[Note: ...
declarator-id:
A typedef-name (9.2.4 [dcl.typedef])
that names a class type or a
cv-qualified version thereof is
also a class-name, but shall not be used
in an elaborated-type-specifier; see also
9.2.4 [dcl.typedef].
as the identifier in a class-head.
A typedef-name that names a class is a
class-name (9.2.4 [dcl.typedef]); however, a A
typedef-name that names a class shall not be
used as the identifier
class-name in the declarator
declarator-id for a constructor declaration.
...
A typedef-name that names a class is a
class-name (7.1.3); however, a A
typedef-name that names a class shall not be
used as the identifier class-name
following the ~ in the declarator for a destructor
declaration.
Notes from 4/02 meeting: There is a problem in that class-or-namespace-name does not
include typedef names for cv-qualified class types. See
9.2.4 [dcl.typedef] paragraph 4: Argument and text removed from proposed resolution
(October 2002): 9.2.4 [dcl.typedef] paragraph 5:
Here's a good question: in this example, should X
be used as a name-for-linkage-purposes (FLP name)?
Because a type-qualifier is parsed as a
decl-specifier, it isn't possible to declare cv-qualified
and cv-unqualified typedefs for a type in a single declaration.
Also, of course, there's no way to declare a typedef for the
cv-unqualified version of a type for which only a cv-qualified version
has a name.
So, in the above example, if X isn't used as the FLP name,
then there can be no FLP name.
Also note that a FLP name usually represents a parameter type, where
top-level cv-qualifiers are usually irrelevant anyway.
Data points: for the above example, Microsoft uses X as the
FLP name; GNU and EDG do not.
My recommendation: for consistency with the direction we're going on
this issue, for simplicity of description (e.g., "the first
class-name declared by the declaration"), and for (very
slightly) increased utility, I think Microsoft has this right.
typedef class { } const X;
If the typedef declaration defines an unnamed class type (or
enum type), the first typedef-name declared by the
declaration to
be have that class type
(or enum type) or a cv-qualified version thereof
is used to denote the class type (or enum type) for linkage purposes
only (6.7 [basic.link]).
[Example: ...
Proposed resolution (10/01): In 6.5.5.2 [class.qual] paragraph 1 add the indicated text:
If the nested-name-specifier of a qualified-id nominates
a class, the
name specified after the nested-name-specifier is looked up in the
scope of the class (6.5.2 [class.member.lookup]), except for the cases
listed below. The name shall represent one or more members of that
class or of one of its base classes (11.7 [class.derived]).
If the class-or-namespace-name of the nested-name-specifier
names a cv-qualified class type, it nominates the underlying class
(the cv-qualifiers are ignored).
Can a typedef T to a cv-qualified class type be used
in a qualified name T::x ? Suggested answer: Yes. All the compilers I tried accept the test case.
struct A { static int i; };
typedef const A CA;
int main () {
CA::i = 0; // Okay?
}