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

问题描述 投票:0回答:1

考虑以下代码片段:

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

{}
中的
void({})
到底是什么?
怎么解释?

当然只是出于好奇。无论如何,让我们走得更远吧。

请注意,GCC 6.1 和 clang 3.8 编译它都没有错误 (

-std=c++14 -pedantic
)。
后者不抱怨,前者显示警告:

警告:非类类型的列表初始值设定项不得加括号

使用

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

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

c++ gcc clang c++14 language-lawyer
1个回答
15
投票

void
类型的转换以及返回
void
值的可能性从一开始就存在于 C++ 语言中。唯一引起疑问的部分是
{}
在这种情况下的作用。

使用 clang 进行快速实验

int a({});

生成一条错误消息,指出

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

这表明 clang 将

{}
解释为
void
值。这似乎是一种不标准的行为。我在语言规范中没有看到任何地方说
{}
应该在这种情况下产生
void
值。

但是由于clang中恰好存在这种情况,所以在clang中编译

void({})
并没有什么异常。 C++ 中的任何值都可以转换为
void
类型,这意味着只要编译器在此上下文中接受
{}
,其余的就自然而然了。

在 GCC 中,这实际上是

-pedantic-errors
模式下的错误

error: list-initializer for non-class type must not be parenthesized

因此,在 GCC 中,它是一个“错误”,而不是“警告”。


这里实际发生的是,打开

({
和关闭
})
的组合使这些编译器将其解释为称为 Statement Expression 的 GNU C 语言扩展(顺便说一下,clang 也支持它)。例如,这就是使以下代码编译的原因

int a = ({ 3; });

在该扩展下,表达式

({})
被视为
void
类型的语句表达式。然而,这与 C++ 中的统一初始化语法相冲突。

© www.soinside.com 2019 - 2024. All rights reserved.