请考虑以下代码段:
auto f() { return void({}); }
int main() { f(); }
{}
中的void({})
究竟是什么?
它是如何解释的?
当然是出于好奇。不管怎样,让我们走得更远。
请注意,GCC 6.1和clang 3.8都编译它没有错误(-std=c++14 -pedantic
)
后者没有抱怨,前者显示警告:
警告:非类型的list-initializer不能带括号
使用-pedantic-errors
代替,当clang编译时,GCC以错误结束。
这种差异是否是两个编译器之一的错误?
我的意思是,它是否应该被接受的有效代码?
答案 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 ++中的统一初始化语法冲突。