I think the following code is ubiquitous:
struct A { ... };
char buf[1024];
auto ptr = new (buf) A(...);
However, new (buf) A(...);
is UB. https://en.cppreference.com/w/cpp/language/lifetime.html says (emphasis mine):
As a special case, objects can be created in arrays of unsigned char or std::byte (since C++17) (in which case it is said that the array provides storage for the object) if:
- the lifetime of the array has begun and not ended
- the storage for the new object fits entirely within the array
- there is no array object that satisfies these constraints nested within the array.
Therefore, the char
array is not considered as a valid storage type.
Why not allow the char
array to be the argument of placement new?
The example you show isn't UB (if buf
is suitably aligned and is big enough). "provides storage" affects whether the creation of the new object ends the lifetime of the array. But at least in the code snippet you show, whether buf
's lifetime ends is immaterial.
As to why plain char
isn't included in the "provides storage" rules...the committee apparently thought that it was a new thing so that it can have stricter rules. This is also consistent with the special treatment of unsigned char
and std::byte
for indeterminate and erroneous values.