使用 C++11 可变参数模板初始化枚举到字符串映射

Using C++11 variadic templates to initialize Enum To String Map

本文关键字:枚举 初始化 字符串 映射 C++11 变参 参数 使用      更新时间:2023-10-16

我认为可以使用 C++11 中引入的可变参数模板参数来初始化一个映射,其中键是整数,值是给定参数的字符串表示法。

如果可能的话,我可以简单地创建一个从枚举名称到其字符串表示的映射,如下所示:

auto map = EnumStringMap<EnumType::Type1, EnumType::Type2>();

我可以通过这个模板初始化一个带有枚举 int 表示的列表

template<typename... Ts> auto enumList(Ts... args){
    QList<int> res = {args...};
    return res;
}
auto enums =  enumList<int, int>(Enums::Enum1, Enums::Enum2);

我认为应该可以使用 STRINGFY C 宏来获取表达式的字符串表示

#define STRINGIFY(x) #x
#define TOSTRING(x) STRINGIFY(x)

但是我不知道如何将类型名称或类型值转换为其字符串表示形式,那么有可能吗?我的目标是生成一个映射,其中包含编译时枚举的字符串表示形式。

qt使用的MOC等方法不适合我,因为我应该将枚举包含在QObject中,这是繁重且不可复制的。

宏由预处理器在任何C++编译之前处理。因此,不能在函数中使用宏来检索枚举值的C++名称。

大多数解决方案都基于定义枚举时使用的宏。互联网上有许多可用的实现,它通常做这样的事情:

#define MY_ENUM(a, b, c) enum a {b , c} 
Map<a, string> mymap = {{b, STRINGIFY(b)}, {b, STRINGIFY(b)}};
MY_ENUM(Color, Red, Blue)
MY_ENUM(Align, Left, Right)

另一种方法是使用元编译器,它将处理C++代码以生成更多代码。这就是Qt对其moc所做的,既然你用Qt标记了你的问题,这可能是最好的方法。

class FooBar : public QObject {
  Q_OBJECT
public:
  enum Action { Open, Save, New, Copy, Cut, Paste, Undo, Redo, Delete };
  Q_ENUM(Action) // Not Q_ENUMS !!!
  static QString convert(Action a) {
    auto metaEnum = QMetaEnum::fromType<Action>();
    return metaEnum.valueToKey(a);
  }
};

这有一些约束,例如枚举必须在QObject(或Q_GADGET(中定义。您可以在Qt文档中找到更多信息。有关如何完成,您可以查看Woboq文章。