一个例子通常比长期解释更好.
您可以在Coliru上编译并运行此代码段.
(另一个前例子也可用)
#include <map>
#include <iostream>
struct MyClass
{
enum class …Run Code Online (Sandbox Code Playgroud) 该ç预处理器有理由担心和C++社区避之唯恐不及.内联功能,功能和模板通常是更安全和更好的替代品#define.
以下宏:
#define SUCCEEDED(hr) ((HRESULT)(hr) >= 0)
Run Code Online (Sandbox Code Playgroud)
绝不是优于安全类型:
inline bool succeeded(int hr) { return hr >= 0; }
Run Code Online (Sandbox Code Playgroud)
但宏确实有它们的位置,请列出您为宏找到的用途,如果没有预处理器,您就无法做到.
请将每个用例放在一个单独的答案中,以便可以进行投票,如果您知道如何在没有预备教授的情况下实现其中一个答案,请指出该答案的评论.
假设我们有一些命名的枚举:
enum MyEnum {
FOO,
BAR = 0x50
};
Run Code Online (Sandbox Code Playgroud)
我搜索的是一个脚本(任何语言),它扫描我项目中的所有标题,并生成一个标题,每个枚举一个函数.
char* enum_to_string(MyEnum t);
Run Code Online (Sandbox Code Playgroud)
以及类似这样的实现:
char* enum_to_string(MyEnum t){
switch(t){
case FOO:
return "FOO";
case BAR:
return "BAR";
default:
return "INVALID ENUM";
}
}
Run Code Online (Sandbox Code Playgroud)
这个问题确实与typedefed枚举和未命名的C风格枚举有关.有人知道这个吗?
编辑:解决方案不应该修改我的源,除了生成的函数.枚举是在API中,因此使用迄今为止提出的解决方案不是一种选择.
我在一些库头文件中有一堆枚举类型,我正在使用,我想有一种方法将枚举值转换为用户字符串 - 反之亦然.
RTTI不会为我做这件事,因为'用户字符串'需要比枚举更具可读性.
一个强力解决方案将是一堆像这样的功能,但我觉得这有点像C样.
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");
}
}
Run Code Online (Sandbox Code Playgroud)
我有一种直觉,认为使用模板有一个优雅的解决方案,但我还不能完全理解它.
更新:感谢您的建议 - 我应该明确说明枚举是在第三方库头中定义的,所以我不想更改它们的定义.
我现在的直觉是避免使用模板并执行以下操作:
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
; …Run Code Online (Sandbox Code Playgroud) 如何让printf显示枚举类型变量的值?例如:
typedef enum {Linux, Apple, Windows} OS_type;
OS_type myOS = Linux;
Run Code Online (Sandbox Code Playgroud)
而我需要的是类似的东西
printenum(OS_type, "My OS is %s", myOS);
Run Code Online (Sandbox Code Playgroud)
必须显示字符串"Linux",而不是整数.
我想,首先我必须创建一个值索引的字符串数组.但我不知道这是否是最美妙的方式.有可能吗?
正如我之前的许多问题所述,我正在通过K&R工作,目前正在进入预处理器.其中一个更有意思的事情 - 我之前从未尝试过的任何学习C的尝试 - 是##预处理器操作员.根据K&R的说法:
预处理器运算符
##提供了一种在宏扩展期间连接实际参数的方法.如果替换文本中##的参数与a相邻,则参数将替换为实际参数,##并删除周围的空白区域,并重新扫描结果.例如,宏paste连接其两个参数:
#define paste(front, back) front ## back所以
paste(name, 1)创建令牌name1.
如何以及为什么有人会在现实世界中使用它?它的使用的实际例子是什么,有什么需要考虑的?
我正在尝试queue使用C 实现一个结构.我的实现非常简单; 队列只能保存ints而不能保留其他内容.我想知道我是否可以模拟C++模板C(可能通过使用预处理器#define),以便我queue可以保存任何数据类型.
注意:我不想用void*.我认为它有点风险,很容易导致奇怪的运行时错误.
我正在读取enum二进制文件中的值,并想检查该值是否真的是enum值的一部分.我该怎么做?
#include <iostream>
enum Abc
{
A = 4,
B = 8,
C = 12
};
int main()
{
int v1 = 4;
Abc v2 = static_cast< Abc >( v1 );
switch ( v2 )
{
case A:
std::cout<<"A"<<std::endl;
break;
case B:
std::cout<<"B"<<std::endl;
break;
case C:
std::cout<<"C"<<std::endl;
break;
default :
std::cout<<"no match found"<<std::endl;
}
}
Run Code Online (Sandbox Code Playgroud)
我是否必须使用switch操作员或有更好的方法吗?
编辑
我设置了枚举值,不幸的是我无法修改它们.更糟糕的是,它们不是连续的(它们的值为0,75,76,80,85,90,95,100等)
我遇到过这种情况很多次......
enum Fruit {
Apple,
Banana,
Pear,
Tomato
};
Run Code Online (Sandbox Code Playgroud)
现在我有了Fruit f; // banana,我想要从f字符串开始"Banana"; 或者我已经string s = "Banana"和我想去了Banana // enum value or int.
到目前为止,我一直这样做..假设枚举在Fruit.h中:
// Fruit.cpp
const char *Fruits[] = {
"Apple",
"Banana",
"Pear",
"Tomato",
NULL
};
Run Code Online (Sandbox Code Playgroud)
显然这是一个混乱的解决方案.如果开发人员在标题中添加了新的水果,并且没有在Fruits []中添加新条目(不能责怪他,他们必须在两个不同的文件中!)应用程序会蓬勃发展.
有没有一种简单的方法可以做我想要的,一切都在一个文件中?预处理器黑客,外星魔法,任何东西......
PS:这与"为了一切"的反思相反,在编译器中实现起来真的很微不足道.看到问题有多常见(至少对我而言)我真的不敢相信没有reflective enum Fruit..甚至在C++ 0x中都没有.
PS2:我正在使用C++,但我也将这个问题标记为C,因为C有同样的问题.如果您的解决方案仅包含C++,那对我来说没问题.