c++:通过关键字获取枚举值,关键字是一个变量

c++: get enum value by keyword and the keyword is a variable

本文关键字:关键字 变量 一个 获取 c++ 枚举      更新时间:2023-10-16

在c++类Defs中,我有一个类似enum services {1st_drink = 101, 2nd_drink = 105, seafood_outside = 200,......}的公共枚举。我有大约200个关键词,每个关键词都有一个值。现在,在另一个类sometest中,我需要获得特定的关键字值。关键字就像我代码中的一个变量,只有经过一些处理才能知道关键字。所以我想做的是:

.......
std::string keyword = string1 + "_" + string2;
unsigned int a = Defs::keyword;
.......

但现在,当我尝试这样做时,我会得到错误"error C2039: 'keyword': is not a member of 'Defs'""error C2440: '=': cannot convert from 'std::string' to 'const unsigned int '"

现在我试着解决这个问题。我注意到有人在按名称获取枚举值之前问了一个类似的问题,但我不想使用这个解决方案,因为我有太多的关键字。有什么好主意吗?

您需要的是std::map<std::string, unsigned int>:

#include <map>
#include <string>
const std::map<std::string, unsigned int> services = {
    { "1st_drink", 101 },
    { "2nd_drink", 200 },
    // ...
};
const std::string keyword = string1 + "_" + string2;
const unsigned int a = services[keyword];

如果您碰巧使用Qt应用程序框架,您可以利用Qt的元对象编译器,该编译器存储有关类的信息,以便在运行时使用。主运行中心可以识别列举。

class Defs: public QObject {
    Q_OBJECT
    enum  Services { firstDrink = 1, secondDrink = 2, ... };
    Q_ENUMS(Services)
};

当moc在上面运行并看到Q_OBJECT时,它会添加一个类型为QMetaObjectstaticMetaObject成员。此QMetaObject实例具有indexOfEnumerator和枚举器成员函数,这些函数使访问代表Defs::Services枚举的QMetaEnum成为可能。

访问QMetaEnum成员的代码如下所示:

const QMetaObject &mo = Defuns::staticMetaObject;
int index = mo.indexOfEnumerator("Services");
QMetaEnum metaEnum = mo.enumerator(index);

然后,我们可以如下使用QMetaEnum对象:

// first, let's convert from an enum value to a string
Services s = Defs::firstDrink;
QByteArray str = metaEnum.valueToKey(s);
// str now contains "firstDrink"
// second, let's convert from a string to an enum value:
int value = metaEnum.keyToValue("firstDrink");
// value now contains the integer 1

我希望这能有所帮助。

作为一个可重用的通用解决方案,您可以在声明enums:时创建这样的枚举解析器模板

template <typename T>
class EnumParser
{
    map <string, T> enumMap;
    T defaultValue;
public:
    EnumParser(){};
    T Parse(const string &value)
    { 
        map <string, T>::const_iterator iValue = enumMap.find(value);
        if (iValue  == enumMap.end())
            return defaultValue;
        return iValue->second;
    }       
};

你可以像这样使用实例化:

enum class Services
{
    DeFault,
    First_drink = 101,
    Second_drink = 105,
    seafood_outside = 200,
};
EnumParser<Services>::EnumParser() : defaultValue(Services::DeFault)
{
    enumMap["DeFault"] = Services::DeFault;
    enumMap["First_drink"] = Services::First_drink;
    enumMap["Second_drink"] = Services::Second_drink;
    enumMap["seafood_outside"] = Services::seafood_outside;
}

然后这样使用:

int value= (int)EnumParser<Services>().Parse(keyword);