【问题标题】:enum as argument returning string枚举作为参数返回字符串
【发布时间】:2012-02-02 11:39:24
【问题描述】:

我当前的程序使用 3 个不同的枚举:

enum ThingEnum{
    Thing1 = 0,
    Thing2 = 1,
    Thing3 = 2,
    OtherThing = 3
};
enum ReturnEnum {
    Success = 4,// the method did what it is supposed to
    Error1 = 5,// an error occured
    Error2 = 6,// an error occured
    Error3 = 7,// an error occured
    Error4 = 8,// a fatal error occured program must terminate
    Pointer = 9// the method may need to be called again
};
enum TypeEnum {
    Type1 = 10,
    Type2 = 11,
    Type3 = 12,
    Type4 = 13,
    OtherType = 14
};  

我想要做的是创建一个全局函数,它接受一个枚举并返回一个字符串(因为枚举的值实际上只是一个始终具有值的专用变量名)。 是否可以创建一个采用通用枚举的函数? 例如

string enumToString (enum _enum){}

或者我必须为每个不同的枚举创建一个函数吗?只是一个可能的想法,我做了一些阅读,一些编译器允许 Enum 解析为 int,所以我可以将 enum 作为 int 传递然后使用它吗?

【问题讨论】:

  • 那么您想要做的是将枚举值转换为字符串吗?也许您应该修改问题标题...
  • as the value of an enum is really just a specialized variable name that always has a valuewhut
  • @Lightness 当编译器读取枚举 Ex{this, thisTo};它将为它们生成值(除非它们被设置为特定值),但是要访问它们,您需要使用表示该值的名称,就像使用解析运算符来获取类中的确切方法一样。正如关于枚举的文献将指出“枚举将解析为特定值(一个 int 地址),但即使该值已知,反向转换也永远不会解析”
  • @gardian06:是的,我知道枚举是什么,谢谢。我想知道引用的段落到底是什么意思。
  • @LightnessRacesinOrbit 这意味着您可以使用与在 C 中可以使用 #define CONST_THING = 0x0A 相同的枚举,并且每次使用 CONST_THING 时,它都会始终解析为该值。与 enum Ex{this, thisTo} 每次使用 thisTo 时相同的方式,它总是会解析为分配给它的值(假设范围),因此 Ex 是一个专用变量,而 thisTo 是它的值。是的,更好的说法可能应该是“因为枚举实际上只是一个具有预设已知值的专用变量”

标签: c++ string enums


【解决方案1】:

“ToString-like”函数实现有两种选择:

  1. 实现一个简单的静态 switch-case 函数。

代码:

std::string ThingEnumToString(ThingEnum thing)
{
    switch (thing) {
    case Thing1:
        return std::string("Thing1");
    case Thing2:    
        return std::string("Thing2");
    case Thing3:
        return std::string("Thing3");        
    case OtherThing:
        return std::string("OtherThing");
    default:
        throw std::invalid_argument("thing");
        break;
    }
}
  1. 使用字典查找实现静态函数。

代码:

typedef std::map<ThingEnum, std::string> ThingsMap;

static ThingsMap GetThingsMap()
{
    ThingsMap things_map;
    things_map.insert(ThingsMap::value_type(Thing1, std::string("Thing1")));
    things_map.insert(ThingsMap::value_type(Thing2, std::string("Thing2")));
    things_map.insert(ThingsMap::value_type(Thing3, std::string("Thing3")));
    things_map.insert(ThingsMap::value_type(OtherThing, std::string("OtherThing")));
    return things_map;
}

static std::string ThingEnumToString(ThingEnum thing)
{
    static const ThingsMap things(GetThingsMap());
    ThingsMap::const_iterator it = things.find(thing);
    if (it != things.end()) {
        return it->second;
    } else {
        throw std::invalid_argument("thing");
    }
}

【讨论】:

  • 我个人在枚举常量比较少的时候选择第一个。相反,当枚举常量很多时,第二个才是实际的。
【解决方案2】:

这是我提倡使用宏来使您的代码更易理解/更易于维护(并消除至少一个错误来源)的情况之一

这样

  #define TOSTRING(name) case name: return #name
  switch (val)
  {
      TOSTRING(Thing1);
      TOSTRING(Thing2);
      default:
         //bad things happened.
   }

【讨论】:

    【解决方案3】:

    不,枚举没有隐式基类。

    您可以使用模板或函数重载。但是,是的,您必须手动完成。

    枚举有一些技巧→字符串“转换”列出here

    【讨论】:

      【解决方案4】:

      enum 名称仅在编译前才有意义。我认为没有一种可移植的或标准定义的方式以干净的方式执行此操作。

      你可以这样做:

      std::string getName(ThingEnum x)
      {
         switch (x)
         {
         case Thing1:
            return "Thing1";
         case Thing2:
            return "Thing2";
         //....
         }
      }
      

      【讨论】:

      • 基本上,如果我可以将枚举放入函数中,那么我基本上可以像 case switch 一样返回正确的字符串。我不一定想让它返回自己的名字,但至少要对其进行逻辑检查。
      • @gardian06 是的,就像在我的编辑中一样,但它不是通用的(无论如何这都没有意义),你必须硬编码很多东西。你为什么还需要这个?
      • 生成日志消息。因为我必须在这些之上集成一些东西,并且“返回的方法:6”没有“返回的方法:错误2”那么有意义。
      猜你喜欢
      • 2018-11-24
      • 1970-01-01
      • 1970-01-01
      • 2015-11-21
      • 1970-01-01
      • 2011-03-27
      • 1970-01-01
      • 1970-01-01
      • 2020-06-07
      相关资源
      最近更新 更多