有很多解决方案如何使用C ++ proprocessor(例如this topic)将枚举的文本表示形式化为字符串。
但是,我想在相反的方向进行转换,以模仿字符串上的开关。
所以例如 - 给出以下枚举:
typedef enum { RIGHT, LEFT, FORWARD, BACKWARD} direction;
对于小枚举,可以定义字符串数组并使用枚举值来获取相应的字符串,但这对于维护是不利的。
我想要一些宏来定义一个函数"方向FromString(char * str)"如果我有一个字符串" RIGHT"将返回RIGHT。 / p>
其他编程语言有很多解决方案,例如C#或Java,所以我认为这不是一种糟糕的做法。
我可以使用similar question,但不使用预处理器。
我目前的溶剂(基于one of the answers to another question)如下所示:
#include <boost/preprocessor.hpp>
#define X_DEFINE_ENUM_WITH_STRING_CONVERSIONS_TOENUM(r, data, elem) \
if (!strcmp(s, BOOST_PP_STRINGIZE( elem ))) return elem;
#define DEFINE_ENUM_WITH_STRING_CONVERSIONS(name, enumerators) \
enum name { \
BOOST_PP_SEQ_ENUM(enumerators) \
}; \
inline const name FromString(char * s) { \
BOOST_PP_SEQ_FOR_EACH( \
X_DEFINE_ENUM_WITH_STRING_CONVERSIONS_TOENUM, \
name, \
enumerators \
) \
return ERR; \
}
可以通过以下方式使用它:
DEFINE_ENUM_WITH_STRING_CONVERSIONS(direction, (RIGHT)(LEFT)(...)(ERR))
缺点是当字符串与任何枚举名称都不匹配时,必须包含ERR来处理这种情况。怎么避免这个?
我在想,可能会使用更优雅的溶剂 Boost Bimap
答案 0 :(得分:1)
如果使用X-macros定义枚举,则可以轻松生成实现切换的函数:
#include <string>
#define MOUSE_BUTTONS \
X(LeftButton, 1) \
X(MiddleButton, 2) \
X(RightButton, 4)
enum MouseButton {
None = 0
#define X(name, value) ,name = value
MOUSE_BUTTONS
#undef X
};
static MouseButton stringAsMouseButton( const std::string &s )
{
#define X(name, value) if ( s == #name ) return name;
MOUSE_BUTTONS
#undef X
return None;
}
答案 1 :(得分:1)
你可以
#define stringify(name) # name
direction FromString(char * s) {
if (!strcmp(s, stringify(RIGHT)) return RIGHT;
if (!strcmp(s, stringify(LEFT)) return LEFT;
if (!strcmp(s, stringify(FORWARD)) return FORWARD;
if (!strcmp(s, stringify(BACKWARD)) return BACKWARD;
return -1;
}
答案 2 :(得分:1)
您可以尝试使用此库(免责声明 - 我是作者):https://github.com/aantron/better-enums
相关方法是_from_string(链接到文档)。如果出现错误,该方法会引发异常。还有另一种returns an option方法,类似于boost::optional
。
如果您想要实现自己的版本,请在Stack Overflow上的this answer中说明该方法。该答案中的代码包含_from_string
的实现。
答案 3 :(得分:0)
您可以创建一个地图,如下所示:
#define RIGHT_DIR "RIGHT"
#define LEFT_DIR "LEFT"
_directionActionMap[RIGHT_DIR] = RIGHT;
_directionActionMap[LEFT_DIR] = LEFT;
...
然后当你想从字符串
中检索枚举时int GetDirectionENUMFromString(const string& str)
{
int directionEnum;
std::map<string,int>::iterator iter;
iter = _directionActionMap.find(str);
if (iter != _directionActionMap.end())
{
directionEnum = (*iter).second;
}
else
{
directionEnum = -1;
}
return directionEnum;
}
用法:
int directionEnum = GetDirectionENUMFromString("RIGHT");
switch( directionEnum )
{
case RIGHT:
break;
case LEFT:
break;
...
}
答案 4 :(得分:0)
我通常使用数组来存储字符串(请求C ++ 11)
enum colors : int
{
RED,
GREEN,
BLUE,
MAX // MAX must be always at the end
};
static const char* const colorsString[] =
{
"RED",
"GREEN",
"BLUE",
};
// Ensure your two "lists" size are matching
static_assert(MAX == sizeof(colorsString) / sizeof(colorsString[0]), "Colors must have the same number of elements.");