GCC和class关键字
gcc and class keyword
我知道typename
和class
关键字在模板参数中是可互换的,但我认为只有typename
是允许嵌套类规范的。
有一次我不小心写错了"class
"而不是"typename
"的嵌套类。我发现gcc也接受class
,所以你可以这样写:
class std::vector<T>::iterator it;
instead of
typename std::vector<T>::iterator it;
这是一个gcc错误还是标准真的允许这种语法?
更新:代码示例:
template <typename T>
void test()
{
class std::vector<T>::iterator it;
}
class a::b
是一个详细的类型说明符。详细类型说明符的名称查找忽略非类型名称。因此,如果您正在解析模板,可以假设两件事:
- 当我们对
b
进行实例化和名称查找时,名称查找要么给我们一个类型,要么出错(找不到任何名称)。
class a::b
不需要typename
(无论如何,你不能把它放在一个详细的类型说明符的任何地方)。c++ 03不允许这样做,因此GCC似乎将c++ 0x规则作为扩展来实现。那不是特别糟糕。每一个真正的编译器都实现了一些规则,这些规则在它们的c++ 03版本中很容易实现,即使在形式上它们需要拒绝它。但是,class a::b
必须查找类名。如果它只是一个类型定义,那么查找详细的类型说明符是无效的。
请注意,class a::b
是在查找中忽略非类型名称的唯一方法(除了像具有类似特殊规则的限定名中的::
之前的晦涩情况)。例如
template<typename T>
struct A { typename T::type t; }
struct B { class type { }; int type; };
// invalid, even though GCC accepts that incorrectly
A<B> a;
如果您编译到c++ 0x,并且使用class T::type t;
,那么代码将有效,因为class T::type
忽略数据成员,但会找到嵌套类。
ISO 14886:2003中的第14.6节("名称解析")似乎是如何工作的定义。第三段说:
一个限定id引用一个类型,并且嵌套名称说明符依赖于模板参数(14.6.2)的限定id应该用关键字
typename
作为前缀,以表明限定id表示一个类型,形成详细类型说明符(7.1.5.3)。
没有提到class
关键字。
使用Comeau Online (Comeau C/c++ 4.3.10.1 (Oct 6 2008 11:28:09))无法编译,因此两个编译器中至少有一个存在错误。
error: typedef "iterator" may not be used in an elaborated
type specifier
class std::vector<T>::iterator it;
标准似乎肯定应该使用typename。从14.6/2:
在模板声明或定义中使用且依赖于模板形参的名称被假定为不命名类型,除非适用的名称查找找到类型名称或该名称由关键字typename限定。
Ideone在依赖名称不能解析为类时显示了一个很好的错误消息。所以你的例子只工作,因为iterator
确实是一个class
。:)
编辑:即使依赖项确实是一个类,MSVC也无法编译,
错误C2242: typedef名称不能跟随类/结构/联合
编辑2 :这似乎是一个MSVC错误,因为如果依赖的名称是一个类,g++和Comeau在线编译就可以了。
我还是不明白发生了什么。如果放代码没有问题,我就会加注释。
template <typename Foo>
void f()
{
class Foo::bb x;
}
struct X {
typedef int bb;
};
int main()
{
f<X>();
return 0;
}
不能用GCC编译,在实例化期间出现错误。如果X::bb是一个类,它将编译。Como具有相同的行为。
编辑,我想我现在理解得更好了。
class Foo::Bar;
是一个详细的类说明符。Foo::Bar作为限定名查找(3.4.4/3)。由于它是依赖的,查找必须在实例化期间的第二阶段完成。然后,如果没有找到它,或者它不是类名或enum-name,则详细的类说明符是错误的。
TL;DR g++似乎没有bug
- Visual Studio 2015:Extern "C" 和 "export" 关键字
- C++中的"inline"关键字
- 如何确保C++函数在定义之前声明(如override关键字)
- 这个语法std::class<>{}(arg1, arg2) 在C++中是什么意思?
- C++核心准则 C35 对于接口类"A base class destructor should be either public and virtual, or protected and nonv
- 使用模板进行堆栈实现; "name followed by :: must be a class or namespace"
- "Undefined class"作为is_base_of的论据
- 谷歌模拟和覆盖关键字
- 使用"class"关键字,后跟未声明的标识符
- 如何添加自定义关键字以 clang 格式被视为"class"?
- 返回类型 - C++ "class"关键字
- 为什么不使用class关键字就无法创建对象
- 当已经有"struct"时,在C++中包含'class'关键字的原因是什么?
- (SWIG c++ to Python)警告301:使用了class关键字,但不在c++模式下
- 如何在c++中使用class中的static关键字来模拟Python中@classmethod的行为
- 构造函数定义是否可以以 "class" 关键字为前缀?
- 为什么C++17在模板中有两个关键字(class和typename)用于相同的目的
- 前向类声明可与使用位置的class关键字互换
- 函数签名中的"class"关键字 - 它是标准C++吗?
- GCC和class关键字