什么时候可以将"typename"与明确引用类型的标识符一起使用?
When can `typename` be used with identifiers that unambiguously refer to a type?
通常,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++语法允许引入模板类型参数,或在限定名称(即包含::
标记的内容)之前引入。
所以你的 #1 和 #2 格式不正确,因为MyClass
和T
是非限定名称,不包含任何::
。
在限定名称之前,typename
令牌为:
- 定义头部的基类名之前使用,也不允许与
class
、struct
或union
关键字组合使用;在这些上下文中,限定名始终被视为类型 - 否则需要,如果限定名称是相关名称并且是未知专业化的成员
- 否则是可选的,无论是否在模板声明中
C++17 [温度分辨率]/3,5,6:
当限定 id旨在引用不是当前实例化成员的类型并且其嵌套名称说明符引用依赖类型时,它应以关键字
typename
为前缀,形成类型名称说明符。在类或 decltype(子句 [class.derived])中用作名称的限定名称或详细类型说明符隐式假定为命名类型,而不使用
typename
关键字。在紧随其后的嵌套名称说明符中,隐式假定标识符或简单模板 ID用于命名类型,而不使用typename
关键字。[注意:这些构造的语法不允许使用typename
关键字。如果对于一组给定的模板参数,实例化了模板的专用化,该专用化引用表示类型或类模板的限定ID,并且限定id 引用未知专用化的成员,则限定 id应以
typename
为前缀,或者应在它隐式命名如上所述类型的上下文中使用。
因此,您的 #3 格式正确,即使名称不依赖于模板参数,甚至不在模板声明中。
注意 C++20 将添加更多上下文,其中即使使用依赖名称typename
也是可选的,因为可以从上下文中明确确定名称只能表示类型。
来自 cpp首选项
用法:
- 在模板声明中,typename 可以用作类的替代项来声明类型模板参数和模板模板参数(自 C++17 起)。
- 在模板的声明或定义中,typename 可用于声明依赖名称是类型。
- 内部对类型要求的要求(自 C++20 起)
所以我想说的是,你无法保证案例 1 和案例 2 会编译。因为它们不属于这三个用例中的任何一个。
对于案例 3,让我们看看 cppPreferred 对此有何看法:
关键字
typename
只能在限定名称(例如 T::x)之前以这种方式使用,但名称不必依赖。关键字 typename 只能在模板声明和定义中使用,并且只能在可以使用依赖名称的上下文中使用。这不包括显式专用化声明和显式实例化声明。(至C++11)
关键字类型名称甚至可以在模板之外使用。(自C++11起)
因此,由于您的示例中没有模板,因此应保证案例 3 仅在 C++11 之后才能正常工作
确实有一个使用 g++ -std=c++11编译正常的测试程序,但在没有-std=c++11的情况下发出此警告
警告:"类型名称"出现在模板外部 [-WC++11-扩展]
- 在C++中,是否可以基于给定的标识符创建基类的新实例,反之亦然
- #ifdef和未声明的标识符
- f2、f3、f4标识符未找到
- 设置 Visual Studio for MPI: 找不到标识符错误
- 未声明的标识符编译暗黑破坏神 2 程序"muleview"
- 在顶点着色器中使用 OpenGl 的未声明标识符,我在顶点着色器中绘制三角形时遇到问题
- Google protobuf 时间戳未声明标识符,在 Windows 上具有C++
- 如何让 GCC/Clang 在保留标识符上出错
- 错误 C2760:语法错误:映射迭代器上意外的标记"标识符",预期的";"
- 当简单捕获中的标识符显示为参数的声明符 ID 时,没有编译器诊断
- 使用说明符 extern 声明的C++中的标识符链接
- C++:枚举:错误:应使用标识符而不是"}"
- 为什么我们不能重复使用具有不同模板参数的别名模板标识符?
- Visual Studio C++ PlaySound 标识符未定义
- 为什么我们不编写可以处理C++标识符的汇编器和链接器?
- 使用未声明的标识符"sqrt"?
- 找不到标识符合并
- 在模板化函数中重新定义(忽略)的 SWIG 标识符
- 在 c++ 中找不到此函数的标识符
- 对类 (C++) 中的私有变量使用未声明的标识符