jlc*_*lin 1 c++ enums map c++11
我需要创建地图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;
}
Run Code Online (Sandbox Code Playgroud)
你不需要map.你的WhatDay功能可以像这样写:
Days WhatDay (unsigned int D) {
return static_cast<Days>(D);
}
Run Code Online (Sandbox Code Playgroud)
这基本上是免费的(在效率方面.)但是出于效率原因和可靠性原因,您可能希望再次确保您enum的基础类型确实是int(或更小或更大的东西):
enum class Days : int {
...
};
Run Code Online (Sandbox Code Playgroud)
但是,使用此方法将丢失的是错误检查.您将无法检查整数是否是有效的枚举值; 特别是如果你的枚举值不连续.
更新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.
Run Code Online (Sandbox Code Playgroud)
这是我的所有关于每个条目的信息,在一般的形式(即通过一个未知函数样的东西叫action.
现在,为了定义枚举,我们可以简单地说:
#define DEF_ENUM(i,v,s) v = i,
enum class Days : int { EXPAND_VALUES(DEF_ENUM) };
#undef DEF_ENUM
Run Code Online (Sandbox Code Playgroud)
作为进一步的示例,您可以定义所需的映射,以及将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
Run Code Online (Sandbox Code Playgroud)
(此示例代码在Ideone上可用.)
请注意这项技术对您的作用.如果没有在数据定义的任何冗余,获得尽可能多的数据结构的定义,数组的初始化,switch语句来的情况下,if- else if- else你要的是数据结构等.所有这些都是在编译时(或之前)完成的,没有任何麻烦.
这是一种非常强大的技术,可能(或可能不)对您有用.
更新1(回应更新的问题):
不,不可能enum在C++中创建运行时.当没有更多的编译器时,你不能在运行时为编译器创建一个新类型(如果你真的是这样的话.)
但是,由于enumC++中的s绝对没有提供运行时功能,因此,在运行时,enum具有相同底层类型的两个s 之间没有区别.或者实际上,在an enum和an 之间int(如果int是底层类型enum).
因此,我提出这个:你定义一个空 enum,并WhatDay像以前一样完全写函数.一切都会好的!(因为你不需要边界检查.)
具体来说,我建议的是:
enum class Days : int { /*really, really empty!*/ };
Days WhatDay (unsigned int D) {
return static_cast<Days>(D);
}
Run Code Online (Sandbox Code Playgroud)
这是有效的,因为在我看来,您在编译时不知道您的枚举值,并且编译器不关心enum运行时的值.没人做到!
如果你想要错误和范围检查,我建议你使用一个" 间隔树 "(在维基百科上阅读它.)当你读你填写此树enum在运行时从文件中的值(这是唯一的数据结构你populate,)然后检查传递给WhatDay函数的每个值.