【问题标题】:Variable enum 'class' in c++C ++中的变量枚举“类”
【发布时间】:2020-10-01 08:45:15
【问题描述】:

我经常在以下代码中使用类似的东西:

// myclass.h

class MyClass {
 public:
  enum MyEnum { E1, E2, NUMMYENUM };
  const char* kMyEnum[NUMMYENUM] = {"e1", "e2"};
  const char* MyEnum2Char(MyEnum me) { return kMyEnum[me]; }

  enum MySEnum { SE1, SE2, NUMMYSENUM };
  static const char* kMySEnum[NUMMYSENUM];
  static const char* MySEnum2Char(MySEnum se) { return kMySEnum[se]; }

  void foo(MyEnum me) {
    //do something, e.g. print
    std::cout << MyEnum2Char(me) << "maps to " << emap[me] << "\n";
  }

  void bar(MySEnum se) {
    //do something, e.g. print
    std::cout << MySEnum2Char(se) << "maps to " << semap[se] << "\n";
  }

 private:
  std::map<MyEnum, int> emap;
  std::map<MySEnum, int> semap;
 };


// myclass.cc

#include "myclass.h"

const char* MyClass::kMySEnum[MyClass::MySEnum::NUMMYSENUM] = {"se1", "se2"};

生成enumchar* 数组和将enum 转换为char 的函数的方式似乎增加了可避免的混乱,我想知道是否没有其他方法可以实现这一点?出于多种原因,无法执行以下操作,但可能会让您对我想要的有所了解:

// myclass.h

class MyClass {
 public:
  MyVariableEnumClass MyEnum(E1, "e1", E2, "e2");    
  static MyVariableEnumClass MySEnum;

  void foo(MyEnum me) {
    //do something, e.g. print
    std::cout << me.string() << "maps to " << emap[me] << "\n";
  }

  void bar(MySEnum se) {
    //do something, e.g. print
    std::cout << se.string() << "maps to " << semap[se] << "\n";
  }

 private:
  std::map<MyEnum, int> emap;
  std::map<MySEnum, int> semap;
 };


// myclass.cc

#include "myclass.h"

MyVariableEnumClass MyClass::MySEnum = MyVariableEnumClass(SE1, "se1", SE2, "se2");

有没有办法实现这样的“无杂乱”?也许使用宏?

【问题讨论】:

  • 有点,我想。缺点是它需要 c++17,而我使用的是 c++11,另外我想指定(可能有不同的命名)附加到每个枚举的字符/字符串(E1"e1" ),而magic_enum 似乎对两者有相同的命名(E1"E1")。
  • 有时使用的一个技巧是有一个定义枚举值的头文件,像这样:ENUM_VALUE(SE1, "se1")(更像这样)。文件本身没有定义ENUM_VALUE。然后你#include 这个头两次——一次定义ENUM_VALUE 以发出枚举值的方式,然后再次定义它以发出字符串文字。所以你可以从同一个源生成MyEnumkMyEnum
  • 另一个技巧是用自己选择的脚本语言定义数据,然后编写一个脚本自动生成 C++ 代码。

标签: c++ c++11 enums


【解决方案1】:

一种称为 XMacro 的技术可用于 C++ 11 以及旧版本的 C++ 和 C,以轻松定义一致的查找表,以将枚举转换为字符串。

首先,您编写一个外部文件(我们称之为 my_class.xmacro),其中包括以下内容:

#define SE_ENUM_TABLE  \
    ENTRY(SE1) \
    ENTRY(SE2) 

接下来在您的 H 文件中包含 my_class.xmacro 定义以下内容:

#include "my_class.xmacro"

    
enum SeEnum{
#define ENTRY(a) a,
       SE_ENUM_TABLE
#undef ENTRY
    };

const std::string seEnumString[] = {
#define str_macro(a) #a
#define ENTRY(a) str_macro(a),
    SE_ENUM_TABLE
#undef ENTRY
};

seEnumStringId 中的宏采用 ENTRY(a) 并将其转换为“a”。所以在预处理器处理完这个文件后,它实际上看起来编译器如下:

enum SeEnum{
    SE1,
    SE2 
};
    
const std::string seEnumString[] = {
    "SE1",
    "SE2" 
    };

使用这种技术,您可以确保添加枚举会自动按 RIGHT 顺序创建字符串 id,并且这种技术也可用于生成其他类型的查找表。

【讨论】:

    猜你喜欢
    • 2017-09-09
    • 2018-08-30
    • 1970-01-01
    • 2016-08-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多