Wow... I thought I had seen a lot of strange C++ code but I have _never_ seen packed structs using this syntax:
struct X {
type alias : numeric_value = false;
...
}
I love the power of C++ but there is _so much_ to the language. I'm sure there would also be some template meta programming solution even if this syntax was available.
The only real problem with C (and C++) bitfields is that the standard doesn’t say anything about how they’re laid out in memory, which unfortunately makes them mostly useless unless you either don’t care about layout or you’re targeting one specific compiler and that compiler documents its choices and doesn’t break them in a few years.
Sign-extension of 1-bit fields also messes people up all the time, but that’s “just” an easy-to-fix bug.
That is a really big problem in some applications. I wish the C committee would come out and say "use the layout that GCC 11
.x.x does" to make these a lot more usable.
The rough C equivalent looks like https://godbolt.org/z/YqGPa7ecd , using _Static_assert ( available C11 on wards and as a GCC built-in from 4.6 ) with no default values for the struct members
It's probably tough to find a metaprogramming solution to this, for two reasons:
1. Addressing happens at the byte level, not the bit level, so a type can't begin on any bit. You'd have to do your own addressing, such as in std::bitset.
2. For now, there's no reflection in the language, so you can't really assign names to members in a general way (hello, preprocessor). A solution might be to index by type; something like the following:
I have done similar things a few times, and like JSON handling, the optimal API does not seem to be the same for every intended use. Size-focused cases want different things than speed-focused ones, and you need to deal with sign extension, etc.
Yup, I'd be very wary of all the template instantiation going on here. Sadly, I often find codegen is the most reasonable solution in a given situation. I wish we had a decent macro system, like Rust's
I thought you were not able to initialize bitfield members like that in struct. Am I misremembering, was that something else or is it compiler/c++ release dependent?
You can absolutely initialize bitfield members in structs, not sure where your memory is from… maybe it was broken on some specific compiler vendors/versions?
This has been possible since C89. See 3.5.2.1 of the C89 rationale [0].
It is architecture/compiler dependent though. This is explicitly acknowledged in the rationale document:
“Since some existing implementations, in the interest of enhanced access time, leave internal holes larger than absolutely necessary, it is not clear that a portable deterministic method can be given for traversing a structure field by field.”
I think they were referring to the default member initializer, a feature added in C++11 not exclusive to bitfields. I couldn't see any reference to anything similar in what you linked (admittedly, I skimmed though).
For example:
struct X {
int defaulted = 1; // 1 is the default member initializer
};
>I think they were referring to the default member initializer
Ah, that would make more sense. The combination of bitfield and default initializer syntax does look especially odd, since both features are rarely used IME.
>I couldn't see any reference to anything similar in what you linked
Indeed, there is no way to specify default values for a C struct at definition time.