Question

In C++03 code, how would I portably implement an unsigned char[sizeof(T)] buffer that has the same size and alignment as that of a given type T?

For example:

template<class T>
void test()
{
    unsigned char buffer[sizeof(T)];   // <----- how do I ensure this is aligned?
    if (some_condition())
    {
        T *const obj = new(buffer) T();
        // ...
        obj->~T();
    }
    else { /* use 'buffer' for something else */ }
}

Is this even possible, or are you forced to use compiler extensions in order to implement this?

Was it helpful?

Solution

In his Guru Of The Week #28 column, Herb Sutter uses a union but it's less robust than Boost's efforts.

Boost's aligned_storage solves the gory details for you. If you look at its implementation, you'll see it uses MSCV's __alignof or GCC's __alignof__ as well as another template: type_with_alignment.

From my own codebase, I once used (derived from the GOTW link above):

#if defined(_MSC_FULL_VER) && (_MSC_FULL_VER >= 150020706)
#  pragma warning(push)
#  pragma warning(disable: 4371)
#endif // #if (defined(_MSC_FULL_VER) && (_MSC_FULL_VER >= 150020706)
      union AlignedStorage
      {
        char        storage[sizeof(T)];
        int16       dummy0;
        int32       dummy1;
        int64       dummy2;
        float       dummy3;
        double      dummy4;
        long double dummy5;
        void        (*dummy6)();
        struct      dummy7;
        int         dummy7::*dummy8;
#if defined(_MSC_FULL_VER) && (_MSC_FULL_VER >= 140050215)
#  pragma warning(push)
#  pragma warning(disable: 4121)
#endif // #if (defined(_MSC_FULL_VER) && (_MSC_FULL_VER >= 140050215)
        int         (dummy7::*dummy9)(int);
#if defined(_MSC_FULL_VER) && (_MSC_FULL_VER >= 140050215)
#  pragma warning(pop)
#endif // #if (defined(_MSC_FULL_VER) && (_MSC_FULL_VER >= 140050215)

      }; // AlignedStorage
#if defined(_MSC_FULL_VER) && (_MSC_FULL_VER >= 150020706)
#  pragma warning(pop)
#endif // #if (defined(_MSC_FULL_VER) && (_MSC_FULL_VER >= 150020706)

These days I would just rely on Boost since it likely covers many more corner cases and compiler specificities

OTHER TIPS

The reason compiler extensions like __alignof and __attribute__((aligned(n)) exist is that determining and enforcing alignment can not be implemented portably in C and C++. I.e. the standard requires no means to do that.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top