Reputation: 26
I have a class that exposes an enum. I am trying to check the validity of the values in the setter function, like so:
enum abc
{
X,
Y
};
int my_class::set_abc(abc value)
{
if(static_cast<int>(value) > static_cast<int>(Y))
return -1;
...
}
There is a similar check for value being less than X.
I see that the compiler removes the check completely. I have Googled for the reason and come across many pages explaining the rules for integer conversions in C++, but I wouldn't find any clarifications about converting enums to ints, or checking the validity.
What is the correct way to accomplish this?
Upvotes: 1
Views: 236
Reputation: 89975
In C++, you can't directly assign integers to enum
variables without an explicit cast.
If your code uses the enum
type everywhere, then there's no point to checking that's valid. It should be valid from the start and should remain valid.
If, however, your code gets the value as an integer and you need to convert it to an enum
(or you perhaps do some arithmetic operation on an enum
value), then you should validate the value at that site.
Upvotes: 0
Reputation: 279255
Since 0
and 1
are the only valid values of the type abc
, whoever passes in a value larger or smaller than that has already invoked undefined behavior in order to create it.
You can't easily write code in C++ to detect conditions that have previously caused UB -- as you observe, the compiler has a tendency to optimize based on what is permitted or forbidden by the language.
You could write an int
overload of the function that checks the value and then converts to the enum type, and not bother checking in the abc
overload since it's someone else's problem to avoid invoking UB.
Alternatively, you could avoid your test being redundant, by putting some arbitrary additional values in the enum. Then the compiler can't remove it.
Upvotes: 1
Reputation: 18848
It seems arbitrary to test against Y
, so I would add some limits. This also allows you to add more elements between min and max, and not be concerned with the ordering.
enum abc
{
ABC_MIN = 0,
X,
Y,
ABC_MAX
};
int my_class::set_abc(abc value)
{
assert(value > ABC_MIN && value < ABC_MAX);
{
Upvotes: 2