The C++ compiler assumes that if two pointers have different types, they must have different addresses.
This is not always true: in HFT you often pre-allocate memory then create/destroy objects with placement new.
To avoid subtle bugs: std::launder
quoting naddr1qv…qtp8When to use std::launder?
Rule of thumb: If you use the pointer returned by
std::construct_atorplacement new, you usually don't needstd::launder. However, if you have a pre-existing pointer to storage (std::byte*,char*, etc.) that was just reused withplacement new, you should usestd::launderbefore accessing it as the new type.A common HFT use case is object pools or ring buffers that reuse preallocated memory with
placement newto avoid allocation latency. After reconstructing an object in reused storage,std::launderis used to obtain a pointer to the new live object and avoid undefined behavior caused by stale compiler lifetime assumptions.struct Tick { uint64_t ts; double px; }; // Pre-allocated memory alignas(Tick) std::byte slot[sizeof(Tick)];Producer thread:
// Placement new new(slot) Tick{ts, px};consumer thread:
// Tell the compiler that this address is now used for a new type auto* tick = std::launder(reinterpret_cast<Tick*>(slot));Use
std::launderwhen you know something the compiler doesn’t.
