Reputation: 1
Consider the following example:
#include <iostream>
using namespace std;
int main() {
int n=1;
[]()
{
n;// (1): error
}();
}
According to c++20 :
A variable x whose name appears as a potentially-evaluated expression E is odr-used by E unless
...
— x is a variable of non-reference type, and E is an element of the set of potential results of a discarded-value expression (7.2) to which the lvalue-to-rvalue conversion is not applied.
And also in c++20 :
A local entity (6.1) is odr-usable in a declarative region (6.4.1) if:
(9.1) — either the local entity is not *this, or an enclosing class or non-lambda function parameter scope exists and, if the innermost such scope is a function parameter scope, it corresponds to a non-static member function, and
(9.2) — for each intervening declarative region (6.4.1) between the point at which the entity is introduced and the region (where *this is considered to be introduced within the innermost enclosing class or non-lambda function definition scope), either:
(9.2.1) — the intervening declarative region is a block scope, or
(9.2.2) — the intervening declarative region is the function parameter scope of a lambda-expression that has a simple-capture naming the entity or has a capture-default, and the block scope of the lambda-expression is also an intervening declarative region.
If a local entity is odr-used in a declarative region in which it is not odr-usable, the program is ill-formed
(1) is a discarded-value expression so "n" is not odr-used and can therefore be used in a lambda without capture (according to the above rules ). So why is (1) error?
Upvotes: 0
Views: 158
Reputation: 2448
Your analysis is correct: n
is not odr-used by its appearance in the lambda body, so it does not have to be captured, which makes this program well-formed. Curiously, none of the major implementations seem to get this right.
The change that made this case valid was introduced by the resolution of CWG2083, prior to which [basic.def.odr]/3 used to read:
A variable
x
whose name appears as a potentially-evaluated expressionex
is odr-used byex
unless applying the lvalue-to-rvalue conversion tox
yields a constant expression that does not invoke any non-trivial functions and, ifx
is an object,ex
is an element of the set of potential results of an expressione
, where either the lvalue-to-rvalue conversion is applied toe
, ore
is a discarded-value expression.
The relevant part of the change is that the "not odr-used if discarded" property now applies to all non-reference variables, rather than only to (a subset of) those usable in constant expressions.
Upvotes: 0