具有非静态成员初始化器的类的 C++11 聚合初始化
Posted
技术标签:
【中文标题】具有非静态成员初始化器的类的 C++11 聚合初始化【英文标题】:C++11 aggregate initialization for classes with non-static member initializers 【发布时间】:2015-01-22 23:22:16 【问题描述】:标准是否允许:
struct A
int a = 3;
int b = 3;
;
A a0,1; // ???
这个类仍然是聚合的吗?
clang
接受此代码,但 gcc
不接受。
【问题讨论】:
【参考方案1】:在 C++11 中,具有类内成员初始值设定项使结构/类不是聚合 - 然而,这在 C++14 中已更改。这是我第一次遇到它时感到惊讶的事情,这种限制的基本原理是类内初始化器与用户定义的构造器非常相似,但相反的论点是没有人真正期望添加类内初始化器应该使他们的类/结构是非聚合的,我肯定没有。
来自draft C++11 standard 部分8.5.1
聚合(强调我的未来):
聚合是没有用户提供的数组或类(第 9 条) 构造函数(12.1),非静态没有大括号或等号初始值设定项 数据成员 (9.2),没有私有或受保护的非静态数据成员 (第 11 条),没有基类(第 10 条),没有虚函数 (10.3)。
在C++14 中,同一段内容如下:
聚合是没有用户提供的数组或类(第 9 条) 构造函数(12.1),没有私有或受保护的非静态数据成员 (第 11 条),没有基类(第 10 条),没有虚函数 (10.3)。
N3605: Member initializers and aggregates 涵盖了此更改,其摘要如下:
Bjarne Stroustrup 和 Richard Smith 提出了关于聚合的问题 初始化和成员初始化器不能一起工作。这 论文提议通过采用 Smith 提议的措辞来解决这个问题 消除了聚合不能具有的限制 成员初始化器。
这条评论基本上总结了不愿意让它们成为聚合体:
聚合不能有用户定义的构造函数和 成员初始化器本质上是某种用户定义的 构造函数(元素)(另请参见核心缺陷 886)。我不反对这个 扩展,但它也对我们的模型有影响 聚合实际上是。接受此扩展后我会 想知道如何教授聚合是什么。
修改版N3653被May 2013采纳。
更新
emsr 指出G++ 5.0 now supports C++14 aggregates with non-static data member initializers 使用std=c++1y
或-std=c++14
:
struct A int i, j = i; ;
A a = 42 ; // a.j is also 42
看到它在工作live。
【讨论】:
看来是gcc不完全支持标准的问题 @Bikineev 嗯,你使用的是哪个版本的gcc
?我无法使用-std=c++11
使用gcc
从4.7
复制到4.9
。你能澄清你的问题吗,你说clang
接受它,我猜你的意思是gcc
?
我使用 gcc 4.9.1。我的意思是 gcc 不支持提案中的这种更改。我得到:“错误:没有匹配函数调用 'A::A(-std=c+1y
,它适用于clang
,但不适用于gcc
。我无法使用-std=c++11
在clang
中使用它,这是正确的。
C++14 聚合初始化器刚刚添加到 gcc 5.0。此功能将通过 -std=c++1y 或 -std=c++14 提供。以上是关于具有非静态成员初始化器的类的 C++11 聚合初始化的主要内容,如果未能解决你的问题,请参考以下文章