当我没有为类型的每个可能值包含分支时,如何让编译器警告我?当我使用稍后可能获得值的类型(
std::variant
或enum
)进行编码时,这一点尤其重要。
这是我正在使用的代码(试图使其工作):
enum MyEnum {
ECHAD
,SHTAYIM
// ,SHALOSH
};
int main() {
MyEnum x = ECHAD;
switch (x) {
case ECHAD:
std::cout << "One" << std::endl;
break;
case SHTAYIM:
std::cout << "Two" << std::endl;
break;
default:
static_assert(false, "You haven't handled every possible value of MyEnum");
}
}
这是一个带有以下代码的 Godbolt:https://godbolt.org/z/Kn76q8naq
在我的心智模型中,这应该可以编译。因为
MyEnum
的所有可能值都已被考虑在内。所以 default
分支不需要编译。也就是说,直到 SHALOSH
添加到枚举中。然后编译器应该跳进来并向我指出这一点。
详尽性检查是一种重构工具。每当您扩展类型的可能性时,编译器都会向您指出您忘记处理刚刚创建的新案例的位置
如需更完整的解释,请参阅此博文:https://blog.janestreet.com/what-do-haskellers-have-against-exhaustiveness/ 以及其中链接的演讲。
如果您不想启用所有警告(在某些项目中,可能需要处理不切实际的警告) 您可以具体添加:
#pragma GCC diagnostic push
#pragma GCC diagnostic error "-Wswitch-enum"
// Your switch statement here
#pragma GCC diagnostic pop
或者如果您不想在每个地方都使用它,您可以定义如下内容:
#define switch_all_cases(expression, scoped_switch) \
_Pragma("GCC diagnostic push") \
_Pragma("GCC diagnostic error \"-Wswitch-enum\"") \
switch(expression) scoped_switch \
_Pragma("GCC diagnostic pop") \
并使用它:
int main() {
MyEnum x = ECHAD;
switch_all_cases(x, {
case ECHAD:
std::cout << "One" << std::endl;
break;
case SHTAYIM:
std::cout << "Two" << std::endl;
break;
})
}
以下代码将无法编译