简体   繁体   English

Clang vs GCC vs MSVC - 使用大括号括起初始化列表创建用户定义类型?

[英]Clang vs GCC vs MSVC - using brace-enclosed initializer list to create user defined type?

Was experimenting with brace-enclosed initializer list and compilers seems to behave differently (well, it's a fairly new feature), but was wondering what should be the correct behavior and especially if 'c3' mentioned below should actually compiles with private, default initialized variable? 正在试验括号封闭的初始化列表和编译器似乎行为不同(嗯,这是一个相当新的特性),但是想知道什么应该是正确的行为,特别是如果下面提到的'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'
}

This is aggregate initialization. 这是聚合初始化。

C++11 paragraph that defines an aggregate says (n3337, §8.5.1/1): 定义聚合的C ++ 11段落(n3337,§8.5.1/ 1):

An aggregate is an array or a class (Clause 9) with no user-provided constructors (12.1), no brace-or-equal initializers for non-static data members (9.2), no private or protected non-static data members (Clause 11), no base classes (Clause 10), and no virtual functions (10.3). 聚合是一个数组或类(第9节),没有用户提供的构造函数(12.1),非静态数据成员(9.2) 没有大括号或相等的初始值,没有私有或受保护的非静态数据成员(子句) 11),没有基类(第10条),也没有虚函数(10.3)。

This means that c2 is not an aggregate and auto c2_ = c2{true, '0', 0}; 这意味着c2不是聚合而且auto c2_ = c2{true, '0', 0}; should trigger a diagnostic in C++11 (and gcc is right). 应该在C ++ 11中触发诊断(并且gcc是正确的)。

However, with clang, you seem to compile in C++14 mode, which removed the "no brace-or-equal initializers" limitation (n3690, §8.5.1/1): 然而,使用clang,你似乎在C ++ 14模式下编译,它删除了“无支撑或相等的初始化器”限制(n3690,§8.5.1/ 1):

An aggregate is an array or a class (Clause 9) with no user-provided constructors (12.1), no private or protected non-static data members (Clause 11), no base classes (Clause 10), and no virtual functions (10.3). 聚合是一个数组或类(第9条),没有用户提供的构造函数(12.1),没有私有或受保护的非静态数据成员(第11条),没有基类(第10条),没有虚函数(10.3) )。

So, auto c2_ = c2{true, '0', 0}; 所以, auto c2_ = c2{true, '0', 0}; is okay in C++14. 在C ++ 14中没问题。

About auto c2__ = c2{true, '0'}; 关于auto c2__ = c2{true, '0'}; , §8.5.1/7 (n3690) says: ,§8.5.1/ 7(n3690)说:

If there are fewer initializer-clauses in the list than there are members in the aggregate, then each member not explicitly initialized shall be initialized from its brace-or-equal-initializer or, if there is no brace-or-equal-initializer , from an empty initializer list (8.5.4). 如果列表中的initializer-clause少于聚合中的成员,那么未明确初始化的每个成员都应从其brace-or-equal-initializer初始化,或者,如果没有brace-or-equal-initializer ,从空的初始化列表(8.5.4)。

Which means it's ok and clang is right to compile it in C++14 mode. 这意味着它是正确的,并且在C ++ 14模式下编译它是正确的。

c3 is not an aggregate (because of private member) neither in C++11 nor in C++14 so all compilers are correct to reject it. c3不是C ++ 11和C ++ 14中的聚合(因为私有成员)所以所有编译器都拒绝它是正确的。

 auto c2_ = c2{true, '0', 0};
 auto c2__ = c2{true, '0'};

These are fine in C++14. 这些在C ++ 14中很好。 The in-class initialization does not stop the type from being an aggregate in C++14, and the in-class value will be used when a value is not provided by the brace-initializer. 类内初始化不会阻止类型在C ++ 14中成为聚合,并且当大括号初始化程序未提供值时,将使用类内值。

auto c3_ = c3{true, '0'};

This is an error, because aggregates cannot have private: or protected: members. 这是一个错误,因为聚合不能有private:protected:成员。 Since it's not an aggregate you only have the implicitly declared default constructor. 由于它不是聚合,因此只有隐式声明的默认构造函数。 You can do the following: 您可以执行以下操作:

auto c3_ = c3{};

c2 is not an aggregate in C++11, but is in C++14. c2不是C ++ 11中的聚合,而是C ++ 14中的聚合。 So the code should not compile in the former, and should in the latter. 所以代码不应该在前者编译,而应该在后者中编译。 It looks like clang is compiling in C++14 mode. 看起来clang正在用C ++ 14模式编译。

c3 is not an aggregate due to the presence of a private data member, so it should not compile, regardless of the standard.. 由于存在private数据成员, c3不是聚合,因此无论标准如何,它都不应编译。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 gcc 不是 clang 上的错误:无法从“转换”<brace-enclosed initializer list> ' 到 'std::vector&lt;&gt;</brace-enclosed> - error on gcc not clang: cannot convert from '<brace-enclosed initializer list>' to 'std::vector<> 用大括号括起来的初始化程序列表 - brace-enclosed initializer list 模板封闭的模板化结构的初始化列表 - Brace-enclosed initializer list of templated struct 无法转换Brace封闭的初始化列表 - Cannot convert Brace-enclosed initializer list 将花括号括起来的初始化列表作为结构体返回 - Return brace-enclosed initializer list as struct 括号括起的初始化程序列表构造函数 - Brace-enclosed initializer list constructor 括号括起的初始化列表无效使用 - invalid use of brace-enclosed initializer list 类括号括起初始化列表失败 - Class brace-enclosed initializer list fails 错误:无法转换&#39; <brace-enclosed initializer list> ()&#39;从&#39; <brace-enclosed initializer list> &#39;到&#39;结构&#39; - Error: could not convert '<brace-enclosed initializer list>()' from '<brace-enclosed initializer list>' to 'struct' 我可以使用 std::initializer_list 而不是大括号封闭的初始化程序来初始化数组吗? - Can I initialize an array using the std::initializer_list instead of brace-enclosed initializer?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM