开关可能掉线(不可以) [英] switch may fall through (no it may not)

查看:260
本文介绍了开关可能掉线(不可以)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

On GCC 7 I have enabled most of all warnings on Qt creator 4.9. Now I have a switch statement which covers all enumeration values. If I add a default: I get a warning (from Qt creator):

warning: default label in switch which covers all enumeration values

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

If I remove the default: I get another warning (from GCC):

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

error: all warnings being treated as errors

我该怎么办?关闭警告?它们很有用,我不想关闭其中任何一个,但是Wimplicit-fallthrough似乎有问题.

What am I supposed to do? Turn off warnings? They are useful, I don't want to turn off any of them, but Wimplicit-fallthrough seems to be faulty.

[[fallthrough]]并没有帮助,因为case的结尾是return,因此我得到了(来自Qt创建者):

[[fallthrough]] doesn't help because the cases end with a return thus I get (from Qt creator):

warning: fallthrough annotation in unreachable code

__attribute__ ((fallthrough))也不执行任何操作. /* FALLTHRU */[[gnu::fallthrough]]// fall through都没有.大概是因为-pedantic吗?

__attribute__ ((fallthrough)) didn't do anything either. Neither did /* FALLTHRU */ or [[gnu::fallthrough]] or // fall through. Presumably because of -pedantic?

示例:

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";
        // default: return QVariant{};
        // Do I add a default:? What do I add here?
    }
}

希望我尝试过的事情表明我的问题不是

Hopefully the things I've tried shows that my question is not a duplicate of this or this or other similar questions because they don't solve my problem.

推荐答案

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

Consider fun(static_cast<E>(42)). This is a perfectly well-defined conversion, but the function from your question will reach the end without returning, and your program's behavior will be undefined. That's why GCC warns that control may reach the end of a non-void function.

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

So why not add a default case? Consider what happens if someone goes back and adds another constant to E, but forgets to update fun. Without a default, GCC will helpfully warn you that the switch doesn't handle all of E's constants. If you add a default case, you've defeated that very helpful protection.

那正确的事情 TM 是做什么的?在函数结尾,在switch之后,返回默认值(或throw或调用abort()进行崩溃,视情况而定):

So what's the Right ThingTM to do? Return your default value (or throw or call abort() to crash, as appropriate) at the end of the function, after the 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()
}

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

This gives you the best of both worlds. If someone passes a value that isn't one of the pre-defined enumerator constants, it will behave in a well-defined way. If someone adds a new constant to E and forgets to update fun then the compiler will still issue a warning.

为了进一步讨论,Jason Turner在他的 CppCon 2018演讲中 ,这值得一看.

For further discussion, Jason Turner covered this topic (among others) in his CppCon 2018 talk, which is worth a watch.

这篇关于开关可能掉线(不可以)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆