它是如何解析的:用带括号的init列表构造未命名的临时对象

How is it parsed: constructing unnamed temporary with braced init list

本文关键字:init 列表 临时对象 未命名 何解析      更新时间:2023-10-16

我最近又遇到了符号

( const int[10] ){ 10, 9, 8, 7, 6, 5, 4, 3, 2, 1 }

我记得它在C和c++中都是允许的,但是通过完全不同的语言机制。

我认为,在c++中,正式的观点是,它是通过显式类型转换(T) 强制转换表达式构造一个未命名的临时对象,它将简化为static_cast,通过c++ 11§5.2.9/4:

构造一个对象。

如果声明T t(e);格式良好,则表达式e可以使用static_cast形式的static_cast<T>(e)显式转换为T类型,对于某些虚构的临时变量t (8.5)

然而,类型转换表达式语法在c++ 11§5.4/2中定义为一元表达式,或者递归地定义为( 类型id ) 类型转换表达式,其中单个基本情况被简化为一元表达式

就我所知,带括号的 init-list不是表达式?

另一种观点是,它是通过函数表示法进行的显式类型转换,c++ 11§5.2.3/3

一个简单类型说明符类型名称说明符跟一个带括号的init-list创建一个临时类型指定类型

的对象。

但是据我所知,简单类型说明符不能涉及括号,而类型说明符涉及关键字typename ?

Per C99(实际上是N1256,这是先前的草案)6.5.2.5/4:

由带圆括号的类型名和用大括号括起来的初始化式列表组成的后缀表达式是复合字面值。它提供了一个未命名的对象,其值由初始化列表给出。

一些编译器——至少是c++和clang——在c++中提供了C99复合文字作为扩展。在语义上,表达式

( const int[10] ){ 10, 9, 8, 7, 6, 5, 4, 3, 2, 1 }

const int[10]类型的字面值:decltype((const int[10]){ 10, 9, 8, 7, 6, 5, 4, 3, 2, 1 })实际上是const int[10]注意:在g++版本之间关于确切类型有一些分歧:4.9之前的g++版本说decltype((const int[10]){ 10, 9, 8, 7, 6, 5, 4, 3, 2, 1 })const int(&)[10]。请看这个演示程序。

你可以在标准c++中通过函数表示法实现显式类型转换,但是你必须为数组类型定义一个类型别名,因为函数表示法需要一个简单类型说明符:

using foo = const int[10];
foo{ 10, 9, 8, 7, 6, 5, 4, 3, 2, 1 };

或Xeo的通用别名模板:

template <typename T>
using foo = T;
foo<const int[10]>{ 10, 9, 8, 7, 6, 5, 4, 3, 2, 1 };