C ++位字段(有效传递它,又称。句法糖)

时间:2015-10-16 12:27:48

标签: c++ flags bit-fields

我遇到了一个我认为无法有效解决问题的问题。我有一堆标志(FLAG_1和FLAG_2下面)。我想重置其中一个并将结果传递给一个函数。如果没有位字段,我可以简单地写一下:

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"

在这种情况下语法很好但在其他地方使用Flags时很麻烦(例如在IF中)。

使用位字段,相同的代码变得更加冗长:

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

在这种情况下采用丑陋的方法,但在其他地方使用位字段时很方便。

因此,是否存在修改位域并在一行中传递它的折衷方案?

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

提前致谢。

2 个答案:

答案 0 :(得分:2)

您可以在比特字段中定义方法 - 它几乎是正常struct,即class。例如,您可以添加清除和设置位的方法:

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

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

然后你用它作为例如:

 func( bf.clr2() );

答案 1 :(得分:1)

我可以想到几个选项,实现这个"语法糖",就像你所说的那样。我将简要介绍一种可能的解决方案。它不是唯一的一个。

鉴于您对struct TBitField的定义,请定义另一个类。枚举类很好用

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

现在,重载+和 - 运算符。像这样:

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

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

现在,您可以使用所需的语法:

func( bf - bits::bit_2 );

这将调用相应的operator。这两个运算符的实现应该是显而易见的,而且没有必要在这里详细说明。

您甚至可以选择放弃帮助类,只需定义:

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

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

然后简单地使用:

func( bf - 2 );

虽然这看起来有些令人困惑,但这就是为什么我认为使用显式助手类更好。

这两种方法都可能引入一点编译器膨胀。为了解决这个问题,对于大多数编译器,我建议将两个运算符定义为inline,并定义将右值引用作为参数的重载版本。