【问题标题】:Using C++11 variadic templates to initialize Enum To String Map使用 C++11 可变参数模板初始化 Enum To String Map
【发布时间】:2018-04-27 02:49:05
【问题描述】:

我认为可以使用 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 中,这很重且不可复制。

【问题讨论】:

  • AFAIK 这在 C++ 中是不可能的。尽管在 C# 中可能。我会自己创建这样的映射(静态)EnumStringMap&lt;EnumType, std::string&gt;
  • BETTER_ENUMS 等库常用的方法是使用 MACRO 来定义枚举。 (直到我们对此进行反思)。
  • @vahancho 对于大量枚举(可能超过 500 个),手动维护它非常困难

标签: c++ qt c++11


【解决方案1】:

宏在任何 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 documentation 中找到更多信息。具体做法可以看Woboq article

【讨论】:

  • 谢谢,我忘了提及我知道 Qt 使用的方法,但是枚举应该包含在不需要的 QObject 中
  • @e.jahandar 您可以使用 Q_GADGET,它比 QObject 轻,但也不完美。要获得完整的 C++ 支持,您需要等待 C++2x。如果您有兴趣,请参阅 Herb Sutter 在 CppCon2017 上的演讲
猜你喜欢
  • 2021-08-20
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-03-23
  • 2016-07-14
  • 1970-01-01
相关资源
最近更新 更多