Can I put a T
and a wrapped T
in an union
and inspect them as I like?
union Example {
T value;
struct Wrapped {
T wrapped;
} wrapper;
};
// for simplicity T = int
Example ex;
ex.value = 12;
cout << ex.wrapper.wrapped; // ?
The C++11 standards only guarantee save inspection of the common initial sequence, but value
isn't a struct
. I guess the answer is no, since wrapped types aren't even guaranteed to be memory compatible to their unwrapped counterpart and accessing inactive members is only well-defined on common initial sequences.
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 memberm
of another union member of struct typeT2
provided m is part of the common initial sequence ofT1
andT2
; the behavior is as if the corresponding member ofT1
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With