When can `typename` be used with identifiers that unambiguously refer to a type?

前端 未结 2 936
野性不改
野性不改 2021-01-20 04:11

Normally, typename is used to disambiguate between cases where an identifier may refer to a type, or may refer to something else:

template

        
2条回答
  •  予麋鹿
    予麋鹿 (楼主)
    2021-01-20 04:55

    The keyword typename is only permitted by the C++ syntax to introduce a template type parameter, or before a qualified name, i.e. something containing the :: token.

    So your #1 and #2 are ill-formed because MyClass and T are unqualified names, not containing any ::.

    Before a qualified name, the typename token is:

    • not allowed by the grammar before a base class name in the head of a class definition, or in combination with the class, struct, or union keywords; a qualified name is always treated as a type in these contexts
    • otherwise required, if the qualified name is dependent and a member of an unknown specialization
    • otherwise optional, whether within a template declaration or not

    C++17 [temp.res]/3,5,6:

    When a qualified-id is intended to refer to a type that is not a member of the current instantiation and its nested-name-specifier refers to a dependent type, it shall be prefixed by the keyword typename, forming a typename-specifier. ...

    A qualified name used as the name in a class-or-decltype (Clause [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]

    If, for a given set of template arguments, a specialization of a template is instantiated that refers to a qualified-id that denotes a type or a class template, and the qualified-id refers to a member of an unknown specialization, the qualified-id shall either be prefixed by typename or shall be used in a context in which it implicitly names a type as described above.

    So your #3 is well-formed, even though the name does not depend on a template parameter and isn't even in a template declaration.

    Note C++20 will add many more contexts where typename is optional even with a dependent name, because it's possible to unambiguously determine from the contexts that the name can only mean a type.

提交回复
热议问题