CWG Issue 2569 (original) (raw)

This is an unofficial snapshot of the ISO/IEC JTC1 SC22 WG21 Core Issues List revision 118f. See http://www.open-std.org/jtc1/sc22/wg21/ for the official list.

2025-11-07


2569. Use of decltype(capture) in a lambda's parameter-declaration-clause

Section: 7.5.5.2 [expr.prim.id.unqual]Status: CD6Submitter: Barry RevzinDate: 2022-04-16Liaison: EWG

[Accepted at the July, 2022 meeting as part of paper P2579R0 (Mitigation strategies for P2036 "Changing scope for lambda trailing-return-type").]

Paper P2036R3disallowed using captures in the _parameter-declaration-clause_of a lambda, because it is not yet known at that point whether the lambda is going to be mutable, and thus the type of an expression referring to a capture may or may not be const. Such problematic uses of captures are now ill-formed. The paper was approved as a Defect Report, recommending to implementers to apply the change to all language modes back to C++11.

However, that broke legitimate uses in popular implementations of the standard library such as:

local_end it) { return it != local_end; };

As specified in 9.2.9.6 [dcl.type.decltype] bullet 1.3,decltype(local_end) does not depend on whether the lambda ends up being mutable or not:

Possible approaches (not necessarily exclusive):

Suggested resolution (carves out an exception fordecltype, sizeof, noexcept):

Change in 7.5.5.2 [expr.prim.id.unqual] paragraph 3 as follows:

An unqualified-id is mutable-agnostic if it is the operand of a decltype(9.2.9.6 [dcl.type.decltype]), sizeof(7.6.2.5 [expr.sizeof]), or noexcept(7.6.2.7 [expr.unary.noexcept]). If the _unqualified-id_appears in a lambda-expression at program point P and the entity is a local entity (6.1 [basic.pre]) or a variable declared by an init-capture (7.5.6.3 [expr.prim.lambda.capture]), then let S be the compound-statement of the innermost enclosing lambda-expression of P. If naming the entity from outside of an unevaluated operand within S would refer to an entity captured by copy in some intervening lambda-expression, then let E be the innermost such lambda-expression, and:

[Example:

[=]<decltype(x) P>{}; // ok: P has type float [=]<decltype((x)) P>{}; // error: x refers to local entity but precedes the // lambda's function parameter scope = y){}; // error: x refers to local entity but is in the lambda's // parameter-declaration-clause

-- end example]

Suggested resolution (carves out an exception for decltype only):

Change in 7.5.5.2 [expr.prim.id.unqual] paragraph 3 as follows:

If the unqualified-id appears in a lambda-expression at program point P and the entity is a local entity (6.1 [basic.pre]) or a variable declared by an init-capture (7.5.6.3 [expr.prim.lambda.capture]), then let S be the compound-statement of the innermost enclosing lambda-expression of P. If naming the entity from outside of an unevaluated operand within S would refer to an entity captured by copy in some intervening lambda-expression, then let E be the innermost such lambda-expression, and:

[Example:

[=]<decltype(x) P>{}; // ok: P has type float [=]<decltype((x)) P>{}; // error: x refers to local entity but precedes the // lambda's function parameter scope = y){}; // error: x refers to local entity but is in the lambda's // parameter-declaration-clause

-- end example]

Additional notes (April, 2022):

Forwarded to EWG withpaper issue 1227, by decision of the CWG chair.

See paper P2579R0 for a more detailed discussion of the issue.