如何轻松地映射c ++枚举到字符串 [英] How to easily map c++ enums to strings

查看:910
本文介绍了如何轻松地映射c ++枚举到字符串的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一些枚举类型在一些库头文件,我正在使用,我想有一种方法将枚举值转换为用户字符串 - 反之亦然。

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

由于函数和帮助类是模板化的, ,或地图状结构。也就是说它还可以向 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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆