c++ - 如何自动将枚举转换为字符串

标签 c++ c enums

这是以下 question 的扩展已经有了很好的答案。

但是,在预处理器执行扩展的所有答案中,枚举都是在同一项目下以特殊方式声明的。 但是,如果声明这些枚举的头文件不是您自己的,或者这些枚举声明的 id 顺序不正确怎么办。

就我而言,我有一个正在使用的 SDK,其中大型枚举表已在单独的头文件中声明,如下所示:

#define NODE_GRAPH_TYPE(_name, _enum)   _name = _enum,
enum NodeGraphType
{
    // next available ID value is 7
    NODE_GRAPH_TYPE(GT_UNKNOWN          , 0)
    NODE_GRAPH_TYPE(GT_STANDARD         , 1)
    NODE_GRAPH_TYPE(GT_APP_SETTINGS     , 3)
    NODE_GRAPH_TYPE(GT_GEOMETRYARCHIVE  , 2)
    NODE_GRAPH_TYPE(GT_SCRIPTED         , 5)
    NODE_GRAPH_TYPE(GT_SCRIPT_STORAGE   , 6)
    NODE_GRAPH_TYPE(GT_PROJECT_SETTINGS , 4)
};

我想做的是尽量避免这种事情:

function NODE_GRAPH_NAME(int type)
{
  switch(type)
  {
    case: GT_PROJECT_SETTINGS:
      return "GT_PROJECT_SETTINGS";
    // ...
  };
}

static const char* NODE_GRAPH_NAME[] = {
  "GT_UNKNOWN",
  /// ...    
}

到目前为止我想出的最好的:

#define STRINGIFY(_x) #_x

static const char* NODE_GRAPH_NAME[] = {
  STRINGIFY(GT_UNKNOWN),
  STRINGIFY(GT_STANDARD),
  STRINGIFY(GT_GEOMETRYARCHIVE),
  STRINGIFY(GT_APP_SETTINGS)
  // etc
};

但它仍然需要我复制所有枚举表,不仅如此,还要按顺序复制它们并仔细检查没有漏洞。

是否有更优雅、更自动化的方式来解决这个问题? 如果有帮助,我实际上是在 C++ 下编译的。但是我链接到的库是纯 C 语言。所以您也许可以用模板做一些花哨的事情。


根据下面 Thomas Matthews 的回答,我得出以下结论:

这不是完全自动的,但使用起来并不太困难。 在重新定义 NODE_GRAPH_TYPE 时,我可以逐字复制 SDK header 中的表并将其放入 NODE_GRAPH_TYPES 表定义中。 它有效。然后我可以创建一个查找函数来定位我需要的项目。这样做的好处是孔无关紧要,乱序定义也无关紧要。

#undef NODE_GRAPH_TYPE
#define NODE_GRAPH_TYPE(_name, _enum) { _enum, #_name },

static const Enum_Entry NODE_GRAPH_TYPES[] = 
{
   NODE_GRAPH_TYPE(GT_UNKNOWN          , 0)

    NODE_GRAPH_TYPE(GT_STANDARD         , 1)
    NODE_GRAPH_TYPE(GT_APP_SETTINGS     , 3)
    NODE_GRAPH_TYPE(GT_GEOMETRYARCHIVE  , 2)
    NODE_GRAPH_TYPE(GT_SCRIPTED         , 5)
    NODE_GRAPH_TYPE(GT_SCRIPT_STORAGE   , 6)
    NODE_GRAPH_TYPE(GT_PROJECT_SETTINGS , 4)
};

static const unsigned int NODE_GRAPH_TYPES_COUNT = 
    sizeof(NODE_GRAPH_TYPES) / sizeof(NODE_GRAPH_TYPES[0]);

const char* NODE_GRAPH_TYPE_NAME(int id)
{    
    for (int i = 0; i < NODE_GRAPH_TYPES_COUNT; ++i){
        if (PIN_TYPES[i].enum_value == id)
            return PIN_TYPES[i].enum_text;
    }
    return "Unknown";
} 

最佳答案

您不能将 enum 转换为文本或将文本转换为 enum 自动,仅作为 enum 标识符在编译期间存在,而不是在运行时存在。

最好的方法是表查找或 std::map

我使用表查找,因为我可以使表staticconst 并在main 之前对其进行初始化。

struct Enum_Entry
{
  int enum_value;
  const char * enum_text;
};

static const Enum_Entry enum_table[] = 
{
  {GT_UNKNOWN, "GT_UNKNOWN"},
  //...
};
static const unsigned int table_capacity =
    sizeof(enum_table) / sizeof(enum_table[0]);

通过将 enum 值和文本放在同一个表中,一个表可用于将文本转换为 enumenum 到文本。
使用 std::map 时,其中一个转换方向效率不高。

关于c++ - 如何自动将枚举转换为字符串,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42123397/

相关文章:

c# - .NET 如何通过套接字获取 int C-Sharp

c - 无法在 C 中将 'y1' 用作浮点变量

java - 是否需要 Java 枚举类型的防御副本?

c++ - 为什么对相同常量的引用在 C++ 中占用不同的内存空间?

c++ - 多参数类模板和我的 'vertices' 类

c - 使用c中的线程对矩阵中的元素求和

c - 使用 calloc 分配二维数组

c++ - 为什么在 C++ 中声明枚举时使用 typedef?

c++ - 返回枚举而不是索引

c++ - 尝试获取 QSqlQuery 的值时出现编译错误?