Validity and/or lifetime extension of mem-initializer in aggregate initialization

南笙酒味 提交于 2021-01-20 20:01:27

问题


CWG 1815 asked (with minor edits):

struct A {};
struct B { A&& a = A{}; };
B b1;         // #1
B b2{A{}};    // #2
B b3{};       // #3

[...] #2 is aggregate initialization, which binds B::a to the temporary in the initializer for b2 and thus extends its lifetime to that of b2. #3 is aggregate initialization, but it is not clear whether the lifetime of the temporary in the non-static data member initializer for B::a should be lifetime-extended like #2 or not, like #1.

Per the Notes on that issue, at Issaquah (2014-02) CWG intended to make #3 behave like #2; that is, well-formed, and performing lifetime extension of the temporary to which b3.a binds. But at the next ISO meeting (Rapperswil, 2014-06) the resolution to CWG 1696 was adopted, ostensibly resolving CWG 1815 but adopting language that appears to make #3 ill-formed:

11 - A temporary expression bound to a reference member from a default member initializer is ill-formed.

However, the example immediately under that clause does not consider aggregate initialization (as in CWG 1815) but only initialization by constructor; specifically, a default constructor defined as 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

So although the wording seems clear, it would also seem contrary to the intent of the Committee, which could be reason to consider the wording defective.

In terms of implementation practice, we can see that there is considerable variance:

gcc clang MSVC ICC
#1 ❌ destroy ✅ reject ☠️ leak ❌ destroy
#2 ✅ extend ✅ extend ✅ extend ✅ extend
#3 ❌ extend ❌ extend ❌ extend ❌ destroy

(Here, "destroy" means the temporary is destructed at the end of the declaration i.e. not lifetime-extended. ✅ indicates conformance, ❌ non-conformance, ☠️ a clear defect.) However, other than ICC, the compilers agree on extending lifetime in #3, contrary to the current wording. Oddly, despite performing lifetime extension, Clang warns that it is unable to do so, indicating that the developers consider lifetime extension to be required by the Standard in this case:

warning: sorry, lifetime extension of temporary created by aggregate initialization using default member initializer is not supported; lifetime of temporary will end at the end of the full-expression [-Wdangling]

Question

Given the expressed intent of CWG, and implementation variance, is it reasonable to consider the current wording as defective and to rely on lifetime extension occurring in #3? Are the Committee aware of this discrepancy and is there prospect of it being resolved in the near or medium term (as a DR to C++20, say)?

来源:https://stackoverflow.com/questions/65528744/validity-and-or-lifetime-extension-of-mem-initializer-in-aggregate-initializatio

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!