This is an unofficial snapshot of the ISO/IEC JTC1 SC22 WG21 Core Issues List revision 115f. See http://www.open-std.org/jtc1/sc22/wg21/ for the official list.
2024-12-06
Consider:
struct S { S(int) {} }; const S& r1 = 0; // #1 const S& r2 = static_cast<const S&>(S(0)); // #2 const S& r3 = static_cast<const S&>(0); // #3 // Are r1, r2, and r3 dangling past this point?
For #1, a temporary object is materialized and the reference binds to the result of the materialization conversion. This results in lifetime extension per 6.7.7 [class.temporary] bullet 6.1.
For #2, 6.7.7 [class.temporary] bullet 6.6 requires the cast to convert "without a user-defined conversion", but S(0) is such.
For #3, a user-defined conversion is clearly required.
However, implementations treat all three cases the same and do extend the lifetime of the temporary.
Suggested resolution:
Change in 6.7.7 [class.temporary] bullet 6.6 as follows:
- ...
- a
- const_cast (7.6.1.11 [expr.const.cast]),
- static_cast (7.6.1.9 [expr.static.cast]),
- dynamic_cast (7.6.1.7 [expr.dynamic.cast]), or
- reinterpret_cast (7.6.1.10 [expr.reinterpret.cast])
converting, without a user-defined conversion, a glvalue operand that is one of these expressions to a glvalue that refers to the object designated by the operand, or to its complete object or a subobject thereof, where
- the cast does not invoke a user-defined conversion, or
- the cast invokes a user-defined conversion that yields a prvalue, and the glvalue result of the cast is bound directly (9.4.4 [dcl.init.ref]) to that prvalue,
- ...
Additional notes (October, 2024)
The suggested resolution does not use the "is one of these expressions" structure that limits the tracking of temporary objects through the expression tree required from implementation. For example:
int glob; struct A { constexpr ~A() { arr[0] = &glob; } int *arr[1]; }; constexpr int f() { int *&&ref = static_cast<int *&&>(0[+A().arr]); // note unary +; lifetime is not extended delete ref; // error: attempt to delete `&glob` return 0; } extern constexpr int x = f();
Suggested resolution:
Change in 6.7.7 [class.temporary] bullet 6.6 as follows:
- ...
- a
- const_cast (7.6.1.11 [expr.const.cast]),
- static_cast (7.6.1.9 [expr.static.cast]),
- dynamic_cast (7.6.1.7 [expr.dynamic.cast]), or
- reinterpret_cast (7.6.1.10 [expr.reinterpret.cast])
converting, without a user-defined conversion, a glvalue operand that is one of these expressions to a glvalue that refers to the object designated by the operand, or to its complete object or a subobject thereof,expression where
- the operand is one of these expressions and the cast does not invoke a user-defined conversion, or
- the result of the cast refers to an object created by a temporary materialization conversion that is required or performed by the cast, or to a subobject of such an object, where
- the cast does not invoke a user-defined conversion, or
- the temporary materialization conversion is applied to the prvalue result of a user-defined conversion that is applied to the operand.
- ...