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
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
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)
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;
}
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[]