What is your procedure when switching over an enum where every enumeration is covered by a case? Ideally you\'d like the code to be future proof, how do you do that?
<I throw an exception. As sure as eggs are eggs, someone will pass an integer with a bad value rather than an enum value into your switch, and it's best to fail noisily but give the program the possibility of fielding the error, which assert() does not.
I tend to do option 2:
add a default case that throws a catchable exception
That should highlight the problem if it ever occurs and it only costs you a couple of lines to imlpement.
My $0.02:
If this method is externally visible (called by code that you don't control), then you probably need to handle the possibility of someone sending you an invalid enum value. In that case, throw an exception.
If this method is internal to your code (only you call it), then the assertion should be all that is necessary. This will catch the case of someday adding a new enum value and forgetting to update your switch statement.
Always provide a default case in every switch, and at the very least, assert if it gets hit. This habit will pay off by saving you hours or even days of head scratching every once in a while.
I am not a C++ guy. But, in C#, I whould have written it like
enum Enum
{
Enum_One,
Enum_Two
};
Special make_special( Enum e )
{
if(Enums.IsDefined(typeof(Enum),(int)e))
{
switch( e )
{
case Enum_One:
return Special( /*stuff one*/ );
case Enum_Two:
return Special( /*stuff two*/ );
}
}
// your own exception can come here.
throw new ArgumentOutOfRangeException("Emum Value out of range");
}
In cases similar to the example provided you can actually combine option 1 with one of the other options: Omit the default and enable the appropriate compiler warning if available. This way you find out immediately if a new enumerated value is added and you can conveniently add the case without having to guarantee that a specific code path executes to find it at runtime.
Then between the end of the switch and the end of the function add code to assert or throw (I prefer assert as this really is an invalid situation). This way if someone casts an int to your enum type you still get the runtime checking as well.
I personally recommend any of your solutions, except the first. Leave in the default case, and assert, throw (whatever exception type you like). In C#, Visual Studio doesn't warn you if you leave out the default case.
The reason I suggest you add the case and fail on it is that this is an important point of code maintenance. As soon as someone adds to the enumerated list, the switch statement has to grow to match.
Also (as UncleBen said), see if you can design against this whole scenario by using polymorphism. That way, when you add a new value to the enumeration, you only have to add it in one place. Any time you see a switch on an enum, you should consider using polymorphism instead.