如何使用 C++ enum+switch 语句进行详尽的编码

问题描述 投票:0回答:1

问题:

当我没有为类型的每个可能值包含分支时,如何让编译器警告我?当我使用稍后可能获得值的类型(

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/ 以及其中链接的演讲。

c++ compiler-errors algebraic-data-types
1个回答
0
投票

如果您不想启用所有警告(在某些项目中,可能需要处理不切实际的警告) 您可以具体添加:

#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;
    })
}

以下代码将无法编译

© www.soinside.com 2019 - 2024. All rights reserved.