打开枚举时编译器警告
enum ENUM(Option1,Option2,Option3);
string func(ENUM x)
{
switch(x)
{
case Option1: return "Option1";
case Option2: return "Option2";
case Option3: return "Option3";
}
}
这可以编译并工作,但会向编译器发出警告,表明并非所有控制路径都会返回。然而,如果你正确使用枚举,情况不是这样吗?如果添加另一个 ENUM val,我希望编译失败,但只要涵盖所有情况,我希望它编译时不产生警告。
这是编译器防止错误的强制转换值吗?它只是 C++ 的一部分并且需要忍受吗?
enum ENUM(Option1,Option2,Option3);
string func(ENUM x)
{
switch(x)
{
case Option1: return "Option1";
case Option2: return "Option2";
case Option3: return "Option3";
}
}
This compiles and works but gives a compiler warning that not all control paths return. However isn't the point that if you use enums properly, this isn't the case? If another ENUM val is added, I want compilation to fail but as long as all cases are covered I want it to compile warning-free.
Is this the compiler protecting against bad casted values, is it just part of C++ and needs to be lived with?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
在 C++ 中,枚举并不安全。您不能期望枚举值是枚举声明中定义的值之一:
int
获得不正确的static_cast
因此,即使您覆盖了枚举的所有元素,编译器也不能期望开关返回。然而,从功能上来说,这确实是一个错误条件。
有两种反应方法:
enum
中添加一个default
情况为了明智地选择,请记住编译器可能(如果您要求它) ) 在没有
default
语句的情况下,只要switch
未涵盖enum
的所有情况,就会触发警告。智能编译器(即 Clang)允许将警告单独映射到错误,这极大地帮助捕获这些错误。因此,您需要做出决定:
default
default
最后,您必须决定如何反应,请注意使用运行时错误与使用默认语句不一致(最好尽可能在编译时捕获错误):
我个人最喜欢的是
UNREACHABLE(Text_)
宏,它会在调试中引发内存转储(以便我获得完整的跟踪)并记录错误并在发布中抛出(以便服务器停止处理此请求,但不会完全停止响应)。这给出了这样的代码:
In C++, enums are not safe. You cannot expect an enum value to be one of the values defined in the enum declaration:
static_cast
from aint
Therefore, the compiler cannot expect the switch to return, even if you cover all elements of your enum. However, it is truly an error condition, functionally speaking.
There are two ways to react:
default
case to yourenum
In order to choose wisely, remember that the compiler may (if you ask it) trigger a warning whenever a
switch
does not cover all the cases of anenum
, at the condition that there is nodefault
statement. Smart compilers (ie Clang) allow to map warnings to errors individually, which greatly help catching those bugs.Therefore, you have a decision to take:
default
default
Finally, you have to decide how to react, noting that using a runtime error is inconsistent with using a default statement (it's best to catch errors at compile-time whenever possible):
My personal fav is a
UNREACHABLE(Text_)
macro, which provokes a memory dump in Debug (so that I get a full trace) and log an error and throw in Release (so that the server stops processing this request, but does not stop responding altogether).This gives code like such:
从编译器的角度来看,枚举的类型是整数,因此 x 的值仍然有可能是其他情况之一。
通常,我会添加一个
default:
标签来触发内部错误。提示:如果将内部错误调用包装在无限循环中,则不必发明虚假的返回值。例如:
From the compilers point of view, the type of the enum is an integer, so it's still possible that the value of
x
is one of the other cases.Normally, I would add a
default:
label that triggers an internal error.Hint: If you wrap the call the the intern error in an infinite loop, you don't have to invent a bogus return value. For example:
如果由于某种原因
x
既不是Option1
、Option2
也不是Option3
,会发生什么情况?当然,您可能会说这永远不会发生,但由于该方法必须返回某些内容,因此您有两个选择:
在末尾添加一个
return string("");
。>
向返回
string("")
的switch
添加一个default
。正如 CodeGray 指出的那样,第二种选择可以说是更好的风格。您还可以返回空字符串以外的其他内容。
What happens if for some reason
x
is neitherOption1
, norOption2
, norOption3
?Sure, you could argue that will never happen, but since the method has to return something, you have two options:
add a
return string("");
at the end.add a
default
to theswitch
that returnsstring("")
.As CodeGray points out, the second option is arguably better style. You could also return something other than an empty string.