I believe this is undefined behavior.
[class.mem] gives us:
The common initial sequence of two standard-layout struct types is the longest sequence of non-static data members and bit-fields in declaration order, starting with the first such entity in each of the structs, such that corresponding entities have layout-compatible types and either neither entity is a bit-field or both are bit-fields with the same width. [...]
In a standard-layout union with an active member of struct type T1
, it is permitted to read a non-static data member m
of another union member of struct type T2
provided m is part of the common initial sequence of T1
and T2
; the behavior is as if the corresponding member of T1
were nominated.
If T
isn't a standard layout struct type, this is clearly undefined behavior. (Note that int
is not a standard layout struct type, as it's not a class type at all).
But even for standard layout struct types, what constitutes a "common initial sequence" is based strictly on non-static data members. That is, T
and struct { T val; }
do not have a common initial sequence - there are no data members in common at all!
Hence, here:
template <typename T>
union Example {
T value;
struct Wrapped {
T wrapped;
} wrapper;
};
Example<int> ex;
ex.value = 12;
cout << ex.wrapper.wrapped; // (*)
you're accessing an inactive member of the union. That's undefined.
与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…