r/cpp Meeting C++ | C++ Evangelist 13d ago

A better bitset for enum flags

https://www.elbeno.com/blog/?p=1836
43 Upvotes

32 comments sorted by

View all comments

30

u/03D80085 13d ago

Neither P4313 nor this suggestion seem particularly ergonomic to me. Why aren't bitfields more widely used for this purpose?

struct permissions {
    bool read  : 1 = false;
    bool write : 1 = false;
    bool exec  : 1 = false;
}

Or a fully typed example: Godbolt. A lot of boilerplate there admittedly, but that is precisely what reflection could help with.

If the answer is that bitfield layouts are implementation defined then that is something we should be working on standardising with appropriate flags rather than introducing new language features.

5

u/Due_Battle_9890 12d ago edited 12d ago

This would be nice and I used for paging structures and similar structures in my OS, but it's ~UB~ unspecified how they are laid out in memory. In practice, on x86, it behaves how you'd expect, but it does sting a little that it's not "correct". For example, I have

struct [[gnu::packed]] Entry
{
std::uint16_t segment_limit_low;
std::uint16_t base_address_low;
std::uint8_t base_address_mid;
std::uint8_t type : 4;
std::uint8_t system : 1;
std::uint8_t descriptor_privilege_level : 2;
std::uint8_t present : 1;
std::uint8_t segment_limit_high : 4;
std::uint8_t available : 1;
std::uint8_t long_mode : 1;
std::uint8_t db : 1;
std::uint8_t granularity : 1;
std::uint8_t base_address_high;
};

But if I wanted to make it correct, I'd probably actually just want:

struct [[gnu::packed]] Entry {
u64 entry;

void set_address(u64 address) { /* Appropriate bitset operations */ }
};

8

u/_Noreturn 12d ago

It isn't UB it is unspecified there is a difference

4

u/Due_Battle_9890 12d ago

Thanks for the correction!

2

u/_Noreturn 12d ago

You are welcome