I am trying to wrap my head around the implicit lifetime and aliasing rules in C++.
The standard says:
Some operations are described as implicitly creating objects within a specified region of storage. For each operation that is specified as implicitly creating objects, that operation implicitly creates and starts the lifetime of zero or more objects of implicit-lifetime types in its specified region of storage if doing so would result in the program having defined behavior.
And:
An operation that begins the lifetime of an array of unsigned char or std::byte implicitly creates objects within the region of storage occupied by the array.
As well as providing an example that states:
// The call to std::malloc implicitly creates an object of type X
Does that mean that the following is legal and correct?
constexpr size_t N = 10;
constexpr size_t S = sizeof(uint32_t);
std::vector<std::byte> buffer;
buffer.resize(N * S);
for (size_t i = 0; i < N * S; i += S)
*reinterpret_cast<uint32_t*>(&buffer.data()[i + 2 * S]) = 42;
uint32_t x;
for (size_t i = 0; i < S; ++i)
*(reinterpret_cast<std::byte*>(&x) + i) = buffer[i];
assert(x == 42);
If not, what am I missing? And is there a way to make it legal using the C++23 subset that LLVM 17 (Clang and libc++) supports?
Note: Even though I tagged the question as "language lawyer", I myself am not one, so I would very much appreciate an explanation in as "simple" terms as possible.
vector<byte>does not automatically createuint32_tobjects in the allocated memory. Only malloc-like allocations guarantee this. You are probably looking forstd::start_lifetime_as.i + 2 * S? Gratuitously indexing out of range detracts from your example. (Wheniis(N-1)*Sin the last iteration, the index is(N*S - S) + 2*SorN*S + S, which is larger thanN*S.) Not to mention that skipping the first2*Selements ofbuffereasily causes yourassertto fail.vector<byte>does not implicitly start the lifetime of whatever objects you are planning to use it for.