This is because y.n
is not odr-used and therefore does not require an access to y.n
the rules for odr-use are covered in 3.2
and says:
A variable x whose name appears as a potentially-evaluated expression ex is odr-used unless applying the
lvalue-to-rvalue conversion (4.1) to x yields a constant expression (5.19) 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 (4.1) is applied to e, or e is a discarded-value expression
Note, Ben Voigt made some helpful comments that clarified this one a bit. So the working assumption here is that x would be:
y
and e would be(the different expression that e is defined for is covered in paragraph 2 of section 3.2):
(b ? y : x).n
y
yields a constant expression and the lvalue-to-rvalue conversion is applied to the expression e.
Since f
yields a lambda which captures f
's local variables by reference x
is no longer valid once the call to f
is done since x
is an automatic variable inside f
. Since y
is a constant expression it acts as if y.n
was not accessed and therefore we don't have the same lifetime issue.
Your example is included in N3939 section 4.1
[conv.lval] and right before that example it says:
When an lvalue-to-rvalue conversion is applied to an expression e, and either
and includes the following bullet which the examle belongs to:
the evaluation of e results in the evaluation of a member ex of the set of potential results of e, and
ex names a variable x that is not odr-used by ex (3.2),
then:
the value contained in the referenced object is not accessed
This was applied to the C++14 draft standard due to defect report 1773 .
constexpr
is evaluated at compile time and is stored in some read-only section of the program independent of the stack frame whilex
is in the stack frame, and accessing it after the stack frame has been deleted is causing undefined behavior. – Bewilder