![](/img/trans.png)
[英]error on gcc not clang: cannot convert from '<brace-enclosed initializer list>' to 'std::vector<>
[英]Clang vs GCC vs MSVC - using brace-enclosed initializer list to create user defined type?
正在试验括号封闭的初始化列表和编译器似乎行为不同(嗯,这是一个相当新的特性),但是想知道什么应该是正确的行为,特别是如果下面提到的'c3'实际上应该编译私有的,默认的初始化变量?
int main() {
struct c1 {
bool b;
char c;
int i;
};
auto c1_ = c1{true, '0', 0};
//clang-3.6 - okay
//gcc-4.9 - okay
//vs-2013 - okay
// ------------------------------------------
struct c2 {
bool b;
char c;
int i = 0; // with default value
};
auto c2_ = c2{true, '0', 0};
//clang-3.6 - okay
//gcc-4.9 - error: no matching function for call to ‘c2::c2(<brace-enclosed initializer list>)’
//vs-2013 - error C2440: '<function-style-cast>' : cannot convert from 'initializer-list' to 'c2'
auto c2__ = c2{true, '0'};
//clang-3.6 - okay
//gcc-4.9 - error: no matching function for call to ‘c2::c2(<brace-enclosed initializer list>)’
//vs-2013 - error C2440: '<function-style-cast>' : cannot convert from 'initializer-list' to 'c2'
// ------------------------------------------
struct c3 {
bool b;
char c;
private:
int i = 0; // with private default value
};
auto c3_ = c3{true, '0'};
//clang-3.6 - error: no matching constructor for initialization of 'c3'
//gcc-4.9 - error: no matching function for call to ‘c3::c3(<brace-enclosed initializer list>)’
//vs-2013 - error C2440: '<function-style-cast>' : cannot convert from 'initializer-list' to 'c3'
}
这是聚合初始化。
定义聚合的C ++ 11段落(n3337,§8.5.1/ 1):
聚合是一个数组或类(第9节),没有用户提供的构造函数(12.1),非静态数据成员(9.2) 没有大括号或相等的初始值,没有私有或受保护的非静态数据成员(子句) 11),没有基类(第10条),也没有虚函数(10.3)。
这意味着c2
不是聚合而且auto c2_ = c2{true, '0', 0};
应该在C ++ 11中触发诊断(并且gcc是正确的)。
然而,使用clang,你似乎在C ++ 14模式下编译,它删除了“无支撑或相等的初始化器”限制(n3690,§8.5.1/ 1):
聚合是一个数组或类(第9条),没有用户提供的构造函数(12.1),没有私有或受保护的非静态数据成员(第11条),没有基类(第10条),没有虚函数(10.3) )。
所以, auto c2_ = c2{true, '0', 0};
在C ++ 14中没问题。
关于auto c2__ = c2{true, '0'};
,§8.5.1/ 7(n3690)说:
如果列表中的initializer-clause少于聚合中的成员,那么未明确初始化的每个成员都应从其brace-or-equal-initializer初始化,或者,如果没有brace-or-equal-initializer ,从空的初始化列表(8.5.4)。
这意味着它是正确的,并且在C ++ 14模式下编译它是正确的。
c3
不是C ++ 11和C ++ 14中的聚合(因为私有成员)所以所有编译器都拒绝它是正确的。
auto c2_ = c2{true, '0', 0};
auto c2__ = c2{true, '0'};
这些在C ++ 14中很好。 类内初始化不会阻止类型在C ++ 14中成为聚合,并且当大括号初始化程序未提供值时,将使用类内值。
auto c3_ = c3{true, '0'};
这是一个错误,因为聚合不能有private:
或protected:
成员。 由于它不是聚合,因此只有隐式声明的默认构造函数。 您可以执行以下操作:
auto c3_ = c3{};
c2
不是C ++ 11中的聚合,而是C ++ 14中的聚合。 所以代码不应该在前者编译,而应该在后者中编译。 看起来clang正在用C ++ 14模式编译。
由于存在private
数据成员, c3
不是聚合,因此无论标准如何,它都不应编译。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.