如何轻松地将c ++枚举映射到字符串

编程入门 行业动态 更新时间:2024-10-28 12:30:27
本文介绍了如何轻松地将c ++枚举映射到字符串的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧! 问题描述 我在我使用的一些库头文件中有一堆枚举类型,我想有一种将枚举值转换为用户字符串的方法,反之亦然。

RTTI不会为我做,因为'用户字符串'需要比枚举更易读。

一个强力解决方案将是一堆这样的功能,但我觉得这有点像C一样。

枚举MyEnum {VAL1,VAL2,VAL3}; String getStringFromEnum(MyEnum e) { switch e { case VAL1:returnValue 1; case VAL2:returnValue 2; case VAL1:returnValue 3; default:throw异常(Bad MyEnum); } }

我有一个直觉,有一个优雅的解决方案使用模板,但我不能完全了解它。

更新:感谢您的建议 - 我应该已经明确表示枚举在第三方库标题中定义,所以我不想更改它们的定义。

我现在的感觉是避免模板和做这样的事情:

char * MyGetValue(int v,char * tmp); //实现是微不足道的 #define ENUM_MAP(类型,字符串)char * getStringValue(const类型& T)\ {\ 返回MyGetValue((int) T,字符串); \ } ; enum eee {AA,BB,CC}; - 存在于库头文件;枚举fff {DD,GG,HH}; ENUM_MAP(eee,AA | BB | CC) ENUM_MAP(fff,DD | GG | HH) //要使用.. 。 eee e; fff f; std :: cout<<<向GetStringValue(E); std :: cout<<<向GetStringValue(F);

解决方案

如果您希望将枚举名称作为字符串,请参阅这篇文章。 否则,一个 std :: map< MyEnum,char const *> 将会很好地工作。 (没有意义的将字符串文字复制到地图中的std :: string)

对于额外的语法糖,下面是如何编写map_init类。目标是允许

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&)。 (从运算符()返回 * 允许链接 operator(),如运算符< 在 std :: ostream s)

模板< typename T> struct map_init_helper { T&数据; 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; } }; 模板< typename T> map_init_helper< T> map_init(T& item) { return map_init_helper< T>(item); }

由于函数和助手类是模板化的,因此可以将它们用于任何地图,或地图样结构。即它也可以添加条目到 std :: unordered_map

如果您不喜欢编写这些帮助器,boost :: assign将提供相同的功能开箱即用。

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 won't do it for me, because the 'user strings' need to be a bit more readable than the enumerations.

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

解决方案

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)

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") ;

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::ostreams)

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

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

If you don't like writing these helpers, boost::assign offers the same functionality out of the box.

更多推荐

如何轻松地将c ++枚举映射到字符串

本文发布于:2023-10-23 03:30:59,感谢您对本站的认可!
本文链接:https://www.elefans.com/category/jswz/34/1519623.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文标签:字符串   轻松

发布评论

评论列表 (有 0 条评论)
草根站长

>www.elefans.com

编程频道|电子爱好者 - 技术资讯及电子产品介绍!