有没有一种简单的方法可以将 C 枚举转换为字符串?

新手上路,请多包涵

假设我们有一些命名的枚举:

 enum MyEnum {
      FOO,
      BAR = 0x50
};

我搜索的是一个脚本(任何语言),它扫描我项目中的所有标题并生成一个标题,每个枚举都有一个函数。

 char* enum_to_string(MyEnum t);

和这样的实现:

 char* enum_to_string(MyEnum t){
      switch(t){
         case FOO:
            return "FOO";
         case BAR:
            return "BAR";
         default:
            return "INVALID ENUM";
      }
 }

问题在于类型定义的枚举和未命名的 C 风格枚举。有人知道吗?

编辑:解决方案不应该修改我的源代码,除了生成的函数。枚举在 API 中,因此使用迄今为止提出的解决方案不是一种选择。

原文由 Edu Felipe 发布,翻译遵循 CC BY-SA 4.0 许可协议

阅读 997
2 个回答

您可能想查看 GCCXML

在您的示例代码上运行 GCCXML 会产生:

 <GCC_XML>
  <Namespace id="_1" name="::" members="_3 " mangled="_Z2::"/>
  <Namespace id="_2" name="std" context="_1" members="" mangled="_Z3std"/>
  <Enumeration id="_3" name="MyEnum" context="_1" location="f0:1" file="f0" line="1">
    <EnumValue name="FOO" init="0"/>
    <EnumValue name="BAR" init="80"/>
  </Enumeration>
  <File id="f0" name="my_enum.h"/>
</GCC_XML>

您可以使用任何您喜欢的语言来提取 Enumeration 和 EnumValue 标签并生成您想要的代码。

原文由 Avdi 发布,翻译遵循 CC BY-SA 2.5 许可协议

在这里聚会有点晚了,但我真的很喜欢这种模式,因为它可以使您免于复制粘贴错误,并且如果枚举没有映射到字符串,它将完全无法编译。它还具有非常 constexpr 友好的优点,因此它内联得非常好。它也不需要中间类、switch 语句或运行时值。

 // Create a mapping between the enum value and the string
#define MY_ENUM_LIST(DECLARE) \
DECLARE(foo, "This is a foo!") \
DECLARE(bar, "This is a bar!") \
DECLARE(bam, "This is a bam!")

// Define the enum officially
enum class MyEnum {
#define ENUM_ENTRY(NAME, TEXT) NAME, // TEXT expressly not used here
    MY_ENUM_LIST(ENUM_ENTRY)
#undef ENUM_ENTRY // Always undef as a good citizen ;)
};

// Create a template function that would fail to compile if called
template <MyEnum KEY> constexpr const char* MyEnumText() {}

// Specialize that bad function with versions that map the enum value to the string declared above
#define ENUM_FUNC(NAME, TEXT) template <> constexpr const char* MyEnumText<MyEnum::NAME>() { return TEXT; }
MY_ENUM_LIST(ENUM_FUNC)
#undef ENUM_FUNC

您使用它的方式非常简单。如果您总是在需要字符串的站点上硬编码枚举值,您只需调用 MyEnumText 的专用版本:

 const auto text{::MyEnumText<MyEnum::foo>()}; // inlines beautifully

如果你需要处理动态枚举值,你可以添加这个额外的助手:

 constexpr const char* MyEnumText(MyEnum key) {
    switch (key) {
#define ENUM_CASE(NAME, TEXT) case MyEnum::NAME: return MyEnumText<MyEnum::NAME>();
        MY_ENUM_LIST(ENUM_CASE)
#undef ENUM_CASE
    }
    return nullptr;
}

它的调用类似于模板特化:

 const auto text{::MyEnumText(MyEnum::foo)}; // inlines beautifully

或者

const MyEnum e{GetTheEnumValue()};
const auto text{::MyEnumText(e)};

原文由 cppguy 发布,翻译遵循 CC BY-SA 4.0 许可协议

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题