You mentioned that. Why exactly are you changing it?
Red Alert uses bitfields to pack all boolean values, this is a optimisation that the Watcom compiler did at the time, and something that is not longer done (as we don't have the constraints they at the time).
Second, is that the enumerations where packed depending on the size of the largest entry, so where UNIT_NONE would equal "-1" 32bit integer in our codebase, Red Alert stores this is a "-1" 8bit char. This causes more headaches that you would think. The same goes for some structures too, but this was intentional and no longer applies to us.
template<unsigned _Count, typename _Type>
struct BitFlags
{
enum
{
BitsInSpan = 8,
NumSpans = (((_Count + (BitsInSpan - 1)) / BitsInSpan))
};
char m_Value[NumSpans];
};
An enum data type can be similar. This would make it easy to access and work with enums and bitflags of variable length.
For example:
enum EMyType
{
MYTYPE_NONE = -1,
MYTYPE_0,
MYTYPE_1,
MYTYPE_2,
MYTYPE_3,
MYTYPE_4
};
typedef BitFlags<5, EMyType> MyTypeBitFlags;
Would result in a 8 bit representation of EMyType. And get the flag with something like
void SetFlag(EMyType value)
{
if (value == MYTYPE_NONE) // -1
{
return; // or something else you want -1 to do
}
m_Value[value / BitsInSpan] |= (1 << value % BitsInSpan)
}
void RemoveFlag(EMyType value)
{
if (value == MYTYPE_NONE) // -1
{
return;
}
m_Value[value / BitsInSpan] &= ~(1 << value % BitsInSpan)
}
bool HasFlag(EMyType value)
{
if (value == MYTYPE_NONE)
{
return false;
}
return m_Value[value / BitsInSpan] & (1 << value % BitsInSpan)
}
Pretty much no effort involved in having variable size bit fields.