Why do bitfields throw exceptions instead of wrapping?

James Miller james at aatch.net
Wed Feb 29 21:12:53 PST 2012


On 1 March 2012 16:15, ixid <nuaccount at gmail.com> wrote:
> In C++ this works:
>
> struct test
> {
>        unsigned int h : 2;
> };
>
> int main()
> {
>        test b;
>        b.h = 0;
>        for(int i = 0;i < 10;i++)
>                ++b.h;
>        return 0;
> }
>
> In D this throws an exception as soon as it wraps:
>
> struct test
> {
>        mixin(bitfields!(
>                                         uint, "h", 2,
>                                         uint, "", 30));
> };
>
> int main()
> {
>        test b;
>        b.h = 0;
>        for(int i = 0;i < 10;i++)
>                b.h = b.h + 1;
>        return 0;
> }
>
> Is there any way to make it work directly like the C++ example without doing
> something like
> if(bitfield is at max)
>    wrap it by hand;
>
> It also seems odd to leave out the various shortcut operators like ++, *=
> etc fr bitfields.

Looking through the bitmanip code, what happens is that the mixin
creates properties, including the setters and getters for those
properties, in the struct.

Due to the way @properties work, b.h is an rvalue, this is because b.h
-> b.h(), the @property declaration just makes it so you can omit the
parenthesis. Thinking of it like this, you wouldn't try
this.getInt()++ would you?

Some experimentation shows that a ref getter allows for this kind of
modification, however, it is difficult to have both ref T and T
getters, due to the compiler not being able to choose which is which
when resolving the calls in most cases. Unfortunately it would be
unwise to just change the getter to a ref type, since that would mean
that any changes to it after retrieval would affect the original.

It is difficult to create a bit field that allows for all of the
features described, but still prevents stupid code from prevailing.
e.g. a 2-bit uint a: a = 4, if it wrapped rather than errored, then
that could cause all sorts of errors down the line, and would be
incredibly hard to diagnose.

If you want wrapping however, during the increment you can do this:

b.h = (b.h + 1) % b.h_max;

since all fields define a *_max field. Not as elegant as doing it
internally, but better than using a condition.

Bitfields are for tightly packed data, and therefore expecting all
language features to be available is missing the point. Hell bitfields
are provided by templates, so they aren't even a part of the language,
they are just a library feature.

Hope that helps

--
James Miller


More information about the Digitalmars-d-learn mailing list