代码之家  ›  专栏  ›  技术社区  ›  Gunther Piez

具有别名的可变大小位字段

  •  1
  • Gunther Piez  · 技术社区  · 15 年前

    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\u t是不够的。BitfieldSmall不适合uint8,但BitfieldLarge不适合。数据需要尽可能紧密地打包(稍后将由SSE指令处理),因此始终使用uint16_t是不可能的。有没有办法用整型来声明“all”字段,整型字段的大小与位字段相同?还是以另一种方式访问位作为一个整体?

    当然,我可以放弃使用模板,显式声明每种类型的位字段,但我希望避免代码重复(有很多运算符和成员函数)。

    6 回复  |  直到 15 年前
        1
  •  5
  •   John Kugelman    15 年前

    也可以将整型作为模板参数。

    template<typename T, typename U>
    union Bitfield 
    {
        T bits;
        U all;
    }
    
    typedef Bitfield<BitfieldSmallBase, uint8_t>  BitfieldSmall;
    typedef Bitfield<BitfieldLargeBase, uint16_t> BitfieldLarge;
    
        2
  •  1
  •   Will    15 年前

    我了解到,虽然您正在使用的变量上的位宽度是让编译器为您进行掩蔽和移位的一种方便方法,但是 不能

        3
  •  1
  •   catwalk    15 年前

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

    union Bitfield 
    {
        T bits;
        typename F<T>::holder_type all;
    };
    
        4
  •  1
  •   D.Shawley    15 年前

    std::bitset boost::dynamic_bitset 而不是自己滚。无论如何, 避开 std::vector<bool> !

        5
  •  0
  •   Matt Matt    15 年前

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

    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;
    
        6
  •  0
  •   Pavel Minaev    15 年前

    这个怎么样?

    #include <limits.h>
    
    template <class T>
    union BitField
    {
        T bits;
        unsigned all : sizeof(T) * CHAR_BIT;
    };