The following code is the classical, infamous type-punning union. Similar code is legal in C99/C11 but illegal in C++, because one has to read from the inactive member.
To activate the inactive member one has to write to it (that is not appropriate here) or to construct it via placement-new.
The code below does exactly this: it initializes member a
and then activates member b
by placement-new. In case of an array of primitive types, the construction is actually a noop, and the bitvalues remain the same.
I never saw this solution in the numerous other questions / answers to this topix, so I wonder if the code below in fact circumvents UB really.
#include <cstdint>
#include <cstddef>
#include <utility>
#include <array>
#include <tuple>
#include <cassert>
union ByteUnion32 {
public:
explicit ByteUnion32(uint32_t v) : a{v}{
new (&b) std::byte[sizeof(uint32_t)]; // set b active, but prevents constexpr, actually a noop
}
std::byte operator[](uint8_t i) const {
return b[i];
}
private:
uint32_t a;
std::byte b[sizeof(uint32_t)];
};
int main(){
ByteUnion32 u10{0x01020304}; // initialise and activate byte-memebers
auto v10 = std::to_integer<uint8_t>(u10[0]);
assert(v10 == 4);
}