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

前端 未结 2 798
野性不改
野性不改 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.

    0 讨论(0)
  • 2021-01-20 05:03

    From cppreference

    Usage:

    • In a template declaration, typename can be used as an alternative to class to declare type template parameters and template template parameters (since C++17).
    • Inside a declaration or a definition of a template, typename can be used to declare that a dependent name is a type.
    • Inside a requirements for type requirements (since C++20)

    So I would say that you have no guaranties that case 1 and case 2 will compile. As they do not fall into any of these three usage cases.

    And for case 3, let's see what cppreference has to say about that:

    The keyword typename may only be used in this way before qualified names (e.g. T::x), but the names need not be dependent.

    The keyword typename must only be used in template declarations and definitions and only in contexts in which dependent names can be used. This excludes explicit specialization declarations and explicit instantiation declarations.(until C++11)

    The keyword typename can be used even outside of templates. (since C++11)

    So as there is no template in your example, case 3 should be guarantied to work only since C++11

    And indeed a test program compiled OK with g++ -std=c++11 but issued this warning without -std=c++11

    warning: 'typename' occurs outside of a template [-Wc++11-extensions]

    0 讨论(0)
提交回复
热议问题