Как я мог бы реализовать совместимое хранилище стеков в С++ 03?

В коде С++ 03, как я портативно реализовать буфер unsigned char[sizeof(T)], который имеет тот же размер и выравнивание, что и у данного типа T?

Например:

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 */ }
}

Возможно ли это, или вы вынуждены использовать расширения компилятора, чтобы реализовать это?

Ответ 1

В колонке Guru Of The Week # 28 Herb Sutter использует союз, но он менее надежный, чем усилия Boost.

Boost aligned_storage решает детали gory для вас. Если вы посмотрите на его реализацию, вы увидите, что он использует MSCV __alignof или GCC __alignof__, а также другой шаблон: type_with_alignment.

Из моей собственной базы кода, которую я когда-то использовал (был получен из ссылки GOTW выше):

#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)

В эти дни я бы просто полагался на Boost, так как он, вероятно, охватывает гораздо больше угловых случаев и специфики компилятора

Ответ 2

Расширения компилятора причины, такие как __alignof и __attribute__((aligned(n)), заключаются в том, что определение и принудительное выравнивание не могут быть реализованы портативно в C и С++. То есть стандарт не требует никаких средств для этого.