I have just hit a confusing problem when trying to compile some code using g++ 4.4.3.
The code below compiles fine, but instead of hitting the expected assert when I pass an ‘invalid’ enum value, the function just returns 1. What I find even stranger is that when I uncomment the lines pertaining to the E3 enum value, things start working as expected.
The fact that there is no default entry in the switch block is by design. We compile with the -Wall option to get warnings of unhandled enum values.
enum MyEnum
{
E1,
E2,
//E3
};
int doSomethingWithEnum(MyEnum myEnum)
{
switch (myEnum)
{
case E1: return 1;
case E2: return 2;
//case E3: return 3;
}
assert(!"Should never get here");
return -1;
}
int main(int argc, char **argv)
{
// Should trigger assert, but actually returns 1
int retVal = doSomethingWithEnum(static_cast<MyEnum>(4));
std::cout << "RetVal=" << retVal << std::endl;
return 0;
}
Your switch statement will be compiled into this (g++ 4.4.5):
As can be seen, the assert is optimized away completely, and the compiler elects to compare against E2 and return 1 in all other cases. With three enum values it can’t do that.
Section 5.2.9 of the C++98 standard (static cast) gives the reason for allowing this:
In other words, the compiler is free to use whatever enum value it wants, (in this case E1) if you try to use an illegal value. This includes doing the intuitive thing and using the supplied illegal value or using different values depending on the circumstances, which is why the behavior changes depending on the number of enum values.