Following a snippet of code from Loki singleton implementation which shows what it calls "MaxAlign Trick". I assume it has something to do with alignment (duh!), but what's the purpose of trying to align with all the types mentioned inside the union? Will the placement new inside Create() break without it?
template <class T> struct CreateStatic
{
union MaxAlign
{
char t_[sizeof(T)];
short int shortInt_;
int int_;
long int longInt_;
float float_;
double double_;
long double longDouble_;
struct Test;
int Test::* pMember_;
int (Test::*pMemberFn_)(int);
};
static T* Create()
{
static MaxAlign staticMemory_;
return new(&staticMemory_) T;
}
// other code...
}
MaxAlignserves two purposes. First, it is an implementation of the C++11std::max_align_t: "a trivial standard-layout type whose alignment requirement is at least as strict (as large) as that of every scalar type." (cppreference). Since the alignment of a type is the alignment of the data member with the highest alignment requirements, the definition ofMaxAligngives us exactly that: a type that is guaranteed to have the max. alignment for the platform of interest.Second, it is also a buffer that is large enough to contain a
T:Taking both aspects,
MaxAlignprovides the C++11 featurestd::aligned_storage_t<size, alignment>(without taking over-alignment ofTis into account - it probably didn't even exist back then).But why is it needed: placement
newrequires the buffer to be suitably aligned for the instance that is being constructed. Without this "alignment trick", you might end up with undefined behaviour.Tbeing an unkonwn type, Loki circumvents any risks by choosing the maximal alignment for the platform the code is being compiled for.In modern code, you would probably not use placement new, but use a
staticobject on the stack, e.g.But 20 years ago, this might not have worked properly across compilers and/or in multi-threaded environments (proper initialisation of
T instancein the above is only guaranteed since C++11 IIRC).