Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I simulate alignas(T)?

I have an array which is used as the underlying memory of an object of type T:

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

How can I make sure memory is aligned correctly for T objects? In C++0x I could just say:

alignas(T) char memory[sizeof T];

but Visual Studio 2010 does not support that particular feature yet.

like image 282
fredoverflow Avatar asked Aug 05 '11 16:08

fredoverflow


2 Answers

The usual (portable) solution is to put the memory declaration in a union with whatever built-in type in T requires the most alignment. The simplest way would be to use a union with all of the likely candidates:

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;

I've yet to hear about, much less encounter, a machine where the above didn't suffice. Generally, just double suffices. (It is definitely sufficient on Intel and on Sparc.)

In some extreme cases, this can result in allocating more memory than necessary, e.g. if T only contains one or two char. Most of the time, this really doesn't matter, and isn't worth worrying about, but if it is, the following can be used:

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

In this case, MaxAlignFor<T> will never be bigger than T (and to have sufficient alignment, since the required alignment will never be larger than the size of T).

Note that none of this is formally guaranteed by the standard. But it will work in practice.

like image 128
James Kanze Avatar answered Sep 27 '22 22:09

James Kanze


Googling for vc++ align shows this page: use __declspec(align(#)).

like image 38
user541686 Avatar answered Sep 27 '22 20:09

user541686