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

时间:2016-12-13 22:40:47

标签: c++ gcc clang c++14 language-lawyer

请考虑以下代码段:

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

{}中的void({})究竟是什么? 它是如何解释的?

当然是出于好奇。不管怎样,让我们​​走得更远。

请注意,GCC 6.1和clang 3.8都编译它没有错误(-std=c++14 -pedantic) 后者没有抱怨,前者显示警告:

  

警告:非类型的list-initializer不能带括号

使用-pedantic-errors代替,当clang编译时,GCC以错误结束。

这种差异是否是两个编译器之一的错误?
我的意思是,它是否应该被接受的有效代码?

1 个答案:

答案 0 :(得分:15)

从一开始就在C ++语言中出现了转换为void类型以及返回void值的可能性。提出问题的唯一部分是{}在这种情况下的作用。

使用clang进行快速实验

int a({});

生成错误消息

error: cannot initialize a variable of type 'int' with an rvalue of type 'void'

表示clang将{}解释为void值。这似乎是一种非标准行为。我没有看到语言规范中的任何地方会说{}应该在此上下文中生成void值。

但是因为在clang中就是这种情况,所以在void({})编译clang时没有什么不寻常之处。 C ++中的任何值都可以转换为void类型,这意味着只要编译器在此上下文中接受{},其余的就会自然地跟随。

在GCC中,-pedantic-errors模式

实际上是一个错误
error: list-initializer for non-class type must not be parenthesized

正式地说这是一个“错误”,而不是GCC中的“警告”。

这里实际发生的是,打开({和关闭})的组合使得这些编译器将其解释为GNU C语言扩展,称为Statement Expression(顺便提供支持铿锵)。例如,这就是使以下代码编译的原因

int a = ({ 3; });

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