最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

lambda - Discarded-value expression and odr-used in C++20 - Stack Overflow

programmeradmin3浏览0评论

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?

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?

Share Improve this question edited Jan 24 at 2:11 Igor Tandetnik 52.6k4 gold badges62 silver badges90 bronze badges asked Jan 18 at 12:46 RedRed 11 silver badge1 bronze badge 9
  • What names can be mentioned inside lambda has nothing to do with odr-use. "[expr.prim.lambda.capture]/1 The body of a lambda-expression may refer to variables with automatic storage duration and the *this object (if any) of enclosing block scopes by capturing those entities, as described below. [expr.prim.lambda.capture]/7 For the purposes of lambda capture, an expression potentially references local entities as follows:... An id-expression that names a local entity potentially references that entity" – Igor Tandetnik Commented Jan 18 at 14:38
  • @ Igor Tandetnik: Why can constexpr variable be used in lambda without capture? – Red Commented Jan 23 at 15:58
  • constexpr implies static. Static variables are not local entities. "[basic.pre]/7 A local entity is a variable with automatic storage duration, a structured binding whose corresponding variable is such an entity, or the *this object." – Igor Tandetnik Commented Jan 23 at 20:52
  • @ Igor Tandetnik, constexpr variable is not static. – Red Commented Jan 24 at 1:10
  • Ah. Lambda is a red herring. It's just a shorthand for defining a class with operator(). So we can reproduce this by writing such a class explicitly (uncomment constexpr and it compiles). Curiously, if n; is replaced with &n;, it fails with constexpr as well. So it looks like you are right and it may have something to do with odr-use after all. – Igor Tandetnik Commented Jan 24 at 1:42
 |  Show 4 more comments

1 Answer 1

Reset to default 0

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 expression ex is odr-used by ex unless applying the lvalue-to-rvalue conversion to x yields a constant expression that does not invoke any non-trivial functions and, if x is an object, ex is an element of the set of potential results of an expression e, where either the lvalue-to-rvalue conversion is applied to e, or e 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.

发布评论

评论列表(0)

  1. 暂无评论