Title
Lifetime extension through static_cast
Status
open
Section
6.7.7 [class.temporary]
Submitter
Brian Bi

Created on 2022-10-17.00:00:00 last changed 1 week ago

Messages

Date: 2024-11-11.17:45:27

Suggested resolution:

Change in 6.7.7 [class.temporary] bullet 6.6 as follows:

  • ...
  • a 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.
  • ...
Date: 2024-10-15.00:00:00

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();
Date: 2023-07-28.20:24:53

Suggested resolution:

Change in 6.7.7 [class.temporary] bullet 6.6 as follows:

  • ...
  • a 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,
  • ...
Date: 2023-07-29.06:03:52

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.

History
Date User Action Args
2024-11-11 17:45:27adminsetmessages: + msg7897
2024-10-26 19:40:31adminsetmessages: + msg7857
2023-07-28 20:24:53adminsetmessages: + msg7388
2022-10-17 00:00:00admincreate