如何轻松地映射c ++枚举到字符串 [英] How to easily map c++ enums to strings
问题描述
我有一些枚举类型在一些库头文件,我正在使用,我想有一种方法将枚举值转换为用户字符串 - 反之亦然。
I have a bunch of enum types in some library header files that I'm using, and I want to have a way of converting enum values to user strings - and vice-versa.
RTTI不会为我做,因为'用户字符串'需要比枚举更可读。
RTTI won't do it for me, because the 'user strings' need to be a bit more readable than the enumerations.
一个强力的解决方案会是这样的一堆函数,但我觉得有点太C了。
A brute force solution would be a bunch of functions like this, but I feel that's a bit too C-like.
enum MyEnum {VAL1, VAL2,VAL3};
String getStringFromEnum(MyEnum e)
{
switch e
{
case VAL1: return "Value 1";
case VAL2: return "Value 2";
case VAL1: return "Value 3";
default: throw Exception("Bad MyEnum");
}
}
我有一个直觉感觉有一个优雅的解决方案。
I have a gut feeling that there's an elegant solution using templates, but I can't quite get my head round it yet.
更新:感谢您的建议 - 我应该明确表示,枚举在第三方库头文件中定义,所以我不想改变它们的定义。
UPDATE: Thanks for suggestions - I should have made clear that the enums are defined in a third-party library header, so I don't want to have to change the definition of them.
我的直觉现在是避免模板和做这样的事情:
My gut feeling now is to avoid templates and do something like this:
char * MyGetValue(int v, char *tmp); // implementation is trivial
#define ENUM_MAP(type, strings) char * getStringValue(const type &T) \
{ \
return MyGetValue((int)T, strings); \
}
; enum eee {AA,BB,CC}; - exists in library header file
; enum fff {DD,GG,HH};
ENUM_MAP(eee,"AA|BB|CC")
ENUM_MAP(fff,"DD|GG|HH")
// To use...
eee e;
fff f;
std::cout<< getStringValue(e);
std::cout<< getStringValue(f);
推荐答案
如果要将枚举名称自身作为字符串,请参阅此帖。
否则, std :: map< MyEnum,char const *>
将很好地工作。 (在复制你的字符串字面量到std ::字符串在地图中)
If you want the enum names themselves as strings, see this post.
Otherwise, a std::map<MyEnum, char const*>
will work nicely. (No point in copying your string literals to std::strings in the map)
对于额外的语法糖,这里是如何编写一个map_init类。目的是允许
For extra syntactic sugar, here's how to write a map_init class. The goal is to allow
std::map<MyEnum, const char*> MyMap;
map_init(MyMap)
(eValue1, "A")
(eValue2, "B")
(eValue3, "C")
;
函数 template< typename T& map_init(T&)
返回 map_init_helper< T>
。
map_init_helper< T>
存储一个T&,并定义了平凡的 map_init_helper& operator()(typename T :: key_type const& typename T :: value_type const&)
。 (返回 * 从
运算符()
允许 c $ c>,如
运算符<
在
std :: ostream
s)
The function template <typename T> map_init(T&)
returns a map_init_helper<T>
.
map_init_helper<T>
stores a T&, and defines the trivial map_init_helper& operator()(typename T::key_type const&, typename T::value_type const&)
. (Returning *this
from operator()
allows the chaining of operator()
, like operator<<
on std::ostream
s)
template<typename T> struct map_init_helper
{
T& data;
map_init_helper(T& d) : data(d) {}
map_init_helper& operator() (typename T::key_type const& key, typename T::mapped_type const& value)
{
data[key] = value;
return *this;
}
};
template<typename T> map_init_helper<T> map_init(T& item)
{
return map_init_helper<T>(item);
}
由于函数和帮助类是模板化的, ,或地图状结构。也就是说它还可以向 std :: unordered_map
Since the function and helper class are templated, you can use them for any map, or map-like structure. I.e. it can also add entries to std::unordered_map
如果你不喜欢写这些助手,boost :: assign会提供相同的功能。
If you don't like writing these helpers, boost::assign offers the same functionality out of the box.
这篇关于如何轻松地映射c ++枚举到字符串的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!