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
[Moved to DR at the February, 2014 meeting.]
Since instances of a variable in constant expressions may be odr-uses, the ordering of:
constant expression evaluation,
the determination of implicit captures, and
the transformation to use closure members for odr-uses of captured variables
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
whether the lexical instances of this in the initialization of addrEqB is valid and
whether the static assertion should pass.
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:
...
in a lambda-expression, a reference to this or to a variable with automatic storage duration defined outside that lambda-expression, where the reference would be an odr-use (6.3 [basic.def.odr], 7.5.6 [expr.prim.lambda]);
a conversion from type cv void * to a pointer-to-object type;
...