Title
Temporary lifetime extension for reference init-captures
Status
review
Section
7.5.6.3 [expr.prim.lambda.capture]
Submitter
Tomasz Kamiński

Created on 2023-05-23.00:00:00 last changed 9 months ago

Messages

Date: 2024-03-03.21:57:08

Proposed resolution (reviewed by CWG 2024-03-01):

Change in 7.5.6.3 [expr.prim.lambda.capture] paragraph 6 as follows:

An init-capture inhabits the lambda scope (6.4.5 [basic.scope.lambda]) of the lambda-expression. An init-capture without ellipsis behaves as if it declares and explicitly captures a variable of the form “auto init-capture ;”, except that:
  • if the capture is by copy (see below), the non-static data member declared for the capture and the variable are treated as two different ways of referring to the same object, which has the lifetime of the non-static data member, and no additional copy and destruction is performed, and
  • if the capture is by reference and the reference would bind to an object that is the result of a temporary expression, the program is ill-formed, and
  • if the capture is by reference, the variable's lifetime ends when the closure object's lifetime ends.
Date: 2024-03-03.21:57:08

Consider:

  struct S {};
  const S f();
  auto x = [&ref = f()] { return ref; }

Subclause 7.5.6.3 [expr.prim.lambda.capture] paragraph 6 specifies:

An init-capture inhabits the lambda scope (6.4.5 [basic.scope.lambda]) of the lambda-expression. An init-capture without ellipsis behaves as if it declares and explicitly captures a variable of the form “auto init-capture ;”, except that:
  • if the capture is by copy (see below), the non-static data member declared for the capture and the variable are treated as two different ways of referring to the same object, which has the lifetime of the non-static data member, and no additional copy and destruction is performed, and
  • if the capture is by reference, the variable's lifetime ends when the closure object's lifetime ends.

It is unclear whether the temporary returned by f() is lifetime-extended by being bound to a reference init-capture.

There is implementation divergence: gcc rejects the example; clang accepts and extends the lifetime of the temporary; MSVC and EDG accept and do not extend the lifetime.

History
Date User Action Args
2024-03-03 21:57:08adminsetmessages: + msg7625
2024-03-03 21:57:08adminsetstatus: open -> review
2023-05-23 00:00:00admincreate