C++ 在C+;中的switch语句中未处理所有枚举值时的编译时断言+;

C++ 在C+;中的switch语句中未处理所有枚举值时的编译时断言+;,c++,C++,当不是所有可能的枚举值都在switch语句中处理时,我希望得到一个编译器警告或错误。当然,我可以添加一个带有断言的默认案例,并(最终)在运行时得到一个错误。但是我想在编译时得到一个错误 我不确定这是否完全可以用C++,但也许有人知道一个窍门… 编辑: 使用-Wswitch似乎是GCC的解决方案。VS2010有类似的功能吗?(我没有使用GCC) 编辑2: 好的,我找到了VC++(VS2010)的解决方案: 启用警告C4062会在缺少值且未提供默认情况下生成警告 启用警告C4061会在缺少值时产生警

当不是所有可能的枚举值都在switch语句中处理时,我希望得到一个编译器警告或错误。当然,我可以添加一个带有断言的默认案例,并(最终)在运行时得到一个错误。但是我想在编译时得到一个错误

我不确定这是否完全可以用C++,但也许有人知道一个窍门…

编辑: 使用
-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.

正在尝试解决一个类似的问题,我想详细说明上面的答案 以前的答复:

  • 奥利弗·查尔斯沃思
  • 托尼克

(9年后,很抱歉,这听起来像是不使用
默认值的原因!您肯定希望编译器帮助您定位
enum
位置,而不是掩盖问题?@Oli这取决于您的首选项。如果您喜欢编译器警告,则添加一个enum会迫使您更改所有开关。如果您更喜欢运行时警告,则n你可以专注于小部分代码(分而治之)。@VJo:你应该总是喜欢编译器警告(最好是错误)依赖于运行时警告意味着,在使用每个可能的输入组合运行每个可能的代码路径之前,您无法确保所有内容都已修复;如果编译器会为您发现这一点,那就太可笑了!@Oli问题在于,这会迫使您实现那些丢失的开关。但我想是的你是对的。@VJO:是的,在这种情况下,它确实会迫使你。但是有什么办法呢?要么你需要对新的案例进行特殊处理,要么你不需要(在这种情况下,你应该使用
默认值
)。