首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Clang对MSVC -使用括号-封闭初始化程序列表来创建用户定义的类型?

Clang对MSVC -使用括号-封闭初始化程序列表来创建用户定义的类型?
EN

Stack Overflow用户
提问于 2014-10-04 14:20:20
回答 3查看 891关注 0票数 2

用大括号括起来的初始化程序列表和编译器进行实验似乎有不同的行为(嗯,这是一个相当新的特性),但是想知道什么应该是正确的行为,特别是如果下面提到的'c3‘应该使用私有的默认初始化变量进行编译的话?

代码语言:javascript
复制
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'
}
EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2014-10-04 14:37:45

这是聚合初始化。

定义聚合的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)说:

如果列表中的初始化者-子句少于聚合中的成员,则未显式初始化的每个成员都应从其大括号或等初始化项中初始化,或者如果没有大括号或等初始化项,则从空初始化程序列表(8.5.4)中初始化。

这意味着可以在C++14模式下编译它。

c3在C++11或C++14中都不是一个聚合(因为是私有成员),所以所有编译器都正确地拒绝它。

票数 4
EN

Stack Overflow用户

发布于 2014-10-04 14:37:14

代码语言:javascript
复制
 auto c2_ = c2{true, '0', 0};
 auto c2__ = c2{true, '0'};

这在C++14中是很好的。类内初始化并不能阻止类型成为C++14中的聚合,当大括号初始化器没有提供值时,将使用类内值。

代码语言:javascript
复制
auto c3_ = c3{true, '0'};

这是一个错误,因为聚合不能有private:protected:成员。由于它不是聚合,所以只有隐式声明的默认构造函数。您可以执行以下操作:

代码语言:javascript
复制
auto c3_ = c3{};
票数 2
EN

Stack Overflow用户

发布于 2014-10-04 14:37:17

c2不是C++11中的聚合,而是C++14中的聚合,因此代码不应该在前者中编译,而应该在后者中编译。看起来clang是在C++14模式下编译的。

c3不是一个聚合,因为private数据成员的存在,所以它不应该编译,不管标准是什么。

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/26193718

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档