2011-08-05 13 views
6

que tiene una matriz que se utiliza como la memoria subyacente de un objeto de tipo T:¿Cómo puedo simular alignas (T)?

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

¿Cómo puedo hacer para asegurar memory está alineado correctamente para T objetos? En C++ 0x, podría decir:

alignas(T) char memory[sizeof T]; 

pero Visual Studio 2010 aún no es compatible con esa característica en particular.

Respuesta

10

La solución habitual (portátil) es poner la declaración de memoria en una unión con cualquier tipo incorporado en T requiere la mayor alineación. La forma más sencilla sería utilizar una unión con todos los posibles candidatos :

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; 

todavía tengo que oír hablar, y mucho menos encuentro, una máquina en la que por encima de no fue suficiente. Generalmente, solo double es suficiente. (Definitivamente es suficiente en Intel y en Sparc.)

En algunos casos extremos, esto puede dar como resultado la asignación de más memoria que necesaria, p. si T solo contiene uno o dos char. La mayoría de las veces , esto realmente no importa, y no vale la pena preocuparse, pero si que es, lo siguiente puede ser utilizado:

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 ; 
} ; 

En este caso, MaxAlignFor<T> nunca habrá más grande que T (y tener una alineación suficiente, ya que la alineación requerida será nunca será mayor que el tamaño de T).

Tenga en cuenta que nada de esto está formalmente garantizado por la norma. Pero funcionará en la práctica.

+0

¿Quiere decir 'union' en lugar de' enum', ¿verdad? – fredoverflow

+0

Sí. Los ejemplos lo aclararon, espero. –

+0

@Mehrdad Dice que VC++ no admite una determinada función. No dice que este fue el único compilador utilizado. –

5

Google para vc++ align muestra this page: use __declspec(align(#)).

+4

Que, como indica claramente el '__', es una extensión específica del compilador. –

+1

@JamesKanze: esto es 3 años tarde, pero lo mencionaré de todos modos ... sí dice Visual C++ en la pregunta :) – Mehrdad

+0

@JamesKanze: Perdón, de hecho comenté con mi teléfono y no me di cuenta que ' Estoy comentando en la publicación incorrecta. Mi respuesta debajo de su publicación estaba destinada a estar aquí, en respuesta a su comentario aquí. – Mehrdad

2

O bien asigne la memoria en el montón (que tiene la garantía de alineación) o use boost::aligned_storage.

3

Si T es un estándar de-diseño y la unión está bien formado, entonces

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

debe estar alineado.

Cuestiones relacionadas