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

2024-12-19


2666. Lifetime extension through static_cast

Section: 6.7.7  [class.temporary]     Status: open     Submitter: Brian Bi     Date: 2022-10-17

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:

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: