I observed some behavior relating to enum structs and compound operators that I don't understand (yet). When using an enum struct as a flag, I'd like to write stuff like flag &= enum_name::What
. However, depending on the compilation this either works or does not.
Here's the code I used for testing:
#include <iostream>
#include <type_traits>
enum struct A : unsigned
{
Zero = 0x01,
One = 0x02,
Two = 0x04,
};
A operator&(A a, A b)
{
typedef std::underlying_type<A>::type uchar;
return A(uchar(a) & uchar(b));
}
A& operator&=(A &a, const A b)
{
return a = A(std::underlying_type<A>::type(a) & std::underlying_type<A>::type(b));
}
std::ostream& operator<<(std::ostream &stream, const A a)
{
switch (a) {
case A::Zero:
stream << "Zero";
break;
case A::One:
stream << "One";
break;
case A::Two:
stream << "Two";
break;
default:
stream << "Unknown";
}
return stream;
}
bool test(A a)
{
return std::underlying_type<A>::type(a);
}
int main()
{
A flag;
flag &= A::One;
if (test(flag & A::One)) {
std::cout << "flag is A::One\n";
}
else {
std::cout << "flag is " << flag << "\n";
}
return 0;
}
Regardless of the compiler (clang 14.0.6 or g++ 12.2.0), the above code emits either "flag is A::One" or "flag is Unknown" every third or fourth compilation. It also does not matter if the values start at 0x00
instead of 0x01
.
Is the reason for this behavior because A flag
is not initialized on line 47? And if this is the case, is there any way to define how enum structs are "default initialized"?