This is a basic example of using a dynamic unsigned char array as a "storage" for a type T.
unsigned char* storage = new unsigned char[sizeof(T)];
T* foo = new(storage) T; // line 2
// use *foo somehow
foo->~T(); //destroy our foo
delete[] storage; // Undefined as of C++23? How else to do it?
After line2, the array itself is still alive, because it provides storage to the T, which is nested within the array, but the array elements should now be out-of-lifetime, because their storage has been reused by the T, and T is not nested within them, only within the array itself.
However, how can we delete this array after we're done using it, using the pointer foo, which is a pointer to the out-of-lifetime first element?
Until (exluding) C++23 [basic.life]/6 suggested to allow, or at least didn't forbid, to use this pointer in the delete expression:
The program has undefined behavior if: (6.1) the object will be or was of a class type with a non-trivial destructor and the pointer is used as the operand of a delete-expression,
this does not apply to unsigned char at it's not a class type. However, starting in C++23 this sentence was changed to
The program has undefined behavior if: (6.1) the pointer is used as the operand of a delete-expression,
which now includes unsigned char.
Does this mean it's not supposed to be possible anymore to use a char-array as storage in this way?
My research into the standard has given me 3 possible interpratations so far:
it might have something to do with the "object representation" now being defined to be an array of unsigned chars, meaning that, potentially, the pointer has now come to point to a new unsigned char, part of the "object representation" and is therefore still alive, or
the entire basic.life/6 paragrah is not supposed to apply here given that it says:
and before the storage which the object occupied is reused
which has happened, although this reuse has also ended again by calling ~T(), or
- could it even be possible that this was never supposed to work with arrays created with a
new-expression considering that thenew-expression does not allow us to specify the required alignment anyway?
Which of these, if any, might be correct?