C ++中枚举的字符串

时间:2009-04-07 17:02:48

标签: c++ string enums

有没有办法将文本文件中的字符串与枚举值相关联?

问题是:我有一些枚举值存储为文本文件中的字符串,我在满足某些条件时即时读取...现在我想将读取值分配给枚举。

最有效的方法是什么?它不需要是最简单的方法。

10 个答案:

答案 0 :(得分:31)

您可以设置一遍又一遍地使用的地图:

template <typename T>
class EnumParser
{
    map <string, T> enumMap;
public:
    EnumParser(){};

    T ParseSomeEnum(const string &value)
    { 
        map <string, T>::const_iterator iValue = enumMap.find(value);
        if (iValue  == enumMap.end())
            throw runtime_error("");
        return iValue->second;
    }
};

enum SomeEnum
{
    Value1,
    Value2
};
EnumParser<SomeEnum>::EnumParser()
{
    enumMap["Value1"] = Value1;
    enumMap["Value2"] = Value2;
}

enum OtherEnum
{
    Value3, 
    Value4
};
EnumParser<OtherEnum>::EnumParser()
{
    enumMap["Value3"] = Value3;
    enumMap["Value4"] = Value4;
}

int main()
{
    EnumParser<SomeEnum> parser;
    cout << parser.ParseSomeEnum("Value2");
}

答案 1 :(得分:9)

std::map< string, enumType> enumResolver;

答案 2 :(得分:3)

我同意std::map最容易解决的许多答案。

如果您需要更快的东西,可以使用哈希映射。也许您的编译器已经提供了一个,例如hash_map或即将推出的标准unordered_map,或者您可以从boost获得一个。当提前知道所有字符串时,也可以使用perfect hashing

答案 3 :(得分:2)

查看Boost.Bimap,它提供两组值之间的双向关联。 您也可以选择基础容器。

答案 4 :(得分:1)

使用std::map提出了一个问题:地图如何初始化?我宁愿使用一个函数:

enum E { A, B };

E f( const std::string & s ) {
   if ( s == "A" ) {
      return A;
    }
    else if ( s == "B" ) {
      return B;
    }
    else {
      throw "Your exception here";
    }
}

答案 5 :(得分:1)

这是你想要的吗?初始化是直的,不需要实例化。

用法:

enum SomeEnum
{
    ENUM_ONE,
    ENUM_TWO,
    ENUM_THREE,
    ENUM_NULL
};

DEFINE_PAIRLIST(CEnumMap, SomeEnum)

INIT_PAIRLIST(CEnumMap)=
{
        {"One", ENUM_ONE},
        {"Two", ENUM_TWO},
        {"Three", ENUM_THREE},
        {"", ENUM_NULL}
};

main{
    // Get enum from string
    SomeEnum i = CEnumMap::findValue("One");

    // Get string from enum
    SomeEnum eee = ENUM_ONE;
    const char* pstr = CEnumMap::findKey(eee);
    ...
}

库:

template <class T>
struct CStringPair
{
    const char* _name;
    T _value;
};

template <class T, class Derived>
struct CStringPairHandle
{
    typedef CStringPair<T> CPair;
    static const CStringPair<T> * getPairList(){
        return Derived::implementation();
    }
    static T findValue(const char* name){
        const CStringPair<T> * p = getPairList();
        for (; p->_name[0]!=0; p++)
            if (strcmp(name,p->_name)==0)
                break;
        return p->_value;
    }

    static const char* findKey(T value){
        const CStringPair<T> * p = getPairList();
        for (; p->_name[0]!=0; p++)
            if (strcmp(value,p->_value)==0)
                break;
        return p->_name;
    };
};

#define DEFINE_PAIRLIST(name, type) struct name:public CStringPairHandle<type, name>{ \
    static CPair _pairList[];       \
    static CPair* implementation(){     \
        return _pairList;           \
    }};
#define INIT_PAIRLIST(name) name::CPair name::_pairList[]

答案 6 :(得分:0)

自己解析字符串,将字符串与值匹配(也是map<string, enum>的索引。

答案 7 :(得分:0)

接受的答案不包含完整列表。我正在添加EnumParser.h我从接受的答案中创建,希望它可以帮助

#include <string>
#include <map>

using namespace std;

template <typename T> class EnumParser
{
    map<string, T> enumMap;
public:
    EnumParser(){};

    T ParseSomeEnum(const string &value)
    { 
        typename map <string, T>::const_iterator iValue = enumMap.find(value);
        if (iValue  == enumMap.end())
            throw runtime_error("");
        return iValue->second;
    }
};

用法很简单:

enum FieldType
{
    Char,
    Integer,
    Long,
    Fixed,
    Price,
    Date,
    Time
};

EnumParser<FieldType>::EnumParser()
{
    enumMap["Char"] = Char;
    enumMap["Integer"] = Integer;
    enumMap["Long"] = Long;
    enumMap["Fixed"] = Fixed;
    enumMap["Price"] = Price;
    enumMap["Date"] = Date;
    enumMap["Time"] = Time;
}

使用:

 EnumParser<FieldType> fieldTypeParser;
 FieldType val = fieldTypeParser.ParseSomeEnum(stringValue)

答案 8 :(得分:0)

您可以计算字符串的哈希值,然后使用它:

template <typename H, typename E>
E map_hash(H const key, std::initializer_list<std::pair<H, E>> const il)
{
  auto const i(
    std::find_if(il.begin(),
      il.end(),
      [key](auto& p)
      {
        return p.first == key;
      }
    )
  );

  assert(i != il.end());

  return i->second;
}

答案 9 :(得分:0)

从此处使用C ++反射库:https://github.com/tapika/cppreflect

您可以-包含这样的库:

#include "cppreflect/cppreflect.h"

基本用法:

声明枚举:

DECLARE_ENUM( enumName,
    // Prefix for all enums, "" if no prefix used.
    "myenum_",

    myenum_enumValue1,
    myenum_enumValue2,
    myenum_enumValue3 = 5,

    // comment
    myenum_enumValue4
);

转换逻辑:

从枚举到字符串:

printf( EnumToString(myenum_enumValue3).c_str() );

=> "enumValue3"

从字符串到枚举:

enumName value;

if( !StringToEnum("enumValue4", value) )
    printf("Conversion failed...");

=> 

value == myenum_enumValue4

主要/核心功能位于此处:

https://github.com/tapika/cppreflect/blob/master/cppreflect/enumreflect.h