Обычное (переносимое) решение - поместить объявление памяти в объединение с любым встроенным типом в T
, который требует наибольшего выравнивания.Простейшим способом было бы использовать объединение со всеми вероятными кандидатами:
union MaxAlign
{
int i ;
long l ;
long long ll ;
long double ld ;
double d ;
void* p ;
void (* pf)() ;
MaxAlign* ps ;
} ;
union
{
MaxAlign dummyForAlignment;
unsigned char memory[sizeof(T)];
} rawT;
Я еще не слышал о, а тем более столкновении, машине, которой вышеупомянутого недостаточно.Как правило, достаточно double
.(Это определенно достаточно для Intel и Sparc.)
В некоторых крайних случаях это может привести к выделению большего объема памяти, чем необходимо, например, если T
содержит только одну или две char
.В большинстве случаев это действительно не имеет значения и не стоит беспокоиться, но если это так, можно использовать следующее:
namespace MyPrivate {
template< typename T, bool isSmaller >
struct AlignTypeDetail ;
template< typename T >
struct AlignTypeDetail< T, false >
{
typedef T type ;
} ;
template< typename T >
struct AlignTypeDetail< T, true >
{
typedef char type ;
} ;
template< typename T, typename U >
struct AlignType
{
typedef typename AlignTypeDetail< U, (sizeof( T ) < sizeof( U )) >::type
type ;
} ;
}
template< typename T >
union MaxAlignFor
{
typename MyPrivate::AlignType< T, char >::type c ;
typename MyPrivate::AlignType< T, short >::type s ;
typename MyPrivate::AlignType< T, int >::type i ;
typename MyPrivate::AlignType< T, long >::type l ;
typename MyPrivate::AlignType< T, long long >::type ll ;
typename MyPrivate::AlignType< T, float >::type f ;
typename MyPrivate::AlignType< T, double >::type d ;
typename MyPrivate::AlignType< T, long double >::type ld ;
typename MyPrivate::AlignType< T, void* >::type pc ;
typename MyPrivate::AlignType< T, MaxAlign* >::type ps ;
typename MyPrivate::AlignType< T, void (*)() >::type pf ;
} ;
В этом случае MaxAlignFor<T>
никогда не будетбольше T
(и иметь достаточное выравнивание, поскольку требуемое выравнивание никогда не будет больше размера T
).
Обратите внимание, что стандарт официально не гарантирует ничего из этого.Но на практике это сработает.