Как я могу симулировать alignas (T)? - PullRequest
6 голосов
/ 05 августа 2011

У меня есть массив, который используется в качестве базовой памяти для объекта типа T:

char memory[sizeof T];
.
.
.
new(memory) T(whatever);

Как я могу убедиться, что memory выровнен правильно для T объектов?В C ++ 0x я мог бы просто сказать:

alignas(T) char memory[sizeof T];

, но Visual Studio 2010 пока не поддерживает эту особую функцию.

Ответы [ 4 ]

10 голосов
/ 05 августа 2011

Обычное (переносимое) решение - поместить объявление памяти в объединение с любым встроенным типом в 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).

Обратите внимание, что стандарт официально не гарантирует ничего из этого.Но на практике это сработает.

5 голосов
/ 05 августа 2011

Поиск в Google для vc++ align показывает эту страницу : используйте __declspec(align(#)).

3 голосов
/ 05 августа 2011

Если T стандартная схема и объединение правильно сформировано, то

union
{
   T t;
   char memory[sizeof T];
};

должно быть выровнено.

2 голосов
/ 05 августа 2011

Либо выделите память в куче (которая имеет гарантию выравнивания), либо используйте boost::aligned_storage.

...