Title
Order of initialization for structured bindings
Status
open
Section
9.6 [dcl.struct.bind]
Submitter
Richard Smith

Created on 2023-02-03.00:00:00 last changed 14 months ago

Messages

Date: 2023-02-03.00:00:00

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:

  1. 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 in 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.
    ...
  2. 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
2023-02-03 00:00:00admincreate