简体   繁体   English

如何切换枚举 class?

[英]How do I switch over an enum class?

Enum classes are supposed to be strong enums in the sense that they don't implicitly convert to and from int .枚举类应该是强枚举,因为它们不会隐式转换为 int 或从int转换。 For instance:例如:

enum class EC { a, b };

However, when switching over such a "strong enum":但是,当切换这样一个“强枚举”时:

int sw(EC ec) {
  switch (ec) {
    case EC::a: return 0;
    case EC::b: return 1;
  }
}

gcc -Wreturn-type -wants me to add a default clause to the switch even though all legal enum values are covered: gcc -Wreturn-type希望我在开关中添加一个default子句,即使涵盖了所有合法的枚举值:

warning: control reaches end of non-void function [-Wreturn-type]

In an old (non-class) enum, this makes sense, because any int could have been accidentally converted to EC .在旧的(非类)枚举中,这是有道理的,因为任何int都可能被意外转换为EC But I had (apparently wrongly) assumed that assigning an invalid enum member to an enum class was UB.但是我(显然错误地)假设将无效的枚举成员分配给枚举 class 是 UB。

How can I use truly strong enum classes where the compiler realises that functions like sw cover all possible paths?在编译器意识到像sw这样的函数涵盖所有可能的路径的情况下,如何使用真正强大的枚举类? Of course I could just add a default: branch that I know will never be triggered, but I want to make sure that adding more members to EC in the future will trigger a warning in the switch .当然,我可以添加一个我知道永远不会触发的default:分支,但我想确保将来向EC添加更多成员在 switch 中触发警告

You can return a dummy variable, to remove the "control reaches end of non-void function".您可以返回一个虚拟变量,以删除“控制到达非无效函数的结尾”。 This way, the warning is removed, and any additions to the enum-class will still trigger a warning in the switch statement:这样,警告就被删除了,对 enum-class 的任何添加仍然会在 switch 语句中触发警告:

int sw(EC ec) {
  switch (ec) {
    case EC::a: return 0;
    case EC::b: return 1;
  }

  return 0; //dummy variable
}

"control reaches end of non-void function" is quite different from common "enumeration value 'c' not handled in switch [-Wswitch]" warning. “控制到达非无效函数的结尾”与常见的“枚举值'c'未在开关 [-Wswitch] 中处理”警告完全不同。 I think compiler is being a bit too cautious here, but this warning may turn out to be handy because it will prevent potential future UB caused by modification of enum and ignoring of -Wswitch warning.我认为编译器在这里有点过于谨慎,但这个警告可能会变得很方便,因为它可以防止由于修改enum和忽略-Wswitch警告而导致的潜在未来 UB。

Rewriting this snippet like this would make code future proof:像这样重写此代码段将使代码面向未来:

online compiler在线编译器

enum class EC { a, b /*,c */ };

int sw(EC ec) {
    int result{};
  switch (ec) { // warning: enumeration value 'c' not handled in switch [-Wswitch]
    case EC::a: result = 0; break;
    case EC::b: result = 1; break;
  }
  return result; // control flow will always leave function properly
}

A enum variable - both old-school one and enum class can hold values that are not one of the members of the enumeration. enum变量 - 老式变量和enum class都可以保存不是枚举成员之一的值。 As long as the integer value fits within the underlying type (with a few more restrictions), it is valid to store it in the enumeration type.只要 integer 值符合基础类型(还有一些限制),就可以将其存储在枚举类型中。

This worked for me:这对我有用:

enum class EC {a, b, c};
int sw (EC ec)
{
    int rc;
    switch (ec)
    {
        case EC::a:
        rc = 0;
        break;
    case EC::b:
        rc = 1;
        break;
    }
    return rc;
}

In GCC/Clang/ICC you can silence this warning with __builtin_unreachable() :在 GCC/Clang/ICC 中,您可以使用__builtin_unreachable()此警告:

int sw(EC ec) {
    switch (ec) {
        case EC::a: return 0;
        case EC::b: return 1;
    }

    assert(false);
    __builtin_unreachable();
}

In MSVC __assume(0) can be used.在 MSVC 中可以使用__assume(0)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM