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

2024-10-26


1613. Constant expressions and lambda capture

Section: 7.5.6.3  [expr.prim.lambda.capture]     Status: C++14     Submitter: Michael Wong     Date: 2013-01-31

N3690 comment CA 16

[Moved to DR at the February, 2014 meeting.]

Since instances of a variable in constant expressions may be odr-uses, the ordering of:

may affect the semantics of a program such as the one below.

The transformation under 7.5.6 [expr.prim.lambda] paragraph 17 introduces uses of the this pointer of the operator() in its function-body. These instances of this are invalid under issue 1369 if the transformation is applied before the evaluation of the constant expressions. Without the resolution of issue 1369, another situation occurs where instances of this in the compound-statement are transformed into class member access expressions (see the initializations of addrEqA and addrEqB below).

Also, for the initialization of nonZero below, the expression fails to be a constant expression if the transformation is applied before constant expression evaluation.

Finally, the answer to the static assertion changes depending on whether the constant expression evaluation is performed before the transformation as opposed to after and whether the proposed resolution issue 1472 is enabled.

There appears to be implementation divergence regarding

Using explicit value captures is not a panacea, since the paragraph 17 transformations only apply to odr-uses. As a result of the resolution of issue 1472, if the reference r below happened to have been initialized with a constant expression, the value of its (modifiable) target is not captured; if the same target were specified in the initialization of the reference with a non-constant expression, its value would be captured.

  struct A {
    void foo();
  };

  struct LitType { int val; };
  constexpr int ceFunc(const LitType &x) { return x.val; }

  void A::foo() {
    constexpr LitType y = { 0 };
    static int z;
    int x, &r = z;
    [=] {
     constexpr bool addrEqA = &x == &x;         // ill-formed under issue 1369 after transformation
                                                // under paragraph 17
     constexpr bool addrEqB = &*this == &*this; // well-formed after transformation under N3290
                                                // paragraph 17
     constexpr bool nonZero = ceFunc(y);        // lvalue-to-rvalue conversion occurs only after
                                                // function invocation substitution; the closure member,
                                                // being not a variable, cannot be constexpr
     static_assert(&r != &z,
       "reference which could be captured by value found to alias target");
                                                // affected by issue 1472
    };
  }

Proposed resolution (September, 2013):

Add the following bullet to 7.7 [expr.const] paragraph 2:

A conditional-expression e is a core constant expression unless the evaluation of e, following the rules of the abstract machine (6.9.1 [intro.execution]), would evaluate one of the following expressions: