自动创建从整数到枚举的值映射
C++11 Automate creation of integer to enum value map
我需要创建一个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(更新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
构造等。所有这些都是在编译时(或之前)完成的,没有任何麻烦。
这是一个非常强大的技术,可能(也可能不)对你有用。
UPDATE 1(回答更新后的问题):
不,在c++中不可能在运行时创建enum
。你不能在运行时为编译器创建一个新的类型,当没有更多的编译器时(如果这是你真正想要的)
然而,由于c++中的enum
s绝对没有提供运行时设施,因此,在运行时,具有相同底层类型的两个enum
s之间没有区别。或者实际上,在enum
和int
之间(如果int
是enum
的底层类型)
enum
,并完全像以前一样编写WhatDay
函数。一切都会好起来的!(因为你不需要边界检查)
具体来说,我的建议是:
enum class Days : int { /*really, really empty!*/ };
Days WhatDay (unsigned int D) {
return static_cast<Days>(D);
}
这是有效的,因为在我看来,你不知道你的枚举值在编译时,编译器不关心一个位的enum
的值在运行时。没人知道!
如果你想要错误和范围检查,我建议你使用"间隔树"(在维基百科上阅读它)。当您在运行时从文件中读取enum
值时(这是您填充的唯一数据结构),然后根据它检查传递给WhatDay
函数的每个值。
- 如何在没有映射的情况下在枚举和字符串之间进行转换?
- std::映射键作为模板化结构与枚举成员
- 如何使用枚举将字符值映射到 int
- 编译结构的时枚举映射
- 有效的双向作用域枚举映射
- 映射枚举值为C 中的模板参数
- 使用 C++11 可变参数模板初始化枚举到字符串映射
- 将枚举值映射到 C++ 中的类型
- 将C++枚举映射为常量字符*
- 在类中映射命名空间枚举
- 将一个枚举映射到另一个枚举
- 定义基于模板的映射指针,以便在验证范围时将 int 解析为枚举
- 在C++中如何将运行时类型鉴别器映射到模板实例(无需手动枚举所有实例)
- 枚举映射对重构具有鲁棒性
- 在模板专门化中映射枚举
- 使用C++中的函数指针映射枚举键和值
- 映射/联接两个自动生成的枚举的最佳方式
- 将存储在多映射中的私有枚举作为值读取
- 将字符串和枚举映射到模板化类型
- c++中的枚举映射