我有一个包含枚举字符串表示的配置文件。有很多不同的枚举值。加载配置后,我需要从字符串表示中计算出枚举值。忽略宏,我能想到的唯一方法就是创建一个可怕的查找函数,对每个可能的值进行字符串比较。类似的东西:
typedef enum Fields
{
FieldFlagNone,
FieldFlagOperation,
FieldFlagFormat,
...
}
Fields getFieldEnum(string fieldName){
if( fieldName.compare("FieldFlagNone") == 0 ){
return FieldFlagNone;
}else if( fieldName.compare("FieldFlagOperation") == 0 ){
return FieldFlagOperation;
}else if( fieldName.compare("FieldFlagFormat") == 0 ){
return FieldFlagFormat;
...
}
是否有更快或更简洁的方法来达到预期效果?
答案 0 :(得分:2)
您可以使用std::unordered_map<std::string, Fields>
,这将加快从线性时间到恒定时间的转换:
std::unordered_map<std::string, Fields> fieldsLookupTable {
{ "FieldFlagNone", FieldFlagNone },
...
};
为了使其更简洁,您可以使用一些宏:
#define LOOKUP_TABLE_ENTRY(x) { #x, x }
然后:
std::unordered_map<std::string, Fields> fieldsLookupTable {
LOOKUP_TABLE_ENTRY(FieldFlagNone),
LOOKUP_TABLE_ENTRY(FieldFlagOperation),
...
};
如果你想真正去消除重复,你可以这样做:
#define ENUM_MODE_DEFINE 0
#define ENUM_MODE_LOOKUP 1
#define ENUM_BEGIN(x) \
#if ENUM_MODE == ENUM_MODE_DEFINE \
typedef enum x { \
#else \
#define LOOKUP_TABLE_NAME x ## LookupTable \
std::unordered_map<std::string, x> LOOKUP_TABLE_NAME; \
#endif
#define ENUM_ENTRY(x) \
#if ENUM_MODE == ENUM_MODE_DEFINE \
x, \
#else \
LOOKUP_TABLE_NAME[#x] = x; \
#endif
#define ENUM_END \
#if ENUM_MODE == ENUM_MODE_DEFINE \
} \
#else \
#undef LOOKUP_TABLE_NAME \
#endif
然后像这样定义你的枚举:
#define FIELDS \
ENUM_BEGIN(Fields) \
ENUM_ENTRY(FieldFlagNone) \
ENUM_ENTRY(FieldFlagOperation) \
...
ENUM_END
以前有枚举定义,现在会有:
#define ENUM_MODE ENUM_MODE_DEFINE
FIELDS
在你拥有查找表的其他地方,你这样说:
#define ENUM_MODE ENUM_MODE_LOOKUP
FIELDS
FIELDS
宏基本上使用ENUM_BEGIN
,ENUM_ENTRY
和ENUM_END
宏,它们会根据ENUM_MODE
的值生成不同的代码。如果您将其定义为ENUM_MODE_DEFINE
,则FIELDS
将生成枚举定义。如果您将其设置为ENUM_MODE_LOOKUP
,则会生成fieldsLookupTable
。
这样我们只使用FIELDS
中的枚举条目名称,因此如果你在那里更改某些内容,查找表和枚举定义将自动更改,不会不同步。