C++ 如何从其值中获取枚举项名称

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/11714325/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-27 15:28:03  来源:igfitidea点击:

How to Get enum item name from its value

c++enums

提问by Nano HE

I declared a enum type as this,

我声明了一个枚举类型,

enum WeekEnum
{
Mon = 0;
Tue = 1;
Wed = 2;
Thu = 3;
Fri = 4;
Sat = 5;
Sun = 6;
};

How can I get the item name "Mon, Tue, etc" when I already have the item value "0, 1, etc."

当我已经拥有项目值“0、1 等”时,如何获取项目名称“周一、周二等”?

I already have a function as this

我已经有了这样的功能

Log(Today is "2", enjoy! );

Log(Today is "2", enjoy! );

And now I want the output below

现在我想要下面的输出

Today is Wed, enjoy

今天是星期三,享受

回答by Luchian Grigore

You can't directly, enumin C++ are not like Java enums.

你不能直接,enum在 C++ 中不像 Java 枚举。

The usual approach is to create a std::map<WeekEnum,std::string>.

通常的方法是创建一个std::map<WeekEnum,std::string>.

std::map<WeekEnum,std::string> m;
m[Mon] = "Monday";
//...
m[Sun] = "Sunday";

回答by RolandXu

No, you have no way to get the "name" from the value in C++ because all the symbols are discarded during compilation.

不,您无法从 C++ 中的值中获取“名称”,因为在编译期间所有符号都被丢弃了。

You may need this way X Macros

您可能需要这种方式X 宏

回答by Cosine

An enumeration is something of an inverse-array. What I believe you want is this:

枚举是某种逆数组。我相信你想要的是:

const char * Week[] = { "", "Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday" };  // The blank string at the beginning is so that Sunday is 1 instead of 0.
cout << "Today is " << Week[2] << ", enjoy!";  // Or whatever you'de like to do with it.

回答by Puppy

You can define an operator that performs the output.

您可以定义执行输出的运算符。

std::ostream& operator<<(std::ostream& lhs, WeekEnum e) {
    switch(e) {
    case Monday: lhs << "Monday"; break;
    .. etc
    }
    return lhs;
}

回答by Killzone Kid

Here is another neat trick to define enum using X Macro:

这是使用 X 宏定义枚举的另一个巧妙技巧:

#include <iostream>

#define WEEK_DAYS \
X(MON, "Monday", true) \
X(TUE, "Tuesday", true) \
X(WED, "Wednesday", true) \
X(THU, "Thursday", true) \
X(FRI, "Friday", true) \
X(SAT, "Saturday", false) \
X(SUN, "Sunday", false)

#define X(day, name, workday) day,
enum WeekDay : size_t
{
    WEEK_DAYS
};
#undef X

#define X(day, name, workday) name,
char const *weekday_name[] =
{
    WEEK_DAYS
};
#undef X

#define X(day, name, workday) workday,
bool weekday_workday[]
{
    WEEK_DAYS
};
#undef X

int main()
{
    std::cout << "Enum value: " << WeekDay::THU << std::endl;
    std::cout << "Name string: " << weekday_name[WeekDay::THU] << std::endl;
    std::cout << std::boolalpha << "Work day: " << weekday_workday[WeekDay::THU] << std::endl;

    WeekDay wd = SUN;
    std::cout << "Enum value: " << wd << std::endl;
    std::cout << "Name string: " << weekday_name[wd] << std::endl;
    std::cout << std::boolalpha << "Work day: " << weekday_workday[wd] << std::endl;

    return 0;
}

Live Demo: https://ideone.com/bPAVTM

现场演示:https: //ideone.com/bPAVTM

Outputs:

输出:

Enum value: 3
Name string: Thursday
Work day: true
Enum value: 6
Name string: Sunday
Work day: false

回答by 2785528

How can I get the item name "Mon, Tue, etc" when I already have the item value "0, 1, etc."

当我已经拥有项目值“0、1 等”时,如何获取项目名称“周一、周二等”?

On some older C code (quite some time ago), I found code analogous to:

在一些较旧的 C 代码(很久以前)上,我发现代码类似于:

std::string weekEnumToStr(int n)
{
   std::string s("unknown");
   switch (n)
   {
   case 0: { s = "Mon"; } break;
   case 1: { s = "Tue"; } break;
   case 2: { s = "Wed"; } break;
   case 3: { s = "Thu"; } break;
   case 4: { s = "Fri"; } break;
   case 5: { s = "Sat"; } break;
   case 6: { s = "Sun"; } break;
   }
   return s;
}

Con: This establishes a "pathological dependency" between the enumeration values and the function... meaning if you change the enum you must change the function to match. I suppose this is true even for a std::map.

缺点:这在枚举值和函数之间建立了“病态依赖”……这意味着如果您更改枚举,则必须更改函数以匹配。我想即使对于 std::map 也是如此。

I vaguely remember we found a utility to generate the function code from the enum code. The enum table length had grown to several hundred ... and at some point it is maybe a sound choice to write code to write code.

我依稀记得我们找到了一个实用程序来从枚举代码生成函数代码。枚举表的长度已经增长到几百个……在某些时候,编写代码来编写代码可能是一个合理的选择。



Note -

笔记 -

in an embedded system enhancement effort, my team replaced many tables (100+?) of null-terminated-strings used to map enum int values to their text strings.

在嵌入式系统增强工作中,我的团队替换了许多用于将枚举 int 值映射到其文本字符串的空终止字符串表(100+?)。

The problem with the tables was that a value out of range was often not noticed because many of these tables were gathered into one region of code / memory, such that a value out-of-range reached past the named table end(s) and returned a null-terminated-string from some subsequent table.

表的问题是通常不会注意到超出范围的值,因为这些表中的许多都被收集到代码/内存的一个区域中,因此超出范围的值超过了指定的表末尾和从某个后续表中返回一个以空字符结尾的字符串。

Using the function-with-switch statement also allowed us to add an assert in the default clause of the switch. The asserts found several more coding errors during test, and our asserts were tied into a static-ram-system-log our field techs could search.

使用 function-with-switch 语句还允许我们在 switch 的 default 子句中添加一个断言。断言在测试期间发现了更多编码错误,并且我们的断言被绑定到我们的现场技术人员可以搜索的静态内存系统日志中。

回答by kayleeFrye_onDeck

If you know the actual enum labels correlated to their values, you can use containers and C++17's std::string_viewto quickly access values and their string representations with the []operator while tracking it yourself. std::string_viewwill only allocate memory when created. They can also be designated with static constexprif you want them available at run-time for more performance savings. This little console app should be fairly fast.

如果您知道与其值相关的实际枚举标签,您可以使用容器和 C++17std::string_view来快速访问值及其与[]运算符的字符串表示,同时自己跟踪它。std::string_view只会在创建时分配内存。static constexpr如果您希望它们在运行时可用以节省更多性能,也可以指定它们。这个小控制台应用程序应该相当快。

#include <iostream>
#include <string_view>
#include <tuple>    
int main() {
    enum class Weekdays { //default behavior starts at 0 and iterates by 1 per entry
        Monday,Tuesday,Wednesday,Thursday,Friday,Saturday,Sunday
    };

    static constexpr std::string_view Monday    = "Monday";
    static constexpr std::string_view Tuesday   = "Tuesday";
    static constexpr std::string_view Wednesday = "Wednesday";
    static constexpr std::string_view Thursday  = "Thursday";
    static constexpr std::string_view Friday    = "Friday";
    static constexpr std::string_view Saturday  = "Saturday";
    static constexpr std::string_view Sunday    = "Sunday";
    static constexpr std::string_view opener    = "enum[";
    static constexpr std::string_view closer    = "] is ";
    static constexpr std::string_view semi      = ":";

    std::pair<Weekdays, std::string_view> Weekdays_List[] = {
        std::make_pair(Weekdays::Monday,    Monday),
        std::make_pair(Weekdays::Tuesday,   Tuesday),
        std::make_pair(Weekdays::Wednesday, Wednesday),
        std::make_pair(Weekdays::Thursday,  Thursday),
        std::make_pair(Weekdays::Friday,    Friday),
        std::make_pair(Weekdays::Saturday,  Saturday),
        std::make_pair(Weekdays::Sunday,    Sunday)
    };

    for (int i=0;i<sizeof(Weekdays_List)/sizeof(Weekdays_List[0]);i++) {
        std::cout<<opener<<i<<closer<<Weekdays_List[(int)i].second<<semi\
        <<(int)Weekdays_List[(int)i].first<<std::endl;
    }    
    return 0;
}

Output:

输出:

enum[0] is Monday:0
enum[1] is Tuesday:1
enum[2] is Wednesday:2
enum[3] is Thursday:3
enum[4] is Friday:4
enum[5] is Saturday:5
enum[6] is Sunday:6

回答by rick-rick-rick

On GCC it may look like this:

在 GCC 上,它可能如下所示:

const char* WeekEnumNames [] = {
    [Mon] = "Mon",
    [Tue] = "Tue",
    [Wed] = "Wed",
    [Thu] = "Thu",
    [Fri] = "Fri",
    [Sat] = "Sat",
    [Sun] = "Sun",
};

回答by elvis.dukaj

The solution I prefer is to mix arrays and ostream like this:

我更喜欢的解决方案是像这样混合数组和 ostream:

std::ostream& operator<<(std::ostream& lhs, WeekEnum e) {
    static const std::array<std::string, 7> WEEK_STRINGS = {"Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday" };

    return os << WEEK_STRINGS[statuc_cast<WeekEnum>(e)]
}

cout << "Today is " << WeekEnum::Monday;

I also suggest to use enum class instead of Enum

我还建议使用 enum 类而不是 Enum

回答by Peter - Reinstate Monica

I have had excellent success with a technique which resembles the X macros pointed to by @RolandXu. We made heavy use of the stringize operator, too. The technique mitigates the maintenance nightmare when you have an application domain where items appear both as strings and as numerical tokens.

我使用类似于@RolandXu 指出的 X 宏的技术取得了巨大的成功。我们也大量使用了 stringize 运算符。当您的应用程序域中的项目同时显示为字符串和数字标记时,该技术可以减轻维护噩梦。

It comes in particularily handy when machine readable documentation is available so that the macro X(...) lines can be auto-generated. A new documentation would immediately result in a consistent program update covering the strings, enums and the dictionaries translating between them in both directions. (We were dealing with PCL6 tokens).

当机器可读文档可用时,它会特别方便,以便可以自动生成宏 X(...) 行。新文档将立即导致一致的程序更新,涵盖字符串、枚举和在它们之间双向翻译的字典。(我们正在处理 PCL6 令牌)。

And while the preprocessor code looks pretty ugly, all those technicalities can be hidden in the header files which never have to be touched again, and neither do the source files. Everything is type safe. The only thing that changes is a text file containing all the X(...) lines, and that is possibly auto generated.

虽然预处理器代码看起来很丑陋,但所有这些技术细节都可以隐藏在头文件中,永远不必再次触及,源文件也是如此。一切都是类型安全的。唯一改变的是一个包含所有 X(...) 行的文本文件,这可能是自动生成的。