我需要创建一个int
到enum
值的映射。(我正在读取文件中的整数,并且需要enum
在运行时从中创建一个整数。)我可以手动创建一个映射,如下例所示。但是,这是一个琐碎的示例,我的枚举中只有几个(即七个)元素。
我的现实世界问题中有数百个元素enum class
。我不需要打印真实世界的名称enum
,但是我确实需要获取enum
给定整数的值。我已经enum class
创建了,并且想要一种自动的方法来创建一个从整数到枚举值的映射。
我正在寻求自动创建我已调用的地图,WeekMap
以便可以将其传递给整数并获取enum
值。这有可能吗?请告诉我是。
// Compile with:
// clang++ -std=c++11 -stdlib=libc++ enum_test.cpp -o enum_test
//
#include <iostream>
#include <string>
#include <map>
enum class Days {
SUNDAY = 1,
MONDAY = 2,
TUESDAY = 3,
WEDNESDAY = 4,
THURSDAY = 5,
FRIDAY = 6,
SATURDAY = 7
};
std::ostream& operator<< (std::ostream& os, const Days& day){
os << static_cast<std::underlying_type<Days>::type>(day);
return os;
}
std::map<unsigned int, Days> WeekMap{
{1, Days::SUNDAY},
{2, Days::MONDAY},
{3, Days::TUESDAY},
{4, Days::WEDNESDAY},
{5, Days::THURSDAY},
{6, Days::FRIDAY},
{7, Days::SATURDAY},
};
// Return the day of the week
Days WhatDay(unsigned int D){
return WeekMap[D];
}
int main() {
std::cout << "\nLearning how to 'cout' enums." << std::endl;
Days myDay = Days::MONDAY;
std::cout << "\nMonday is day: " << myDay << "\n" << std::endl;
for (int i=1; i<8; i++){
std::cout << "Day number: " << i << " is " << WhatDay(i) << std::endl;
}
return 0;
}
您不需要map
。您的WhatDay
函数可以这样写:
Days WhatDay (unsigned int D) {
return static_cast<Days>(D);
}
从效率的角度来看,这基本上是免费的。但是出于效率和可靠性的考虑,您可能要确保自己enum
的基础类型确实是int
(或更大或更小的东西):
enum class Days : int {
...
};
但是,使用此方法将失去的是错误检查。您将无法检查整数是否为有效的枚举值;尤其是当您的枚举值不连续时。
UPDATE 2(下面是Update 1!)要某种程度上自动创建这种enum
,以及许多其他代码,可以使用以下技术:
您首先以通用格式写下您感兴趣的数据:
#define EXPAND_VALUES(action) \
action (1, SUNDAY, "Sunday") \
action (2, MONDAY, "Monday") \
action (3, TUESDAY, "Tuesday") \
action (4, WEDNESDAY, "Wednesday") \
action (5, THURSDAY, "Thursday") \
action (6, FRIDAY, "Friday") \
action (7, SATURDAY, "Saturday")
// Note the lack of a separator after the entries; this is more flexible.
这是我所拥有的关于每个条目的全部信息,形式一般(即传递给名为的未知函数之类的东西)action
。
现在,要定义枚举,我们可以简单地说:
#define DEF_ENUM(i,v,s) v = i,
enum class Days : int { EXPAND_VALUES(DEF_ENUM) };
#undef DEF_ENUM
作为进一步的示例,您可以定义所需的映射,以及另一个将enum
值映射到字符串的表,如下所示:
#define DEF_MAP(i,v,s) {i, Days::v},
std::map<int, Days> WeekMap { EXPAND_VALUES(DEF_MAP) };
#undef DEF_MAP
#define DEF_STR_MAP(i,v,s) {Days::v, s},
std::map<Days, std::string> WeekStrMap { EXPAND_VALUES(DEF_STR_MAP) };
#undef DEF_STR_MAP
(此示例代码在Ideone上可用。)
请注意此技术对您的作用。如果没有在数据定义的任何冗余,获得尽可能多的数据结构的定义,数组的初始化,switch
语句来的情况下,if
- else if
-else
你想要的数据进行结构等。所有这些都是在编译时(或之前)完成的,没有任何麻烦。
这是一种非常强大的技术,可能对您有用(也可能没有)。
更新1(针对更新的问题):
不可以,无法enum
在C ++中创建运行时。如果没有更多的编译器,则无法在运行时为编译器创建新类型(如果确实要这样做)。
但是,由于enum
C ++中的s绝对不提供运行时功能,因此在运行时,enum
具有相同基础类型的两个s之间没有区别。或实际上是在anenum
和an之间int
(如果int
是该类型的基础类型enum
)。
因此,我建议这样做:您定义一个empty enum
,并WhatDay
像以前一样编写函数。一切都会好起来的!(因为您不需要边界检查。)
具体来说,我的建议是:
enum class Days : int { /*really, really empty!*/ };
Days WhatDay (unsigned int D) {
return static_cast<Days>(D);
}
之所以可行,是因为在我看来您不知道编译时的枚举值,并且编译器不在乎enum
运行时的a值。没人做到!
而且,如果您要进行错误和范围检查,建议您使用“间隔树”(在Wikipedia上进行阅读)。enum
在运行时从文件中读取值时,请填充此树(这是您唯一的数据结构)填充),然后WhatDay
根据它检查传递给函数的每个值。
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句