通常,typename
用于消除标识符可能引用类型或可能引用其他内容的情况之间的歧义:
template<class T>
void foo(typename T::type value) {
// ...
}
当标识符已经是类型时,什么时候可以使用typename
?
1.如果已经有这个名字的类可以使用吗?
class MyClass{};
void foo(typename MyClass value) {}
2.它可以与声明为类型的模板参数一起使用吗?
template<class T>
void foo(typename T value) {}
3.它可以与明确类型的内部类一起使用吗?
class A {
public:
class B {};
};
// Compiles; no typename necessary
void foo(A::B value) {}
// This compiles too on gcc and msvc
void bar(typename A::B value) {}
编译器解释
案例 1:MSVC 认为这可以; gcc 和 clang 抛出错误
情况 2:MSVC 认为这可以; gcc 和 clang 抛出错误
情况 3: A::B
是明确的类型,但 gcc 和 clang 现在允许使用 typename
。
最佳答案
关键字typename
只被C++ 允许syntax介绍一个template type parameter , 或 before a qualified name ,即包含 ::
标记的内容。
所以你的 #1 和 #2 格式错误,因为 MyClass
和 T
是不合格的名称,不包含任何 ::
。
在限定名称之前,typename
标记是:
- a base class name 之前的语法不允许在类定义的头部,或 in combination with the
class
,struct
, orunion
keywords ;在这些上下文中,限定名称始终被视为一种类型 - 否则需要,如果限定名称是dependent and a member of an unknown specialization
- 否则可选,无论是否在模板声明中
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 thetypename
keyword. [Note: Thetypename
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.
所以你的 #3 是格式正确的,即使名称不依赖于模板参数,甚至不在模板声明中也是如此。
注意 C++20 将添加 many more contexts其中 typename
是可选的,即使是从属名称也是如此,因为可以从上下文中明确地确定该名称只能表示一种类型。
关于c++ - `typename` 何时可以与明确引用类型的标识符一起使用?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55777503/