Consider the following example in C++14:
alignas(T) unsigned char data[sizeof(T)];
new (data) T();
T* p = reinterpret_cast<T*>(data);
p->something(); // UB?
Is this code legal, or are the Strict Aliasing rules being violated, since unsigned char* may not be aliased by T*? If it's legal, what parts of the Standard explicitly say so?
cppreference has a similar example which claims std::launder must be used in C++17. What does this mean for C++14, where we don't have std::launder?
// Access an object in aligned storage
const T& operator[](std::size_t pos) const
{
// Note: std::launder is needed after the change of object model in P0137R1
return *std::launder(reinterpret_cast<const T*>(&data[pos]));
}
Thanks everyone for your replies! I will try to answer the question combining the knowledge I've gotten from the responses.
There is no Strict Aliasing violation
As per basic.life#2:
Therefore, after the placement
newcall, thechararray no longer contains objects of typechar. It contains a newly created object of typeT.Later, we access the object of type
Tvia aT*, which is a valid alias. Therefore, Strict Aliasing rules are not violated here.Lifetime
The real problem is lifetime. When we
reinterpret_cast<T*>(data), we are using a pointer (data) that points to expired data, since it has been replaced by the new object. There is no guarantee that thedatapointer is "updated" to point to the newly-created object.Tvia the pointer returned by placementnew.data, as long as we launder it viastd::launder. This allows not having to store the pointer returned by placementnew.