如何干净地验证并转换为无关紧要的枚举?

时间:2018-03-08 22:52:53

标签: c++ enums casting

请考虑以下代码:

//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;

我的应用程序将收到一些数据,我想知道它引用的是哪种动物。

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
}

显然,我需要对传入的数据进行一些验证,否则我会冒着崩溃的风险。

对我而言,似乎解决方案是在演示枚举时进行显式验证,但我不太了解C ++以了解干净的方法:

//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!
}

必须有更好的方法来做到这一点,所以我觉得我错过了一些东西。我怎么能设计这样做,以便可以将一个int强制转换为Animal,但是当转换失败时,Animal不会最终成为无效值?

2 个答案:

答案 0 :(得分:0)

如果执行验证的代码不在代码库的性能关键部分的路径中,则可以使用执行必要验证的函数。

std::pair<bool, Animal> getAnimal(int data)
{
   switch (data)
   {
      case Animal::DOG
        return {true, Animal::DOG};

      ...

      default:
   }

   return {false, ANIMAL::DOG};
}

并将其用作:

auto res = getAnimal(data);
if ( res.first )
{
   // Valid data.
   // Use res.second.
}
else
{
   // Deal with invalid data.
}

答案 1 :(得分:0)

使用包含枚举值和名称的表:

+--------+----------+  
| DOG    | "DOG"    |  
+--------+----------+  
| CAT    | "CAT"    |  
+--------+----------+  
| LLAMA  | "llama"  |  
+--------+----------+  
| ALPACA | "alpaca" |  
+--------+----------+  

在表格中搜索ID。如果ID存在,您可以获取关联的名称。您还可以按名称搜索以查找ID。

如果要将ID与名称或名称与ID相关联,则可以使用std::map