Deepan
Deepan

Reputation: 26

Checking enum validity

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

Answers (3)

jamesdlin
jamesdlin

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

Steve Jessop
Steve Jessop

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

Aesthete
Aesthete

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

Related Questions