gcc void({})中的{}是什么?

u5rb5r59  于 2023-10-19  发布在  其他
关注(0)|答案(1)|浏览(108)

考虑以下代码段:

auto f() { return void({}); }
int main() { f(); }

void({})中的{}到底是什么?怎么解释?
当然,只是出于好奇。我们再走远一点。
注意,GCC 6.1和clang 3.8都编译了它,没有错误(-std=c++14``-pedantic)。后者没有抱怨,前者显示了一个警告:
警告:非类类型的列表初始值设定项不能用括号括起来
使用-pedantic-errors,GCC在clang编译时以错误结束。
这种差异是两个编译器中的一个错误吗?我的意思是,它是有效的代码,应该被接受或不?

tv6aics1

tv6aics11#

转换为void类型以及返回void值的可能性从一开始就存在于 C++ 中。唯一提出问题的部分是{}在此上下文中的作用。
一个关于clang的快速实验

int a({});

生成一条错误消息,
错误:无法用“void”类型的右值初始化“int”类型的变量
这表明Clang{}解释为void值。这似乎是一种非标准行为。我没有看到语言规范中有任何地方会说{}应该在这种上下文中产生void值。
但由于这恰好是clang中的情况,因此在clang中编译void({})没有任何异常。C++中的任何值都可以转换为void类型,这意味着只要编译器在此上下文中接受{},其余的就自然地遵循。
在GCC中,它实际上是-pedantic-errors模式下的错误:
错误:非类类型的列表初始值设定项不能用括号括起来
因此,在GCC中,它是一个“错误”,而不是一个“警告”。
打开({和关闭})的组合使这些编译器将其解释为称为语句表达式的GNU C语言扩展(附带地,clang也支持)。例如,这就是使下面的代码能够编译的原因

int a = ({ 3; });

在该扩展下,表达式({})被视为void类型的语句表达式。但是,这与C++中的统一初始化语法相冲突。

相关问题