Consider the following code:
//Note that the enum is nonsequential. I don't have control of
//this enum so I cannot change it to be sequential
enum class Animal {
DOG = 0,
CAT = 1,
LLAMA = 20,
ALPACA = 21,
};
//This data is received as an int,
//but I want to know what Animal it refers to
int data_0 = 0;
int data_2 = 2;
My application will receive some data, and I want to know which Animal it refers to.
Animal foo = static_cast<Animal>(data_0); //Great, it's an Animal::DOG.
Animal bar = static_cast<Animal>(data_2); //Whoops! This will crash.
if (foo == Animal::DOG) { //This is an easy comparison
//do something
}
Clearly, I need to be doing some validation on the incoming data or I risk a crash.
To me, it seems like the solution is to do explicit validation when casting an enum, but I don't know enough about C++ to know a clean way to do this:
//This is not sufficient to validate the value
if (data_2 > Animal::DOG && data_2 < Animal::ALPACA) {
Animal bar = static_cast<Animal>(data_2); //Whoops! This will crash.
}
//This is sufficient to validate the value, but is very ugly
Animal bar;
if (data_2 == static_cast<int>(Animal::DOG) ||
data_2 == static_cast<int>(Animal::CAT) ||
data_2 == static_cast<int>(Animal::LLAMA) ||
data_2 == static_cast<int>(Animal::ALPACA)) {
bar = static_cast<Animal>(data_2); //This does not run because of the checking
}
//bar was not assigned, so it would be NULL or 0
if (bar == Animal::DOG) {
//oh no, we shouldn't be here!
}
There has to be a better way to do this, so I feel like I'm missing something. How could I designthis be done such that an int can be cast to an Animal, but Animal cannot end up being an invalid value when the casting fails?