如何处理-Wreturn-type切换C ++ 11枚举类?

时间:2018-11-13 14:01:38

标签: c++ enums gcc-warning

如果我有一个基于切换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枚举类?

2 个答案:

答案 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 ++。当希望通过时,您可以在此类代码中使用它。在此之前,您必须诉诸于前面提到的特定于编译器的解决方案。