无论您添加任何语法糖,掩蔽和转换都会发生。如果您想让事情变得真正易于使用,但首先要制作起来有点困难,您可以使用一个类,以及一些宏/模板代码,以便更容易定义新类:
template<bool> struct CompileTimeAssert;
template<> struct CompileTimeAssert<true> { };
#define ASSERT(check) if (!check) throw exception("Assertion Failure" #check)
#define ADDBITVALUE(backingField, backingFieldType, fieldName, offset, size) \
public: \
static const unsigned int fieldName##Offset = offset; \
static const backingFieldType fieldName##Mask = CalculateMask<offset, size, backingFieldType>::Value; \
public: \
void Set##fieldName(backingFieldType value) \
{\
ASSERT(("Value too large for field.", (value & (fieldName##Mask >> fieldName##Offset)) == value));\
backingField |= value << fieldName##Offset;\
}\
backingFieldType Get##fieldName() const\
{\
return (backingField & fieldName##Mask) >> fieldName##Offset;\
}\
private:
#define ADDSPANNEDVALUE(backingField1, backingField1Type, backingField2, backingField2Type, fieldName, offset1, size1, offset2, size2)\
ADDBITVALUE(backingField1, backingField1Type, fieldName##internal1, offset1, size1)\
ADDBITVALUE(backingField2, backingField2Type, fieldName##internal2, offset2, size2)\
public: \
void Set##fieldName(backingField1Type value) \
{\
backingField1Type value1 = value << (sizeof(backingField1Type)*8-size1);\
value1 = value1 >> (sizeof(backingField1Type)*8-size1);\
Set##fieldName##internal1(value1);\
Set##fieldName##internal2(value >> size1);\
}\
backingField1Type Get##fieldName() const\
{\
return Get##fieldName##internal1() | (Get##fieldName##internal2() << size1);\
}\
private:
template <unsigned int Offset, int Size, typename T>
struct CalculateMask
{
CompileTimeAssert<(Size > 0)> Object;
static const T Value = (T)((1 << Offset) | CalculateMask<Offset + 1, Size - 1, T>::Value);
};
template <unsigned int Offset, typename T>
struct CalculateMask<Offset, 0, T>
{
CompileTimeAssert<(Offset <= sizeof(T) * 8)> Object;
static const T Value = 0;
};
然后像这样定义你的类:
class BitGroup
{
unsigned short Values;
unsigned short Values2;
ADDBITVALUE(Values, unsigned short, Field1, 0, 12);
ADDSPANNEDVALUE(Values, unsigned short, Values2, unsigned short, Field2, 12, 4, 0, 2);
ADDBITVALUE(Values2, unsigned short, Field3, 2, 14);
public:
BitGroup() : Values(0), Values2(0) {}
};
用法:
BitGroup bg;
bg.SetField1(15);
cout << bg.GetField1();
bg.SetField2(63);
cout << bg.GetField1();
如果您的字段超出支持字段的范围,您将获得编译时断言。没有检查字段是否重叠,因此您必须注意这一点。