Jens Maurer, Mark Hall, Ville Voutilainen
2010年11月12日
N3206=10-0196

N3206: Override control: Eliminating Attributes

The Core Working Group discussed the syntax for override control as related to FCD National Body comments US 44 and CA 3 on 2010年11月10日, 2010年11月11日, and 2010年11月12日. The author believes the consensus established at that time via a chain of straw polls was:

The wording below also address core issue 1065 "[[hiding]] with [[override]]".

Drafting notes: There is an ambiguity when parsing supposedly unnamed classes: "struct final { ... } * p" might define an unnamed final class, or it might define a class called "final". When resolving any ambiguity towards "identifier", unnamed classes can't ever be "final".

Add a new paragraph after 2.11 lex.name paragraph 1:

(追記) Some identifiers have a special meaning when appearing in a certain context (see table X).
Identifiers with special meaning
overridefinal
When referred to in the grammar, these identifiers are used explicitly rather than using the identifier grammar production. Any ambiguity whether a given identifier has a special meaning or not is resolved to interpret the token as a regular identifier. (追記ここまで)
Remove section 7.6.4 dcl.attr.final:
(削除) The attribute-token final specifies derivation semantics for a class and overriding semantics for a virtual function. It shall appear at most once in each attribute-list and no attribute-argument-clause shall be present. The attribute may be applied to class definitions and to virtual member functions being declared in a class definition. (削除ここまで)

(削除) If a class B is marked final and a class D is derived from B the program is ill formed. (削除ここまで)

(削除) If a virtual member function f in some class B is marked final and in a class D derived from B a function D::f overrides B::f, the program is ill-formed. (削除ここまで)

(削除) [ Example: ... ] (削除ここまで)

Remove in 7.6.5 dcl.attr.override:
(削除) The attribute-token override asserts that a virtual member function overrides a function in a base class. It shall appear at most once in each attribute-list and no attribute-argument-clause shall be present. The attribute may be applied to virtual member functions being declared in a class definition. (削除ここまで)

(削除) If a virtual member function f is marked override and does not override (10.3 class virtual) a member function of a base class the program is ill-formed. (削除ここまで)

(削除) The attribute-token hiding asserts that a class member name hides a name in a base class. It shall appear at most once in each attribute-list and no attribute-argument-clause shall be present. The attribute may be applied to class members being declared in a class definition. (削除ここまで)

(削除) If a class member is marked hiding and its name does not hide (3.3.10 basic.scope.hiding, 10.2 class.member.lookup) a class member name in a base class the program is ill-formed. (削除ここまで)

(削除) The attribute-token base_check specifies that overriding and hiding of base members is strictly checked within a class. It shall appear at most once in each attribute-list and no attribute-argument-clause shall be present. The attribute may be applied to a class definition. (削除ここまで)

(削除) In a class definition marked base_check, if a virtual member function that is neither implicitly-declared nor a destructor overrides (10.3 class.virtual) a member function of a base class and it is not marked override, the program is ill-formed. Similarly, in such a class definition, if a class member name other than that of an implicitly-declared special member function hides (3.3.10 basic.scope.hiding, 10.2 class.member.lookup) a class member name in a base class and it is not marked hiding, the program is ill-formed. [ Note: a using-declaration makes the potentially hidden name visible, avoiding the need for the hiding attribute. -- end note ] [ Example: ... ] (削除ここまで)

Change the grammar in 9 class and the following sentence:
class-head:
 (削除) class-key attribute-specifieropt identifieropt base-clauseopt
 class-key attribute-specifieropt nested-name-specifier identifier base-clauseopt
 class-key attribute-specifieropt nested-name-specifieropt simple-template-id base-clauseopt (削除ここまで)
 (追記) class-key attribute-specifieropt class-head-name class-virt-specifier-seqopt base-clauseopt
 class-key attribute-specifieropt base-clauseopt
class-head-name:
 nested-name-specifieropt class-name
class-virt-specifier-seq:
 class-virt-specifier
 class-virt-specifier-seq class-virt-specifier
class-virt-specifier: (追記ここまで)
 (追記) final
 explicit (追記ここまで)
... (追記) A class-virt-specifier-seq shall contain at most one of each class-virt-specifier. (追記ここまで) A class-specifier (削除) where the (削除ここまで) (追記) whose (追記ここまで) class-head omits (削除) the optional identifier (削除ここまで) (追記) the class-head-name (追記ここまで) defines an unnamed class. (追記) [ Note: An unnamed class thus can't be final or explicit. ] (追記ここまで)
Add a new paragraph after 9 class paragraph 2:
(追記) If a class is marked with the class-virt-specifier final and it appears as a base-type-specifier in a base-clause (10 class.derived), the program is ill-formed. (追記ここまで)
Change 9 class paragraph 10:
If a (削除) class-head (削除ここまで) (追記) class-head-name (追記ここまで) contains a nested-name-specifier, the class-specifier shall refer to a class that was previously declared directly in the class or namespace to which the nested-name-specifier refers, or in an element of the inline namespace set (7.3.1 namespace.def) of that namespace (i.e., not merely inherited or introduced by a using-declaration), and the class-specifier shall appear in a namespace enclosing the previous declaration. In such cases, the nested-name-specifier of the (削除) class-head (削除ここまで) (追記) class-head-name (追記ここまで) of the definition shall not begin with a decltype-specifier.
Change the grammar in 9.2 class.mem:
member-declarator:
 declarator (追記) virt-specifier-seqopt (追記ここまで) pure-specifieropt
 declarator (追記) virt-specifier-seqopt (追記ここまで) brace-or-equal-initializeropt
 identifieropt attribute-specifieropt (追記) virt-specifier-seqopt (追記ここまで) : constant-expression
(追記) virt-specifier-seq:
 virt-specifier
 virt-specifier-seq virt-specifier
virt-specifier: (追記ここまで)
 (追記) override
 final
 new (追記ここまで)
pure-specifier:
 = 0
Add two new paragraphs after 9.2 class.mem paragraph 8:
(追記) A virt-specifier-seq shall contain at most one of each virt-specifier. The virt-specifiers override and final shall only appear in the declaration of a virtual member function. (追記ここまで)

(追記) If a class member is marked new and its name does not hide (3.3.10 basic.scope.hiding, 10.2 class.member.lookup) a class member name in a base class the program is ill-formed. (追記ここまで)

Add a new paragraph after 10 class.derived paragraph 8:
(追記) In a class definition marked with the class-virt-specifier explicit, if a virtual member function that is neither implicitly-declared nor a destructor overrides (10.3 class.virtual) a member function of a base class and it is not marked with the virt-specifier override, the program is ill-formed. Similarly, in such a class definition, if a class member name other than that of an implicitly-declared special member function hides (3.3.10 basic.scope.hiding, 10.2 class.member.lookup) a class member name in a base class and it is not marked new, the program is ill-formed, unless the class member is a member function that overrides the corresponding member in the base class. [ Note: a using-declaration makes the potentially hidden name visible, avoiding the need for the new marker. -- end note ] [ Example: (追記ここまで)
(追記) 
class B {
 virtual void some_func();
 virtual void f(int);
 virtual void h(int);
 void j(int);
 void k();
 typedef B self;
};
class D explicit : public B {
 void sone_func() override; // error: misspelled name
 void f(int) override; // OK: f implicitly virtual, overrides B::f
 virtual void f(long) override; // error: non-matching argument type
 virtual void f(int) const override; // error: non-matching cv-qualification
 virtual int f(int) override; // error: non-matching return type
 virtual void g(long); // OK: new virtual function introduced
 void h(int); // error: h implicitly virtual, but overriding without marker
 virtual void h(double); // error: hides B::h without marker
 virtual void h(char *) new; // OK
 using B::j;
 int j(double); // OK: not hiding due to "using"
 void j(int); // OK, despite `obscuring' B::j(int)
 virtual int j(void) new; // error: not hiding due to "using"
 int k; // error: hides B::k without marker
 int m(int) new; // error: no hiding despite marker
 typedef D self; // error: hides B::self without marker
}; (追記ここまで)
(追記) -- end example ] (追記ここまで)
Add two new paragraphs after 10.3 class.virtual paragraph 3:
(追記) If a virtual function f in some class B is marked with the virt-specifier final and in a class D derived from B a function D::f overrides B::f, the program is ill-formed. [ Example: (追記ここまで)
(追記) struct B {
 virtual void f() const final;
};
struct D : B {
 void f() const; // error: D::f attempts to override final B::f
};
 (追記ここまで)
(追記) -- end example ] (追記ここまで)

(追記) If a virtual function is marked with the virt-specifier override and does not override a member function of a base class, the program is ill-formed. [ Example: (追記ここまで)

(追記) struct B {
 virtual void f(int);
};
struct D : B {
 void f(long) override; // error: wrong signature overriding B::f
 void f(int) override; // ok
};
 (追記ここまで)
(追記) -- end example ] (追記ここまで)

AltStyle によって変換されたページ (->オリジナル) /