Title
Missing template keyword in class-or-decltype
Status
c++17
Section
11.7 [class.derived]
Submitter
Richard Smith

Created on 2013-07-03.00:00:00 last changed 81 months ago

Messages

Date: 2022-02-18.07:47:23

Proposed resolution, March, 2017:

  1. Change Clause 11 [class] paragraph 3 as follows:

  2. If a class is marked with the class-virt-specifier final and it appears as a base-type-specifier class-or-decltype in a base-clause ( 11.7 [class.derived]), the program is ill-formed. Whenever a class-key is followed by a class-head-name...
  3. Change the grammar in 11.7 [class.derived] paragraph 1 as follows:

    • base-specifier:
        attribute-specifier-seqopt base-type-specifier class-or-decltype
        attribute-specifier-seqopt virtual access-specifieropt base-type-specifier class-or-decltype
        attribute-specifier-seqopt access-specifier virtualopt base-type-specifier class-or-decltype

      class-or-decltype:
        nested-name-specifieropt class-name
        nested-name-specifier template simple-template-id
        decltype-specifier

      base-type-specifier:
        class-or-decltype
  4. Change 11.7 [class.derived] paragraph 2 as followx:

  5. The type denoted by a base-type-specifier A class-or-decltype shall be denote a class type that is not an incompletely defined class (Clause 11 [class]); this. The class denoted by the class-or-decltype of a base-specifier is called a direct base class for the class being defined. During the lookup for a base class name...
  6. Change 13.3 [temp.names] paragraphs 4 and 5 as follows:

  7. When the name of a member template specialization appears after . or -> in a postfix-expression or after a nested-name-specifier in a qualified-id, and the object expression of the postfix-expression is type-dependent or the nested-name-specifier in the qualified-id refers to a dependent type, but the name is not a member of the current instantiation The keyword template is said to appear at the top level in a qualified-id if it appears outside of a template-argument-list or decltype-specifier. In a qualified-id of a declarator-id or in a qualified-id formed by a class-head-name ( Clause 11 [class]) or enum-head-name (9.7.1 [dcl.enum]), the keyword template shall not appear at the top level. In a qualified-id used as the name in a typename-specifier (13.8 [temp.res]), elaborated-type-specifier (9.2.9.5 [dcl.type.elab]), using-declaration (9.9 [namespace.udecl]), or class-or-decltype ( 11.7 [class.derived]), an optional keyword template appearing at the top level is ignored. In these contexts, a < token is always assumed to introduce a template-argument-list. In all other contexts, when naming a template specialization of a member of an unknown specialization (13.8.3.2 [temp.dep.type]), the member template name must shall be prefixed by the keyword template. Otherwise the name is assumed to name a non-template. [Example:...

    A name prefixed by the keyword template shall be a template-id or the name shall refer to a class template or an alias template. [Note: The keyword template may not be applied to non-template members of class templates. —end note]...

  8. Change 13.8 [temp.res] paragraph 5 as follows:

  9. A qualified name used as the name in a mem-initializer-id, a base-specifier, class-or-decltype ( 11.7 [class.derived]) or an elaborated-type-specifier is implicitly assumed to name a type, without the use of the typename keyword. In a nested-name-specifier that immediately contains a nested-name-specifier that depends on a template parameter, the identifier or simple-template-id is implicitly assumed to name a type, without the use of the typename keyword. [Note: The typename keyword is not permitted by the syntax of these constructs. —end note]
Date: 2014-11-24.00:00:00

Additional note, November, 2014:

Concerns have been expressed over the clarity and organization of the proposed resolution, so the issue has been moved back to "review" status to allow CWG to address these concerns.

Date: 2014-02-15.00:00:00

Proposed resolution (February, 2014) [SUPERSEDED]:

  1. Change Clause 11 [class] paragraph 3 as follows:

  2. If a class is marked with the class-virt-specifier final and it appears as a base-type-specifier class-or-decltype in a base-clause (11.7 [class.derived]), the program is ill-formed. Whenever a class-key is followed...
  3. Change the grammar in 11.7 [class.derived] paragraph 1 as follows:

    • base-specifier:
        attribute-specifier-seqopt base-type-specifier class-or-decltype
        attribute-specifier-seqopt virtual access-specifieropt base-type-specifier class-or-decltype
        attribute-specifier-seqopt access-specifier virtualopt base-type-specifier class-or-decltype
      class-or-decltype:
        nested-name-specifieropt class-name
        nested-name-specifier template simple-template-id
        decltype-specifier
      base-type-specifier:
        class-or-decltype
      access-specifier:
        ...
  4. Delete paragraph 4 and change paragraph 5 of 13.3 [temp.names] as follows, splitting paragraph 5 into two paragraphs and moving the example from paragraph 4 into paragraph 5:

  5. When the name of a member template specialization appears after . or -> in a postfix-expression or after a nested-name-specifier in a qualified-id, and the object expression of the postfix-expression is type-dependent or the nested-name-specifier in the qualified-id refers to a dependent type, but the name is not a member of the current instantiation (13.8.3.2 [temp.dep.type]), the member template name must be prefixed by the keyword template. Otherwise the name is assumed to name a non-template. [Example: ... —end example]

    A name prefixed by the keyword template shall be a template-id or the name shall refer to a class template or alias template. [Note: The keyword template may not be applied to non-template members of class templates. —end note] The nested-name-specifier (_N4567_.5.1.1 [expr.prim.general]) of

    • a class-head-name (Clause 11 [class]) or enum-head (9.7.1 [dcl.enum]) (if any) or

    • a qualified-id in a declarator-id (9.3 [dcl.decl]),

    or a nested-name-specifier directly contained in such a nested-name-specifier (recursively), shall not be of the form

      nested-name-specifier template simple-template-id ::

    [Note: That is, a simple-template-id shall not be prefixed by the keyword template in these cases. —end note]

    The keyword template is optional in a typename-specifier (13.8 [temp.res]), elaborated-type-specifier (9.2.9.5 [dcl.type.elab]), using-declaration (9.9 [namespace.udecl]), or class-or-decltype (11.7 [class.derived]), and in recursively directly-contained nested-name-specifiers thereof. In these contexts, a < token is always assumed to introduce a template-argument-list. [Note: Thus, if the preceding name is not a template-name, the program is ill-formed. —end note] In other contexts, when the name of a member template specialization appears after a nested-name-specifier that denotes a dependent type, but the name is not a member of the current instantiation, the member template name shall be prefixed by the keyword template. Similarly, when the name of a member template specialization appears after . or -> in a postfix-expression (7.6.1 [expr.post]) and the object expression of the postfix-expression is type-dependent, but the name is not a member of the current instantiation (13.8.3.2 [temp.dep.type]), the member template name shall be prefixed by the keyword template. Otherwise, the name is assumed to name a non-template. [Example:

        <From original paragraph 4>
    

    end example] [Note: As is the case with the typename prefix...

This resolution also resolves issues 314, 343, 1794, and 1812.

Date: 2014-01-15.00:00:00

Additional note (January, 2014):

This is effectively issues 314 and 343.

See also issue 1812.

Date: 2017-02-15.00:00:00

[Adopted at the February/March, 2017 meeting.]

A class-or-decltype is used as a base-specifier and as a mem-initializer-id that names a base class. It is specified in 11.7 [class.derived] paragraph 1 as:

    class-or-decltype:
      nested-name-specifieropt class-name
      decltype-specifier

Consequently, a declaration like

  template<typename T> struct D : T::template B<int>::template C<int> {};

is ill-formed, although most implementations accept it; some actually require the use of the template keyword, although the relevant wording in 13.3 [temp.names] paragraph 4 only requires it in a qualified-id, not in a class-or-decltype. It would probably be good to add a production like

      nested-name-specifier template simple-template-id

to the definition of class-or-decltype and explicitly mention those contexts in 13.3 [temp.names] as not requiring use of the template keyword.

History
Date User Action Args
2018-02-27 00:00:00adminsetmessages: + msg6165
2018-02-27 00:00:00adminsetstatus: drafting -> c++17
2015-11-10 00:00:00adminsetstatus: review -> drafting
2014-11-24 00:00:00adminsetmessages: + msg5174
2014-11-24 00:00:00adminsetstatus: ready -> review
2014-03-03 00:00:00adminsetmessages: + msg4836
2014-03-03 00:00:00adminsetstatus: drafting -> ready
2014-01-20 00:00:00adminsetmessages: + msg4745
2013-10-14 00:00:00adminsetstatus: open -> drafting
2013-07-03 00:00:00admincreate