使用GCC,如果您在switch
值上enum
并且其中一个枚举缺少case
语句,则会发出警告。当您添加default
项时,将不再发出警告,这在一般情况下是有意义的。
有没有办法使用default
语句,如果不涵盖所有enum
值,仍会收到警告?由于我的函数可以处理不纯的输入,我想覆盖一般情况,但仍然会收到关于遗漏枚举情况的编译器警告。
目前我最终在switch语句后分配了一个默认值。
答案 0 :(得分:10)
-Wswitch-enum,但不幸的是,只有最新版本支持此功能。
(你当然可以通过在交换机外部使用goto并省略默认值来模拟你想要的行为,但我强烈建议不要这样做,它很难看,其他人阅读你的代码会有WTF经验。)< / p>
答案 1 :(得分:3)
在阅读“DavidRodríguez - dribeas”中的链接后,我认为总结那里列出的选项会很有帮助。
有两种方法可以执行此操作 - 为所有switch
语句打开有关缺少枚举案例的消息,然后针对您不关心的语句禁用它,或将其保留为默认值并强制执行你真正关心的那些switch
陈述的错误。
选项1:警告所有人,将某些人标记为无声
首先,将-Wswitch-enum
添加到编译器标志中,以便所有switch
语句(即使具有default
子句的语句都会在未处理枚举的情况下生成警告。
然后,对于那些希望switch
案例处理事情并且不希望看到警告的default
语句,请像这样包装switch
语句:
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wswitch-enum"
switch () {
...
}
#pragma GCC diagnostic pop
这将暂时禁用-Wswitch-enum
标志(隐藏有关缺少枚举案例的警告),仅针对该案例陈述。
选项2:仅在标记时发出警告
由于默认GCC行为是在存在default
子句时隐藏警告,因此不需要为此选项更改编译器标志。
相反,对于那些包含switch
子句的default
语句,但您仍希望看到有关枚举枚举的警告,请将switch
包裹起来:
#pragma GCC diagnostic push
#pragma GCC diagnostic warning "-Wswitch-enum"
switch () {
...
}
#pragma GCC diagnostic pop
这会临时启用-Wswitch-enum
和push
行之间的pop
标记,即使存在default
子句,也会显示有关缺少枚举案例的消息。如果您希望在遗失的情况下编译失败,可以将单词warning
更改为error
。
答案 2 :(得分:1)
不幸的是,截至今天,如果您包含enum
切换,gcc和llvm都无法检测到您没有比较switch
中default
的所有值。
答案 3 :(得分:1)
我会说问题更多的是enum
级别。
我的意思是你应该首先验证你的输入(即确保它确实映射到一个真正的枚举)并且只有一次验证,如果你使用枚举,在这种情况下,默认值变得多余。
为了验证输入,我使用的简单解决方案是通过宏创建枚举,该宏也将自动生成转换函数:from / to {{ 1}},来自string
(或其他)。
例如:
int
可以生成:
DEFINE_ENUM_DETAILED(SomeEnum, int, (Foo, 0, "Foo")(Bar, 1, "Bar"));
这是我发现生成轻松的唯一方法(尽管这里的字符串转换有点简化)。
另一种解决方案是使用脚本从备用文件生成源代码。
编辑:让交换机运行并验证
简单的答案是(就像我上面所做的那样)让程序流出交换机而不是使用默认子句。如果正常流量(落入struct SomeEnum {
enum { Foo = 0, Bar = 1 } type;
type FromString(std::string const& s) {
if (s == "Foo") { return Foo; }
if (s == "Bar") { return Bar; }
assert(0 && "SomeEnum::FromString - unknown value");
}
std::string ToString(type e) {
switch(e) {
case Foo: return "Foo";
case Bar: return "Bar";
}
}
type FromIntegral(int i) {
switch(i) {
case Foo: return Foo;
case Bar: return Bar;
}
assert(0 && "SomeEnum::FromIntegral- unknown value");
}
};
时)不会从开关中掉出来,则可以这样做。
case
答案 4 :(得分:0)
一个原因是您必须能够编写无警告代码而不会背弃。例如,如果你有一个包含100个常量的枚举,那么你必须在每个switch语句中列出它们中的每一个,即使你只需要检查其中的一些,如果警告应该按照你的建议工作