1

我有一些包含位域的结构,其大小可能会有所不同。例子:

struct BitfieldSmallBase {
    uint8_t a:2;
    uint8_t b:3;
    ....
}

struct BitfieldLargeBase {
    uint8_t a:4;
    uint8_t b:5;
    ....
}

以及一次访问所有位的联合:

template<typename T>
union Bitfield 
{
    T bits;
    uint8_t all;    // <-------------  Here is the problem

    bool operator & (Bitfield<T> x) const {
        return !!(all & x.all);
    }
    Bitfield<T> operator + (Bitfield<T> x) const {
        Bitfield<T> temp;
        temp.all = all + x.all;   //works, because I can assume no overflow will happen
        return temp;
    }
    ....
}

typedef Bitfield<BitfieldSmallBase> BitfieldSmall;
typedef Bitfield<BitfieldLargeBase> BitfieldLarge;

问题是:对于某些位域基类,一个 uint8_t 是不够的。BitfieldSmall 确实适合 uint8_t,但 BitfieldLarge 不适合。数据需要尽可能紧密地打包(稍后将由 SSE 指令处理),因此始终使用 uint16_t 是没有问题的。有没有办法用整数类型声明“全部”字段,其大小与位域相同?或者另一种访问整体位的方法?

我当然可以放弃使用模板并明确声明每种位域,但我想避免代码重复(有很多运算符和成员函数)。

4

6 回答 6

5

您也可以将整数类型设为模板参数。

template<typename T, typename U>
union Bitfield 
{
    T bits;
    U all;
}

typedef Bitfield<BitfieldSmallBase, uint8_t>  BitfieldSmall;
typedef Bitfield<BitfieldLargeBase, uint16_t> BitfieldLarge;
于 2009-10-01T12:04:04.263 回答
1

我已经了解到,虽然您使用的 vars 上的位宽是让编译器为您进行屏蔽和移位的一种方便方法,但您不能对成员的顺序和填充做出假设结构。它的编译器依赖并且编译器确实改变了顺序,并且依赖于项目中的其他代码。

如果您想将一个字节视为离散字段,您真的必须以艰难的方式去做。

于 2009-10-01T12:08:12.523 回答
1

您可以使用模板元编程来定义一个模板函数,该函数从 BitfieldSmallBase、BitfieldLargeBase 等映射到另一种类型 - 默认情况下为 uint8_t,并将 BitfieldLargeBase 的 uint16_t 作为模板特化,然后像这样使用它:

union Bitfield 
{
    T bits;
    typename F<T>::holder_type all;
};
于 2009-10-01T12:08:45.490 回答
1

您可能需要考虑std::bitsetboost::dynamic_bitset而不是自己滚动。在任何情况下,避开std::vector<bool>

于 2009-10-01T12:09:20.840 回答
0

将您需要的字节数作为模板参数的一部分:

template <typename T, int S=1>
struct BitField 
{
   union
   {
      T bits;
      unsigned char bytes[S];
   };
};

typedef Bitfield<BitfieldSmallBase, 1>  BitfieldSmall;
typedef Bitfield<BitfieldLargeBase, 2> BitfieldLarge;
于 2009-10-01T21:31:50.380 回答
0

这个怎么样?

#include <limits.h>

template <class T>
union BitField
{
    T bits;
    unsigned all : sizeof(T) * CHAR_BIT;
};
于 2009-10-01T21:36:08.193 回答