22-08-2024, 06:03 PM
Rule 9.4.2 requires that all switch blocks have a "default" case, for defensive programming.
This is however not required when using C-style enums, i.e. unscoped and without underlying type. Presumably because it's Undefined Behavior to cast an int out-of-range to a C-style enum, whereas it's well-defined behavior for "C++ enums". Since UB is assumed to not happen, one can assume that a C-style enum has a valid value.
However, there's a subtlety. The "range" of a C-style enum is not just the list of valid enumerators, but the smallest bitset that contains all enumerators.
So for example:
The following code is **not** Undefined Behavior, because the valid range of this enum is 0-7 (2^3 - 1).
So I'd argue that defensive programming still applies here and a "default" case would still be needed.
What do you think?
This is however not required when using C-style enums, i.e. unscoped and without underlying type. Presumably because it's Undefined Behavior to cast an int out-of-range to a C-style enum, whereas it's well-defined behavior for "C++ enums". Since UB is assumed to not happen, one can assume that a C-style enum has a valid value.
However, there's a subtlety. The "range" of a C-style enum is not just the list of valid enumerators, but the smallest bitset that contains all enumerators.
So for example:
Code:
enum Foo
{
a = 0,
b = 1,
c = 2,
d = 3
};
The following code is **not** Undefined Behavior, because the valid range of this enum is 0-7 (2^3 - 1).
Code:
enum Foo x = static_cast<Foo>(7);
So I'd argue that defensive programming still applies here and a "default" case would still be needed.
What do you think?