Общее хранилище на основе char [] и исключение UB, связанных со строгим псевдонимом

Я пытаюсь создать шаблон класса, который объединяет несколько типов в достаточно большой массив символов и позволяет получить доступ к данным в виде отдельных правильно типизированных ссылок. Теперь в соответствии со стандартом это может привести к нарушению строгого псевдонима и, следовательно, к неопределенному поведению, так как мы получаем доступ кchar[] данные через объект, который не совместим с ним. В частности, стандарт гласит:

If a program attempts to access the stored value of an object through a glvalue of other than one of the following types the behavior is undefined:

the dynamic type of the object, a cv-qualified version of the dynamic type of the object, a type similar (as defined in 4.4) to the dynamic type of the object, a type that is the signed or unsigned type corresponding to the dynamic type of the object, a type that is the signed or unsigned type corresponding to a cv-qualified version of the dynamic type of the object, an aggregate or union type that includes one of the aforementioned types among its elements or non-static data members (including, recursively, an element or non-static data member of a subaggregate or contained union), a type that is a (possibly cv-qualified) base class type of the dynamic type of the object, a char or unsigned char type.

Учитывая формулировку выделенного пункта, я пришел к следующемуalias_cast идея:

#include <iostream>
#include <type_traits>

template <typename T>
T alias_cast(void *p) {
    typedef typename std::remove_reference<T>::type BaseType;
    union UT {
        BaseType t;
    };
    return reinterpret_cast<UT*>(p)->t;
}

template <typename T, typename U>
class Data {
    union {
        long align_;
        char data_[sizeof(T) + sizeof(U)];
    };
public:
    Data(T t = T(), U u = U()) { first() = t; second() = u; }
    T& first() { return alias_cast<T&>(data_); }
    U& second() { return alias_cast<U&>(data_ + sizeof(T)); }
};


int main() {
    Data<int, unsigned short> test;
    test.first() = 0xdead;
    test.second() = 0xbeef;
    std::cout << test.first() << ", " << test.second() << "\n";
    return 0;
}

(The above test code, especially the Data class is just a dumbed-down demonstration of the idea, so please don't point out how I should use std::pair or std::tuple. The alias_cast template should also be extended to handle cv qualified types and it can only be safely used if the alignment requirements are met, but I hope this snippet is enough to demonstrate the idea.)

Этот трюк заставляет замолчать предупреждения g ++ (при компиляции сg++ -std=c++11 -Wall -Wextra -O2 -fstrict-aliasing -Wstrict-aliasing), и код работает, но действительно ли это верный способ указать компилятору пропустить оптимизацию на основе строгого алиасинга?

Если он недействителен, то как можно реализовать подобный класс общего хранения на основе массива char без нарушения правил наложения имен?

Редактировать: заменяяalias_cast с простымreinterpret_cast как это:

T& first() { return reinterpret_cast<T&>(*(data_ + 0)); }
U& second() { return reinterpret_cast<U&>(*(data_ + sizeof(T))); }

выдает следующее предупреждение при компиляции с g ++:

aliastest-so-1.cpp: In instantiation of ‘T& Data::first() [with T = int; U = short unsigned int]’: aliastest-so-1.cpp:28:16:
required from here aliastest-so-1.cpp:21:58: warning: dereferencing type-punned pointer will break strict-aliasing rules [-Wstrict-aliasing]

Ответы на вопрос(1)

Ваш ответ на вопрос