开关可能掉线(可能不会掉线)

Ayx*_*xan 4 c++ gcc qt-creator

在GCC 7上,我已在Qt creator 4.9上启用了大多数警告。现在,我有一个switch语句,它涵盖了所有枚举值。如果添加,default:我会收到警告(来自Qt创建者):

warning: default label in switch which covers all enumeration values
Run Code Online (Sandbox Code Playgroud)

如果我删除,default:则会收到另一个警告(来自GCC):

error: this statement may fall through [-Werror=implicit-fallthrough=]  
       }  
       ^

error: all warnings being treated as errors
Run Code Online (Sandbox Code Playgroud)

我应该做些什么?关闭警告?它们很有用,我不想关闭它们中的任何一个,但是Wimplicit-fallthrough似乎有问题。

[[fallthrough]]无济于事,因为cases以a结尾return(从Qt创建者那里):

warning: fallthrough annotation in unreachable code
Run Code Online (Sandbox Code Playgroud)

__attribute__ ((fallthrough))也没做任何事 /* FALLTHRU */[[gnu::fallthrough]]或都没有// fall through。大概是因为-pedantic

例:

enum class E {a, b, c};

QVariant fun(E e) {
     switch (e) {
        case a: return "something";
        case b: return "something_else";
        case c: return "something_different";
        // default: return QVariant{};
        // Do I add a default:? What do I add here?
    }
}
Run Code Online (Sandbox Code Playgroud)

希望的事情我已经试过表明,我的问题不是一个重复的这个或其他类似的问题,因为他们不解决我的问题。

Mil*_*nek 7

考虑一下fun(static_cast<E>(42))。这是一个定义明确的转换,但是问题中的函数将不返回而到达末尾,并且程序的行为将不确定。这就是为什么GCC警告控制可能到达非空函数的末尾的原因。

那么,为什么不添加一个default案例呢?考虑一下,如果有人返回并向其中添加另一个常量E,却忘记更新,会发生什么情况fun。没有default,GCC会帮助您警告该开关不能处理所有E的常量。如果添加一个default案例,则说明您已经取消了非常有用的保护措施。

那么,Right Thing TM应该做什么?在函数的末尾,返回您的默认值(或throw调用abort()崩溃,视情况而定)switch

enum class E {a, b, c};

QVariant fun(E e) {
     switch (e) {
        case E::a: return "something";
        case E::b: return "something_else";
        case E::c: return "something_different";
    }
    return "some_default"; // or throw or abort()
}
Run Code Online (Sandbox Code Playgroud)

这使您两全其美。如果有人传递的值不是预定义的枚举器常量之一,它将以明确定义的方式运行。如果有人向其中添加新常量E而忘记更新,fun则编译器仍会发出警告。

为了进一步讨论,Jason Turner在他的CppCon 2018演讲中涵盖了这个主题(值得一提)。