GCC打开枚举,保留缺少警告但使用默认值

时间:2011-03-23 08:52:34

标签: c++ gcc

使用GCC,如果您在switch值上enum并且其中一个枚举缺少case语句,则会发出警告。当您添加default项时,将不再发出警告,这在一般情况下是有意义的。

有没有办法使用default语句,如果不涵盖所有enum值,仍会收到警告?由于我的函数可以处理不纯的输入,我想覆盖一般情况,但仍然会收到关于遗漏枚举情况的编译器警告。

目前我最终在switch语句后分配了一个默认值。

5 个答案:

答案 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-enumpush行之间的pop标记,即使存在default子句,也会显示有关缺少枚举案例的消息。如果您希望在遗失的情况下编译失败,可以将单词warning更改为error

答案 2 :(得分:1)

不幸的是,截至今天,如果您包含enum切换,gcc和llvm都无法检测到您没有比较switchdefault的所有值。

答案 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语句中列出它们中的每一个,即使你只需要检查其中的一些,如果警告应该按照你的建议工作