In several location within the standard, storage reuse is mentioned, such as here: https://timsong-cpp.github.io/cppwp/n4861/basic.life#1.5.
But I cannot get a proper definition of what is a storage reuse vs what would be an incorrect object creation. I'll illustrate that with the following snippet:
#include
#include
#include
int main() {
std::byte storage[10000];
std::int32_t *po0 = new (storage + 2 * sizeof(std::int32_t)) std::int32_t;
// does this "reuse" po0 storage?
std::int16_t *po1 = new (storage + 2 * sizeof(std::int32_t)) std::int16_t;
// std::int64_t *po2 = new (storage + 2 * sizeof(std::int32_t)) std::int64_t;
// std::int16_t *po3 =
// new (storage + 2 * sizeof(std::int32_t) + sizeof(std::int8_t))
// std::int16_t;
// std::int32_t *po4 =
// new (storage + 2 * sizeof(std::int32_t) + sizeof(std::int32_t))
// std::int32_t;
// std::int32_t *po5 =
// new (storage + 2 * sizeof(std::int32_t) - sizeof(std::int16_t))
// std::int32_t;
// std::int64_t *po6 =
// new (storage + 2 * sizeof(std::int32_t) - sizeof(std::int16_t))
// std::int64_t;
}
NB for simplicity sake, I didn't consider alignment issues but only where the new object creation is occurring (before the first object, at same location, inside the object) and how the new object is overlapping the first one.
NB I used integers for the example, but it can be any type.
NB consider that only one of the six objects *po1 to *po6 is created.
Which of these 6 object creation by placement new are valid and constitute a storage reuse, that will end *po0 lifetime?
Here is a graphical representation of the different scenarios:
| po0 | po0 | po0 | po0 | ||||||
|---|---|---|---|---|---|---|---|---|---|
| po1 | po1 | ||||||||
| po2 | po2 | po2 | po2 | po2 | po2 | po2 | po2 | ||
| po3 | po3 | ||||||||
| po4 | po4 | po4 | po4 | ||||||
| po5 | po5 | po5 | po5 | ||||||
| po6 | po6 | po6 | po6 | po6 | po6 | po6 | po6 |