Does bitfield count as common initial sequence with a whole int of the same type?

Viewed 69

I was wondering if the following was valid C++:

union id {
    struct {
        std::uint32_t generation : 8;
        std::uint32_t index : 24;
    };
    std::uint32_t value;
};

I want this so I can access both generation and index separately, which keeping access to the whole number. Since they all are std::uint32_t, this shouldn't be UB right?

I plan to use it like that:

auto my_id = id{
    .generation = 1,
    .index = 4,
};

auto my_id_value = std::uint32_t{id.value};

If it is UB, is there another way to make this work and valid according to the C++ standard?

1 Answers

By resolution of CWG 645 (for C++11; not sure whether it is supposed to apply to C++98 as DR) the common initial sequence requires corresponding non-static data members or bit-fields in the two classes (by declaration order) to either be both bit-fields (of the same width) or neither be bit-fields.

The wording for that can still be found in [class.mem.general]/23 in the current draft, including an example stating clearly that a bit-field of the same type as a non-static data member will not be part of the common initial sequence.

Therefore the exceptional rule in [class.mem.general]25 allowing access to inactive members in the common initial sequence of standard-layout class members in a union doesn't apply in your case and reading id.value in auto my_id_value = std::uint32_t{id.value}; has undefined behavior.

Related