聚合初始化中 mem-initializer 的有效性和/或生命周期延长

eca*_*mur 6 c++ lifetime language-lawyer temporary-objects c++14

CWG 1815询问(稍作修改):

struct A {};
struct B { A&& a = A{}; };
B b1;         // #1
B b2{A{}};    // #2
B b3{};       // #3
Run Code Online (Sandbox Code Playgroud)

[...]#2是聚合初始化,它绑定B::a到初始化器中的临时对象 for b2,从而将其生命周期延长到b2. #3是聚合初始化,但不清楚非静态数据成员初始值设定项中的临时生命周期是否B::a应该像 一样延长生命周期#2,例如#1

根据关于该问题的说明,在 Issaquah (2014-02) CWG 打算使#3行为像#2;也就是说,格式良好,并执行b3.a绑定的临时对象的生命周期扩展。但在接下来的ISO会议(拉珀斯韦尔,2014-06),分辨率为CWG 1696获得通过,表面上是解决CWG 1815,但采用的语言,似乎使#3病态的

11 - 绑定到来自默认成员初始值设定项的引用成员的临时表达式格式错误。

但是,紧接在该条款下的示例不考虑聚合初始化(如 CWG 1815),而仅考虑构造函数的初始化;具体来说,默认构造函数定义为 defaulted:

struct A {
  A() = default;        // OK
  A(int v) : v(v) { }   // OK
  const int& v = 42;    // OK
};
A a1;                   // error: ill-formed binding of temporary to reference
A a2(1);                // OK, unfortunately
Run Code Online (Sandbox Code Playgroud)

因此,尽管措辞似乎很清楚,但它似乎也与委员会的意图背道而驰,这可能是认为措辞有缺陷的原因。

在实现实践方面,我们可以看到存在相当大的差异:

海湾合作委员会 MSVC 国际商会
#1 ? 破坏 ? 拒绝 ?? 泄露 ? 破坏
#2 ? 延长 ? 延长 ? 延长 ? 延长
#3 ? 延长 ? 延长 ? 延长 ? 破坏

(这里,“销毁”表示临时文件在声明结束时被销毁,即不延长生命周期。一生中#3,违背了现在的措词。奇怪的是,尽管执行了生命周期延长,但 Clang警告说它无法这样做,这表明开发人员认为在这种情况下标准要求延长生命周期:

警告:抱歉,不支持使用默认成员初始值设定项的聚合初始化创建的临时生命周期延长;临时的生命周期将在完整表达式结束时结束 [-Wdangling]

鉴于 CWG 表达的意图和实施差异,将当前措辞视为有缺陷并依赖生命周期延长是否合理#3?委员会是否意识到这种差异,是否有可能在近期或中期解决(例如作为 C++20 的 DR)?