Created on 2023-02-03.00:00:00 last changed 4 months ago
Proposed resolution (approved by CWG 2024-06-28):
Change in 6.7.7 [class.temporary] paragraph 5 as follows:
There arefourfive contexts in which temporaries are destroyed at a different point than the end of the full-expression. ...
Insert a new paragraph after 6.7.7 [class.temporary] paragraph 7 as follows:
The fourth context is when a temporary object is created in the for-range-initializer of a range-based for statement. If such a temporary object would otherwise be destroyed at the end of the for-range-initializer full-expression, the object persists for the lifetime of the reference initialized by the for-range-initializer.
The fifth context is when a temporary object is created in a structured binding declaration (9.6 [dcl.struct.bind]). Any temporary objects introduced by the initializers for the variables with unique names are destroyed at the end of the structured binding declaration.
Change in 6.9.1 [intro.execution] paragraph 5 as follows:
A full-expression is...
- an unevaluated operand (7.2.3 [expr.context]),
- a constant-expression (7.7 [expr.const]),
- an immediate invocation (7.7 [expr.const]),
- an init-declarator (9.3 [dcl.decl]) (including such introduced by a structured binding (9.6 [dcl.struct.bind])) or a mem-initializer (11.9.3 [class.base.init]), including the constituent expressions of the initializer,
- an invocation of a destructor generated at the end of the lifetime of an object other than a temporary object (6.7.7 [class.temporary]) whose lifetime has not been extended, or
- an expression that is not a subexpression of another expression and that is not otherwise part of a full-expression.
Change in 9.6 [dcl.struct.bind] paragraph 4 as follows:
... Each vi is the name of an lvalue of type Ti that refers to the object bound to ri; the referenced type is Ti. The initialization of e is sequenced before the initialization of any ri. The initialization of each ri is sequenced before the initialization of any rj where i < j.
CWG 2024-06-14
The specification for the lifetime of temporaries should be moved to 6.7.7 [class.temporary].)
CWG 2024-05-03
CWG tentatively agreed that all temporaries in a structured binding (including those from default arguments of get invocations) should persist until the semicolon on the declaration as written.
Possible resolution [SUPERSEDED]:
Change in 6.9.1 [intro.execution] paragraph 5 as follows:
A full-expression is...
- an unevaluated operand (7.2.3 [expr.context]),
- a constant-expression (7.7 [expr.const]),
- an immediate invocation (7.7 [expr.const]),
- an init-declarator (9.3 [dcl.decl]) , an initializer of a structured binding declaration (9.1 [dcl.pre]), or a mem-initializer (11.9.3 [class.base.init]), including the constituent expressions of the initializer,
- an invocation of a destructor generated at the end of the lifetime of an object other than a temporary object (6.7.7 [class.temporary]) whose lifetime has not been extended, or
- an expression that is not a subexpression of another expression and that is not otherwise part of a full-expression.
Change in 9.6 [dcl.struct.bind] paragraph 4 as follows:
... Each vi is the name of an lvalue of type Ti that refers to the object bound to ri; the referenced type is Ti. The initialization of e is sequenced before the initialization of any ri. The initialization of each ri is sequenced before the initialization of any rj where i < j.
Append a new paragraph at the end of 9.6 [dcl.struct.bind] as follows:
... [ Example: ... The type of the id-expression x is "int", the type of the id-expression y is "const volatile double". -- end example ]
The initialization of e and of any ri are sequenced before the destruction of any temporary object introduced by the initializer for e or by the initializers for the ri. The temporary objects are destroyed in the reverse order of their construction.
[Accepted as a DR at the June, 2024 meeting.]
Consider:
auto [a, b] = f(X{});
If X is a tuple-like type, this is transformed to approximately the following:
auto e = f(X{}); T1 &a = get<0>(std::move(e)); T2 &b = get<1>(std::move(e));
However, the sequencing of the initializations of e, a, and b is not specified. Further, the temporary X{} should be destroyed after the initializations of a and b.
Possible resolution [SUPERSEDED]:
Change in 6.9.1 [intro.execution] paragraph 5 as follows:
A full-expression is...
- an unevaluated operand (7.2.3 [expr.context]),
- a constant-expression (7.7 [expr.const]),
- an immediate invocation (7.7 [expr.const]),
- an init-declarator (9.3 [dcl.decl]) or a mem-initializer (11.9.3 [class.base.init]), including the constituent expressions of the initializer,
- the initializers for all uniquely-named variables introduced by a structured binding declaration (9.6 [dcl.struct.bind]), including the constituent expressions of all initializers,
- an invocation of a destructor generated at the end of the lifetime of an object other than a temporary object (6.7.7 [class.temporary]) whose lifetime has not been extended, or
- an expression that is not a subexpression of another expression and that is not otherwise part of a full-expression.
Change in 9.6 [dcl.struct.bind] paragraph 4 as follows:
... Each vi is the name of an lvalue of type Ti that refers to the object bound to ri; the referenced type is Ti. The initialization of e is sequenced before the initialization of any ri. The initialization of ri is sequenced before the initialization of rj if i < j.
History | |||
---|---|---|---|
Date | User | Action | Args |
2024-07-20 13:52:34 | admin | set | status: ready -> dr |
2024-06-28 19:56:12 | admin | set | messages: + msg7763 |
2024-06-28 19:56:12 | admin | set | status: review -> ready |
2024-06-14 20:31:51 | admin | set | messages: + msg7736 |
2024-05-05 06:50:51 | admin | set | status: open -> review |
2024-05-04 22:02:54 | admin | set | messages: + msg7689 |
2023-02-03 00:00:00 | admin | create |