46 c++ language-lawyer aggregate-initialization c++11 list-initialization
假设有一个std::array
要初始化的东西.如果使用双括号可以:
std::array<int, 2> x = {{0, 1}};
std::array<int, 2> x{{0, 1}};
Run Code Online (Sandbox Code Playgroud)
在良好的旧聚合初始化中使用单个括号也是可以的,因为括号省略将处理缺少的大括号:
std::array<int, 2> x = {0, 1};
Run Code Online (Sandbox Code Playgroud)
但是,使用单个括号的列表初始化是否可以?GCC接受它,Clang拒绝它"在使用直接列表初始化时不能省略关于子对象初始化的大括号".
std::array<int, 2> x{0, 1};
Run Code Online (Sandbox Code Playgroud)
提到括号内容的标准中唯一的部分是8.5.1/12,其中说:
使用赋值表达式初始化聚合成员时,将考虑所有隐式类型转换(第4节).如果赋值表达式可以初始化成员,则初始化成员.否则,如果成员本身是子集合,则假定使用大括号,并考虑赋值表达式初始化子集合的第一个成员.
8.5.1是关于聚合初始化的,所以应该意味着Clang是正确拒绝的,对吗?没那么快.8.5.4/3说:
列表初始化对象或类型T的引用定义如下:
[...]
- 否则,如果T是聚合,则执行聚合初始化(8.5.1).
我认为这意味着与聚合初始化完全相同的规则,包括括号elision,适用,意味着GCC是正确的接受.
我承认,措辞不是特别清楚.那么,哪个编译器正确处理第三个片段呢?括号省略是否在列表初始化中发生,或者不是?
Joh*_*itb 22
Brace elision适用,但不适用于C++ 11.在C++ 14中,它们将适用于http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#1270.如果你很幸运,Clang会将它反向移植到他们的C++ 11模式(让我们希望他们会这样做!).
相关:http : //en.cppreference.com/w/cpp/language/aggregate_initialization
简而言之,
struct S {
int x;
struct Foo {
int i;
int j;
int a[3];
} b;
};
S s1 = { 1, { 2, 3, {4, 5, 6} } };
S s2 = { 1, 2, 3, 4, 5, 6}; // same, but with brace elision
S s3{1, {2, 3, {4, 5, 6} } }; // same, using direct-list-initialization syntax
S s4{1, 2, 3, 4, 5, 6}; // error in C++11: brace-elision only allowed with equals sign
// okay in C++14
Run Code Online (Sandbox Code Playgroud)