Why is a const variable sometimes not required to be captured in a lambda?

后端 未结 3 1771
灰色年华
灰色年华 2020-12-08 03:44

Consider the following example:

#include 

int main() {
    const int m = 42;
    [] { m; }(); // OK

    const int n = std::rand();
    [] {          


        
3条回答
  •  没有蜡笔的小新
    2020-12-08 04:28

    Its because it is a constant expression, the compiler treats is as if it were [] { 42; }();

    The rule in [expr.prim.lambda] is:

    If a lambda-expression or an instantiation of the function call operator template of a generic lambda odr-uses (3.2) this or a variable with automatic storage duration from its reaching scope, that entity shall be captured by the lambda-expression.

    Here a quote from the standard [basic.def.odr]:

    A variable x whose name appears as a potentially-evaluated expression ex is odr-used unless applying the lvalue-to-rvalue conversion to x yields a constant expression (...) or e is a discarded-value expression.

    (Removed not so important part to keep it short)

    My simple understanding is: the compiler knows that m is constant at compile-time, whereas n will change at run-time and therefore n has to be captured. n would be odr-used, because you have to actually take a look at what is inside n at run time. In other words the fact that "there can be only one" definition of n is relevant.

    This is from a comment by M.M:

    m is a constant expression because it's a const automatic variable with constant expression initializer, but n is not a constant expression because its initializer was not a constant expression. This is covered in [expr.const]/2.7. The constant expression is not ODR-used, according to first sentence of [basic.def.odr]/3

    See here for a demo.

提交回复
热议问题