How can I overload the |=
operator on a strongly typed (scoped) enum
(in C++11, GCC)?
I want to test, set and clear bits on strongly typed enums. Why strongly typed? Because my books say it is good practice. But this means I have to static_cast<int>
everywhere. To prevent this, I overload the |
and &
operators, but I can't figure out how to overload the |=
operator on an enum. For a class you'd simply put the operator definition in the class, but for enums that doesn't seem to work syntactically.
This is what I have so far:
enum class NumericType
{
None = 0,
PadWithZero = 0x01,
NegativeSign = 0x02,
PositiveSign = 0x04,
SpacePrefix = 0x08
};
inline NumericType operator |(NumericType a, NumericType b)
{
return static_cast<NumericType>(static_cast<int>(a) | static_cast<int>(b));
}
inline NumericType operator &(NumericType a, NumericType b)
{
return static_cast<NumericType>(static_cast<int>(a) & static_cast<int>(b));
}
The reason I do this: this is the way it works in strongly-typed C#: an enum there is just a struct with a field of its underlying type, and a bunch of constants defined on it. But it can have any integer value that fits in the enum's hidden field.
And it seems that C++ enums work in the exact same way. In both languages casts are required to go from enum to int or vice versa. However, in C# the bitwise operators are overloaded by default, and in C++ they aren't.
Then your books are not talking about your use case. Unscoped enumerations are fine for flag types.
This works? Compile and run: (Ideone)
print 3.
This seems to work for me:
However, you may still consider defining a class for your collection of
enum
bits:Then, change your
|
and&
operators to returnNumericTypeFlags
instead.By combining distinct values to make new, undefined values, you are totally contradicting the strong-typing paradigm.
It looks like you are setting individual flag bits that are completely independent. In this case, it does not make sense to combine your bits into a datatype where such a combination yields an undefined value.
You should decide on the size of your flag data (
char
,short
,long
,long long
) and roll with it. You can, however, use specific types to test, set and clear flags:This is very basic, and is fine when each flag is only a single bit. For masked flags, it's a bit more complex. There are ways to encapsulate bit flags into a strongly-typed class, but it really has to be worth it. In your case, I'm not convinced that it is.