考虑以下代码段:
auto f() { return void({}); }
int main() { f(); }
void({})
中的{}
到底是什么?怎么解释?
当然,只是出于好奇。我们再走远一点。
注意,GCC 6.1和clang 3.8都编译了它,没有错误(-std=c++14``-pedantic
)。后者没有抱怨,前者显示了一个警告:
警告:非类类型的列表初始值设定项不能用括号括起来
使用-pedantic-errors
,GCC在clang编译时以错误结束。
这种差异是两个编译器中的一个错误吗?我的意思是,它是有效的代码,应该被接受或不?
1条答案
按热度按时间tv6aics11#
转换为
void
类型以及返回void
值的可能性从一开始就存在于 C++ 中。唯一提出问题的部分是{}
在此上下文中的作用。一个关于clang的快速实验
生成一条错误消息,
错误:无法用“void”类型的右值初始化“int”类型的变量
这表明Clang将
{}
解释为void
值。这似乎是一种非标准行为。我没有看到语言规范中有任何地方会说{}
应该在这种上下文中产生void
值。但由于这恰好是clang中的情况,因此在clang中编译
void({})
没有任何异常。C++中的任何值都可以转换为void
类型,这意味着只要编译器在此上下文中接受{}
,其余的就自然地遵循。在GCC中,它实际上是
-pedantic-errors
模式下的错误:错误:非类类型的列表初始值设定项不能用括号括起来
因此,在GCC中,它是一个“错误”,而不是一个“警告”。
打开
({
和关闭})
的组合使这些编译器将其解释为称为语句表达式的GNU C语言扩展(附带地,clang也支持)。例如,这就是使下面的代码能够编译的原因在该扩展下,表达式
({})
被视为void
类型的语句表达式。但是,这与C++中的统一初始化语法相冲突。