GCC 不支持 new 表达式中的大括号省略

GCC does not support brace elision in a new-expression

考虑这个程序:

struct S {
    int m;
};

int main() {
    S s_arr[1]{0};
    S *s_new = new S[1]{0};
    int i_arr[1][1]{0};
    int (*i_new)[1] = new int[1][1]{0};
    return 0;
}

我认为主函数中的所有四个变量都应该使用聚合初始化来初始化。

然而,GCC 只接受 s_arri_arr,但拒绝 s_newi_new,报告(g++ 8.3.0 on Ubuntu):

test.cpp: In function ‘int main()’:
test.cpp:7:26: error: could not convert ‘0’ from ‘int’ to ‘S’
     S *s_new = new S[1]{0};
                          ^
test.cpp:9:38: error: array must be initialized with a brace-enclosed initializer
     int (*i_new)[1] = new int[1][1]{0};
                                      ^
test.cpp:9:38: error: array must be initialized with a brace-enclosed initializer

(注意:最后一行是g++生成的)

我也在godbolt上测试过,none的gcc版本6.1到9.2都可以编译这个程序。 6.x 和 7.x 版本还给出消息说:“抱歉,未实现:无法使用初始化程序 初始化多维数组” i_new

{0} 更改为 {{0}} 解决了在 godbolt 上测试的所有 GCC 版本(6.1 到 9.2)的 s_newinew。我可以理解这一点,因为 S[1]int[1][1] 都是聚合类型,其元素类型是子聚合(S 的数组;数组的数组)。但是,C++ 允许省略这些大括号,而 GCC 接受 s_arri_arr,其中省略这些大括号。

另一方面,clang 6.0.0到clang 9.0.0愉快地接受了原程序。

在C++14规范中(gnu++14是GCC 6.5/7.4/8.3/9.2的默认值),

5.3.4 New / 17

A new-expression that creates an object of type T initializes that object as follows:

......

(17.2) — Otherwise, the new-initializer is interpreted according to the initialization rules of 8.5 for direct initialization.

new-initializer 应该被解释为直接初始化。由于s_arri_arr也是直接初始化的,我认为它们应该以同样的方式解释,并且原始程序应该是良构的。

这里有什么我遗漏的吗,或者这是 GCC 中的错误?

我试图通过 GCC Bugzilla 进行搜索,但没有找到任何相关内容。

是的,这绝对是一个错误。 new 表达式定义为使用直接初始化规则 ([expr.new]/18.2), and brace elision applies to all cases of aggregate initialization ([dcl.init.aggr]/12)。

如果在 bugzilla 中搜索后找不到错误,请提交错误。