如果我有一个基于切换enum class
而返回的函数,则gcc发出warning: control reaches end of non-void function [-Wreturn-type]
。示例代码:
enum class Test { a, b, c } ;
int foo(Test test) {
switch (test) {
case Test::a: return 0;
case Test::b: return 1;
case Test::c: return 2;
}
}
我想到了两种解决方案,但似乎都不正确:
1)具有抛出的默认情况。但是,当我向enum class
添加其他成员时,我不再收到错过案件的错误。
2)用一个实用语抑制警告,但是我不防备有人通过static_cast<Test>(123)
。
所以我的问题是,如何处理-Wreturn-type错误以切换C ++ 11枚举类?
答案 0 :(得分:2)
通常,我会在开关之后放置 ,无论是throw something()
还是return -1
。您需要确保在运行时,无论发生什么情况,对该函数的调用至少都是安全的。您的编译器会告诉您更多信息。
示例:
enum class Test { a, b, c } ;
int foo(Test test) {
switch (test) {
case Test::a: return 0;
case Test::b: return 1;
case Test::c: return 2;
}
throw std::runtime_error("Unhandled Test enumerator " + std::to_string((int)test) + " in foo()");
}
理想情况下,您的客户永远不会看到此问题,但是,如果他们这样做了(通过顶级catch
-您拥有一个,对吗?),您会立即知道问题所在并可以解决。 / p>
另外(但不是唯一),我将考虑放置诸如assert
(或项目特定的等效项)之类的调试声明,以便在开发过程中检测到此错误。 (不过,在上面带有try
的示例中,这实际上将阻止生成有用的错误消息,因此并不总是合适的。)
此外,如果您打开-Werror
却没有向switch
添加项目,则您的项目将无法生成,因此从源头上解决了问题。
通常,不要忽略或尝试抑制警告:请注意!
答案 1 :(得分:1)
注意:编写此答案时要牢记性能(如果您不需要它,请忽略此问题,并在切换后放置一些致命错误)。
我建议使用特定于编译器的功能来标记无法访问代码。所有主要的编译器都有这样的东西。例如,GCC / Clang / icc具有__builtin_unreachable
,MSVC具有__assume(false)
。
在发布模式下使用这些工具。在调试模式下,在其中放置一些致命错误(断言,异常等)。这样,在开发过程中,您会发现错误,而在发布模式下,生成的代码将非常有效。
请注意,有一个proposal,打算将std::unreachable()
添加到C ++。当希望通过时,您可以在此类代码中使用它。在此之前,您必须诉诸于前面提到的特定于编译器的解决方案。