String to enum in C++

后端 未结 10 1623
渐次进展
渐次进展 2020-11-28 07:15

Is there a way to associate a string from a text file with an enum value?

The problem is: I have a few enum values stored as string in a text file which I read on

相关标签:
10条回答
  • 2020-11-28 07:54

    Using C++ reflection library from here: https://github.com/tapika/cppreflect

    You can - include library like this:

    #include "cppreflect/cppreflect.h"
    

    Basic usage:

    Declare enumeration:

    DECLARE_ENUM( enumName,
        // Prefix for all enums, "" if no prefix used.
        "myenum_",
    
        myenum_enumValue1,
        myenum_enumValue2,
        myenum_enumValue3 = 5,
    
        // comment
        myenum_enumValue4
    );
    

    Conversion logic:

    From enumeration to string:

    printf( EnumToString(myenum_enumValue3).c_str() );
    
    => "enumValue3"
    

    From string to enumeration:

    enumName value;
    
    if( !StringToEnum("enumValue4", value) )
        printf("Conversion failed...");
    
    => 
    
    value == myenum_enumValue4
    

    Main / core functionality resides in here:

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

    0 讨论(0)
  • 2020-11-28 07:55

    Accepted answer doesn't contain full listing. I'm adding EnumParser.h which I created from the accepted answer, hope it can help

    #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;
        }
    };
    

    Usage is simple:

    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;
    }
    

    use:

     EnumParser<FieldType> fieldTypeParser;
     FieldType val = fieldTypeParser.ParseSomeEnum(stringValue)
    
    0 讨论(0)
  • 2020-11-28 07:55

    You can calculate the hash of the string and then use this:

    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;
    }
    
    0 讨论(0)
  • 2020-11-28 07:59

    Is this what you want? The initialization is straight, and no instantiation is needed.

    usage:

    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);
        ...
    }
    

    library:

    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[]
    
    0 讨论(0)
提交回复
热议问题