具有非静态成员初始值设定项的类的 C++11 聚合初始化

标准中是否允许:

struct A
{
  int a = 3;
  int b = 3;
};

A a{0,1}; // ???

这个类还聚合吗?clang 接受此代码,但 gcc 不接受.

Is this class still aggregate? clang accepts this code, but gcc doesn't.

推荐答案

在 C++11 中,具有类内成员初始值设定项使结构/类不是聚合 —然而,这在 C++14 中有所改变.当我第一次遇到它时,我发现这是令人惊讶的,这种限制的基本原理是类内初始化器与用户定义的构造器非常相似,但反论点是没有人真正期望添加类内初始化器应该使他们的类/结构是非聚合的,我确定没有.

In C++11 having in-class member initializers makes the struct/class not an aggregate — this was changed in C++14, however. This is something I found surprising when I first ran into it, the rationale for this restriction is that in-class initializers are pretty similar to a user defined constructor but the counter argument is that no one really expects that adding in-class initializers should make their class/struct a non-aggregate, I sure did not.

来自 草案 C++11 部分 8.5.1 聚合(强调我的未来):

From the draft C++11 standard section 8.5.1 Aggregates (emphasis mine going forward):

聚合是没有用户提供的数组或类(第 9 条)构造函数 (12.1),非静态没有大括号或相等的初始值设定项数据成员 (9.2),没有私有或受保护的非静态数据成员(第 11 条),没有基类(第 10 条),也没有虚函数(10.3).

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).

在 C++14 中,相同的段落读取:

and in C++14 the same paragraph reads:

聚合是没有用户提供的数组或类(第 9 条)构造函数 (12.1),没有私有或受保护的非静态数据成员(第 11 条),没有基类(第 10 条),也没有虚函数(10.3).

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).

此更改包含在 N3605:成员初始化器和聚合,其具有以下摘要:

This change is covered in N3605: Member initializers and aggregates which has the following abstract:

Bjarne Stroustrup 和 Richard Smith 提出了一个关于聚合的问题初始化和成员初始化器不能一起工作.这论文提议通过采用史密斯提议的措辞来解决这个问题消除了聚合不能有的限制成员初始值设定项.

Bjarne Stroustrup and Richard Smith raised an issue about aggregate initialization and member-initializers not working together. This paper proposes to fix the issue by adopting Smith's proposed wording that removes a restriction that aggregates can't have member-initializers.

这个评论基本上总结了不愿意让它们成为聚合体:

This comment basically sums up the reluctance to allowing them to be aggregates:

聚合不能有用户定义的构造函数和成员初始化器本质上是某种用户定义的构造函数(元素)(另见核心缺陷 886).我不反对这个扩展,但它也对我们的模型有影响聚合实际上是.接受此扩展后我会想知道如何教授聚合是什么.

Aggregates cannot have user-defined constructors and member-initializers are essentially some kind of user-defined constructor (element) (see also Core Defect 886). I'm not against this extension, but it also has implications on what our model of aggregates actually is. After acceptance of this extension I would like to know how to teach what an aggregate is.

修订版N36532013 年 5 月.

更新

emsr 指出 G++ 5.0 现在支持具有非静态数据的 C++14 聚合使用 std=c++1y-std=c++14 的成员初始值设定项:

emsr points out that G++ 5.0 now supports C++14 aggregates with non-static data member initializers using either std=c++1y or -std=c++14:

struct A { int i, j = i; };
A a = { 42 }; // a.j is also 42

看到它直播.

相关文章