当不是在switch语句中处理所有可能的枚举值时,我想得到编译器警告或错误。 当然,我可以添加一个带有断言的默认情况,并且(最终)在运行时获得错误。 但是我想在编译时遇到错误。
我不确定这是否可能与C ++有关,但也许有人知道一个技巧......
编辑:
使用-Wswitch似乎是GCC的解决方案。 VS2010有类似的东西吗? (我没有使用GCC)。
EDIT2:
好的,我找到了VC ++(VS2010)的解决方案:
启用警告C4062会在缺少值时发出警告,并且不提供默认情况。
即使提供了默认情况,启用警告C4061也会在缺少值时发出警告。
哪个编译器?
您还没有提到您正在使用的编译器。如果您正在使用GCC,只需启用-Wswitch(由-Wall自动启用)即可免费获得。
AFAIK没有传统的方法来实现你想要的MSVC。有类似的事情,但它们涉及复杂的模板伏都教或真正凶猛的宏谜语。
例如,不要以常规方式定义枚举,而是执行以下操作:
#define MyEnumEntries(m) \
m(A, 1) \
m(B, 2) \
m(C, 3) \
enum Abc {
// the following will expand into your enum values definitions
# define M_Decl(name, value) name = value,
MyEnumEntries(M_Decl)
};
现在,您的交换机可以重写为:
Abc a = A;
switch( a )
{
#define M_Goto(name, value) \
case value:
goto label_##name;
MyEnumEntries(M_Goto)
case label_A:
// TODO
break;
case label_B:
// TODO
break;
}
如果您不为所有枚举值添加开关条目label_...,则上述将无法编译。
如果您使用g ++,使用-Wall,那么您将获得它。
例如,这个:
enum Abc
{
A =1,
B,
C
};
Abc a = A;
switch( a )
{
case A:
break;
case B:
break;
}
会引起警告。
但最好使用default断言失败的情况,因为当你添加一个新的枚举值时,你必须改变你在这个枚举上使用开关的所有文件。
这听起来像是不使用default的理由!当然,您希望编译器帮助您找到enum位置,而不是掩盖问题?
@Oli这取决于你的喜好。如果您喜欢编译器警告,那么添加一个枚举会强制您更改所有开关。如果你喜欢运行时警告,那么你可以专注于小块代码(分而治之)。
@VJo:你应该总是更喜欢编译器警告(理想情况下是错误)。依赖于运行时警告意味着在使用每个可能的输入组合运行每个可能的代码路径之前,您无法确定所有内容是否已修复;如果编译器会轻易地为你发现这个,这是荒谬的!
@Oli问题是这迫使你实现那些丢失的开关。但我猜你是对的。
@VJO:是的,在这种情况下,它会强迫你。但是替代方案是什么?您需要对新案例进行特殊处理,或者不需要特殊处理(在这种情况下,您应该使用default)。
@Oli替代方法是默认的:)如果您使用依赖于新枚举的功能,操作将失败并显示相应的消息(日志或屏幕)。这样就可以解决问题(如果你有几个地方需要改变,可能会分配更多的人。
如果您使用-Wall启用所有警告,g ++会自动执行此操作。