추가하는 구문 설탕에 관계없이 마스킹 및 이동이 발생합니다. 일을 사용하기가 쉽지만 처음부터 좀 더 어렵게 만들려면 매크로/템플릿 코드 약간을 사용하여 클래스를 사용하여 새로운 클래스를 정의하는 것이 조금 더 쉽습니다.
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();
당신의 필드 등판이 필드의 범위를 벗어나는 경우는 컴파일 시간이 주장 얻을 것이다. 필드가 겹치지 않는지 확인하지 않으므로이를주의해야합니다.
비트 필드를 사용하는 것이 유혹적이지만 이식 할 수없는 경우가 많으며 이는 종종 거래가 될 수 있습니다. –
브라이언이 말했듯이, 휴대용이 아니며 제 OS와 작동하지 않습니다. –