C++ 在C+;中的switch语句中未处理所有枚举值时的编译时断言+;
当不是所有可能的枚举值都在switch语句中处理时,我希望得到一个编译器警告或错误。当然,我可以添加一个带有断言的默认案例,并(最终)在运行时得到一个错误。但是我想在编译时得到一个错误 我不确定这是否完全可以用C++,但也许有人知道一个窍门… 编辑: 使用C++ 在C+;中的switch语句中未处理所有枚举值时的编译时断言+;,c++,C++,当不是所有可能的枚举值都在switch语句中处理时,我希望得到一个编译器警告或错误。当然,我可以添加一个带有断言的默认案例,并(最终)在运行时得到一个错误。但是我想在编译时得到一个错误 我不确定这是否完全可以用C++,但也许有人知道一个窍门… 编辑: 使用-Wswitch似乎是GCC的解决方案。VS2010有类似的功能吗?(我没有使用GCC) 编辑2: 好的,我找到了VC++(VS2010)的解决方案: 启用警告C4062会在缺少值且未提供默认情况下生成警告 启用警告C4061会在缺少值时产生警
-Wswitch
似乎是GCC的解决方案。VS2010有类似的功能吗?(我没有使用GCC)
编辑2:
好的,我找到了VC++(VS2010)的解决方案:
启用警告C4062
会在缺少值且未提供默认情况下生成警告
启用警告
C4061
会在缺少值时产生警告,即使提供了默认情况。您没有提到正在使用的编译器。如果您使用的是GCC,只需启用-Wswitch
(由-Wall
自动启用)即可免费获得。如果您使用-Wall
启用所有警告,则g++会自动执行此操作。如果您使用的是g++,使用-Wall
,则您将获得它
例如,这:
enum Abc
{
A =1,
B,
C
};
Abc a = A;
switch( a )
{
case A:
break;
case B:
break;
}
将会引起警告
但是最好在断言失败的情况下使用
default
case,因为当您添加新的枚举值时,您必须更改在该枚举上使用switch的所有文件。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.
。正在尝试解决一个类似的问题,我想详细说明上面的答案
以前的答复:
- 奥利弗·查尔斯沃思
- Bћ
- 托尼克
(9年后,很抱歉,这听起来像是不使用
默认值的原因!您肯定希望编译器帮助您定位enum
位置,而不是掩盖问题?@Oli这取决于您的首选项。如果您喜欢编译器警告,则添加一个enum会迫使您更改所有开关。如果您更喜欢运行时警告,则n你可以专注于小部分代码(分而治之)。@VJo:你应该总是喜欢编译器警告(最好是错误)依赖于运行时警告意味着,在使用每个可能的输入组合运行每个可能的代码路径之前,您无法确保所有内容都已修复;如果编译器会为您发现这一点,那就太可笑了!@Oli问题在于,这会迫使您实现那些丢失的开关。但我想是的你是对的。@VJO:是的,在这种情况下,它确实会迫使你。但是有什么办法呢?要么你需要对新的案例进行特殊处理,要么你不需要(在这种情况下,你应该使用默认值
)。