简体   繁体   中英

C++ bit fields (passing it in effectively, aka. syntactic sugar)

I've run into a problem that I feel to be solving inefficiently. I have a bunch of flags (below FLAG_1 and FLAG_2). I want to reset one of them and pass the result into a function. Without a bit field, I could simply write:

BYTE flags=FLAG_1 | FLAG_2; // both flags set
func(flags & ~FLAG_2); // preserve Flags in the current scope and pass in "Flags minus FLAG_2"

Nice syntax in this situation but cumbersome when working with Flags elsewhere (eg in IFs).

Using a bit field the same code becomes more verbose:

struct TBitField{
    unsigned flag1:1;
    unsigned flag2:1;
};
TBitField bf={ true, true }; // both flags set
TBitField tmp=bf;
tmp.flag2=false;
func(tmp);

Ugly approach in this situation but handy when working with the bit field elsewhere.

Hence, is there a compromise to modify the bit field and pass it over in just one line?

TBitField bf={ true, true }; // both flags set
func( bf - FLAG_2 ); // my idealized pseudo-syntax...

Thanks in advance.

You are allowed to define methods in your bitfield - it's pretty much a normal struct , which is a class . You could for example add methods to clear and set bits:

struct TBitField {
      unsigned flag1:1;
      unsigned flag2:1;

      TBitField clr2() {
           TBitField tmp = *this;
           tmp.flag2 = false;
           return tmp;
      }
 };

Then you use it as for example:

 func( bf.clr2() );

There are several options I can think of, to implement this "syntactical sugar", as you call it. I'll give a brief outline of one such possible solution. It's not the only one.

Given your definition of a struct TBitField , define another class. An enum class will work well

 enum class bits {bit_0, bit_1, bit_2 ... }; // And so on.

Now, overload the + and - operators. Something like this:

TBitField operator+(const TBitField &a, bits bit_number)
{
    // ...
}

and

TBitField operator-(const TBitField &a, bits bit_number)
{
    // ...
}

Now, you can use your desired syntax:

func( bf - bits::bit_2 );

And this will invoke the corresponding operator . The implementation of the two operators should be obvious, and not necessary to spell out, here.

You may even choose to forego a helper class, and simply define:

TBitField operator+(const TBitField &a, int bit_number)
{
    // ...
}

TBitField operator-(const TBitField &a, int bit_number)
{
    // ...
}

And then simply use:

func( bf - 2 );

Although that looks slightly confusing, that's why I think that using an explicit helper class is better.

Either approach will likely introduce a little bit of compiler bloat. To remedy this, with most compilers I'd suggest defining both operators as inline , and also define overloaded versions that take an rvalue reference as a parameter.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM