[Voted into WP at March 2004 meeting.]
Proposed resolution (April 2003):
Replace in 6.2 [basic.def] paragraph 2
Replace in 9.2.3 [dcl.fct.spec] paragraphs 5 and 6 The virtual specifier shall only be used in declarations of
nonstatic class member functions that appear within a
member-specification of a class
The explicit specifier shall be used only in declarations of
constructors within a class
Replace in 9.2.4 [dcl.typedef] paragraph 4
Replace in _N4868_.9.8.2.3 [namespace.memdef] paragraph 3
Replace in 9.3.4.3 [dcl.ref] paragraph 4
Replace in 9.5.4 [dcl.init.ref] paragraph 3
Replace in 11.3 [class.name] paragraph 2
Replace in 11.4.9 [class.static] paragraph 4 Replace in 11.4.12 [class.nest] paragraph 1
Replace in 11.6 [class.local] paragraph 1
Replace in 11.7 [class.derived] paragraph 1
Replace in 11.7.2 [class.mi] paragraph 5
Replace in the example in 6.5.2 [class.member.lookup] paragraph 6
(the whole paragraph was turned into a note by the
resolution of core issue 39)
Replace in 11.7.4 [class.abstract] paragraph 2
Replace in the footnote at the end of 11.8.3 [class.access.base] paragraph 1
Replace in _N3225_.11.3 [class.access.dcl] paragraph 1
Replace in the example in 12.3 [over.over] paragraph 5
Replace in C.8.6 [diff.dcl] paragraph 1
Replace in C.8.7 [diff.class] paragraph 3
The resolution of core issue 45 (DR)
deletes 11.8.8 [class.access.nest] paragraph 2.
The following occurrences of "class declaration" are not changed:
A declaration is a definition unless it declares a function
without specifying the function's body
(9.6 [dcl.fct.def]), it contains the
extern specifier (9.2.2 [dcl.stc]) or
a linkage-specification
[Footnote: Appearing inside the braced-enclosed
declaration-seq in a linkage-specification does not
affect whether a declaration is a definition. --- end
footnote]
(9.12 [dcl.link]) and neither an
initializer nor a function-body, it declares a static
data member in a class
declaration
definition
(11.4.9 [class.static]), it is a class name
declaration (11.3 [class.name]), or it is
a typedef declaration
(9.2.4 [dcl.typedef]), a
using-declaration
(9.10 [namespace.udecl]), or a
using-directive
(9.9.4 [namespace.udir]).
declaration
definition; see
11.7.3 [class.virtual].declaration
definition; see
11.4.8.2 [class.conv.ctor].
A
typedef-name
that names a class is 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 definition
(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]), the program is ill-formed.
The name of the friend is not found by simple name lookup until a
matching declaration is provided in that namespace scope (either
before or after the class
declaration
definition granting friendship).
There shall be no references to references, no arrays of references,
and no pointers to references. The declaration of a reference shall
contain an initializer
(9.5.4 [dcl.init.ref]) except when
the declaration contains an explicit extern specifier
(9.2.2 [dcl.stc]), is a class member
(11.4 [class.mem]) declaration within a
class
declaration definition, or is the
declaration of a parameter or a return type
(9.3.4.6 [dcl.fct]); see
6.2 [basic.def].
The initializer can be omitted for a reference only in a parameter
declaration (9.3.4.6 [dcl.fct]), in the
declaration of a function return type, in the declaration of a class
member within its class
declaration definition
(11.4 [class.mem]), and where the
extern specifier is explicitly used.
A class
definition declaration introduces the
class name into the scope where it is defined
declared and hides any class, object, function, or other
declaration of that name in an enclosing scope
(6.4 [basic.scope]). If a class name
is declared in a scope where an object, function, or enumerator of the
same name is also declared, then when both declarations are in scope,
the class can be referred to only using an
elaborated-type-specifier
(6.5.6 [basic.lookup.elab]).
Static members obey the usual class member access rules (
11.8 [class.access]). When used
in the declaration of a class member, the static specifier
shall only be used in the member declarations that appear within the
member-specification of the class
declaration
definition.
A class can be
defined declared within another
class. A class defined declared within
another is called a nested class. The name of a nested class
is local to its enclosing class. The nested class is in the scope of
its enclosing class. Except by using explicit pointers, references,
and object names, declarations in a nested class can use only type
names, static members, and enumerators from the enclosing class.
A class can be
defined declared within a
function definition; such a class is called a local class. The
name of a local class is local to its enclosing scope. The local
class is in the scope of the enclosing scope, and has the same access
to names outside the function as does the enclosing function.
Declarations in a local class can use only type names, static
variables, extern variables and functions, and enumerators
from the enclosing scope.
... The class-name in a base-specifier shall not be an
incompletely defined class (Clause 11 [class]);
this class is called a
direct base class for the class being
declared defined. During the lookup for a
base class name, non-type names are ignored
(_N4868_.6.4.10 [basic.scope.hiding]).
If the name found is not a class-name, the program is ill-formed.
A class B is a base class of a class D if it is a
direct base class of D or a direct base class of one of
D 's base classes. A class is an indirect base class
of another if it is a base class but not a direct base class. A class
is said to be (directly or indirectly) derived from its (direct
or indirect) base classes. [Note: See
11.8 [class.access]
for the meaning of access-specifier.] Unless
redefined redeclared in the
derived class, members of a base class are also considered to be
members of the derived class. The base class members are said to be
inherited by the derived class. Inherited members can be
referred to in expressions in the same manner as other members of the
derived class, unless their names are hidden or ambiguous
(6.5.2 [class.member.lookup]).
[Note: the scope resolution operator ::
(_N4567_.5.1.1 [expr.prim.general])
can be used to refer to a direct or indirect base member explicitly.
This allows access to a name that has been redefined
redeclared in the derived class. A derived class can itself
serve as a base class subject to access control; see
11.8.3 [class.access.base].
A pointer to a derived class can be implicitly converted to a pointer
to an accessible unambiguous base class
(7.3.12 [conv.ptr]).
An lvalue of a derived class type can be bound to a reference to an
accessible unambiguous base class
(9.5.4 [dcl.init.ref]).]
For another example,
for an object c of class type C , a single subobject
of type V is shared by every base subobject of c
that
class V { /* ... */ };
class A : virtual public V { /* ... */ };
class B : virtual public V { /* ... */ };
class C : public A, public B { /* ... */ };
is declared to have has a
virtual base class of type V .
The names
defined declared in V and
the left hand instance of W are hidden by those in
B , but the names defined declared in
the right hand instance of W are not hidden at all.
... A virtual function is specified pure by using a
pure-specifier (11.4 [class.mem])
in the function declaration in the class
declaration
definition. ...
[Footnote: As specified previously in
11.8 [class.access], private members of
a base class remain inaccessible even to derived classes unless
friend declarations within the base class
declaration definition are used to grant access
explicitly.]
The access of a member of a base class can be changed in the derived
class by mentioning its qualified-id in the derived class
declaration definition. Such mention is
called an access declaration. ...
The initialization of pfe is ill-formed because no
f() with type int(...) has been
defined declared, and not because of any
ambiguity.
Rationale: Storage class specifiers don't have any meaning when
associated with a type. In C++, class members can be
defined declared with the static
storage class specifier. Allowing storage class specifiers on type
declarations could render the code confusing for users.
In C++, a typedef name may not be
Drafting notes:
redefined redeclared in a class
declaration definition after being used in the
declaration that definition
The ARM used the term "class declaration" to refer to what
would usually be termed the definition of the class. The standard
now often uses "class definition", but there are some surviving uses
of "class declaration" with the old meaning. They should be found
and changed.