C ++枚举类:强制转换为不存在的条目 [英] C++ enum class: Cast to non existing entry

查看:104
本文介绍了C ++枚举类:强制转换为不存在的条目的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在一个项目中遇到这种情况,我们有一些套接字通信,主要交换字符以进行流控制.我们将这些字符转换为 enum类:char .我想知道,如果另一端发送的字符不在我们的枚举类中,会发生什么情况.

I have this situation on one Project where we have some socket-communication that mainly exchanges characters for flow-control. We cast those characters to an enum class : char in a switch. I was wondering, what might happen, if the other end sends an character that is not in our enum class.

我有这个mwe:

enum class Foo : char {
    UNKNOWN,
    ENUM1 = 'A',
    ENUM2 = 'B',
    ENUM3 = 'C'
};

char bar1() {
    return 'B';
}

char bar2() {
    return 'D';
}

int main() {
    switch((Foo)bar1()) {
        case Foo::UNKNOWN:std::cout << "UNKNWON" << std::endl;break;
        case Foo::ENUM1:std::cout << "ENUM1" << std::endl;break;
        case Foo::ENUM2:std::cout << "ENUM2" << std::endl;break;
        case Foo::ENUM3:std::cout << "ENUM3" << std::endl;break;
        default:std::cout << "DEFAULT" << std::endl;break;
    }
    switch((Foo)bar2()) {
        case Foo::UNKNOWN:std::cout << "UNKNWON" << std::endl;break;
        case Foo::ENUM1:std::cout << "ENUM1" << std::endl;break;
        case Foo::ENUM2:std::cout << "ENUM2" << std::endl;break;
        case Foo::ENUM3:std::cout << "ENUM3" << std::endl;break;
        default:std::cout << "DEFAULT" << std::endl;break;
    }
    return 0;
}

在此示例中,我有一个 enum类:char ,具有一个未指定的条目和三个由char分配的条目.当我运行它时,我收到的输出是

In this example I have an enum class : char with an unspecified entry and three char-assigned entries. When I run it, the output I receive is

ENUM2
DEFAULT

这似乎可以正常工作,因为未定义的示例只是跳转到默认情况.但是,这是要做的事"吗?有一些我现在可能看不到的陷阱或其他并发症吗?

This seems to work flawlessly since the undefined example just jumps to the default case. However, is this "save to do"? Are there some pitfalls or other complications that I might not see right now?

推荐答案

这是完全安全的,因为:

This is fully safe, because:

  • 您的枚举类是一个有范围的枚举;
  • 您的枚举具有固定的基础类型:char ;
  • 所以您的枚举值是 char 类型的值;
  • 因此,将char值强制转换为枚举是完全有效的.
  • your enum class is a scoped enumeration;
  • your enumeration has a fixed underlying type : char ;
  • so the values of your enumeration are the values of type char ;
  • so the cast of a char value to the enum is completely valid.

以下是与上述语句相对应的C ++ 17标准引号:

Here the C++17 standard quotes that correspond to the above statements:

[dcl.enum]/2:(...)枚举键 enum class enum struct 是语义上等价的;用以下之一声明的枚举类型这是一个作用域枚举,其枚举器的作用域是枚举器.

[dcl.enum]/2: (...) The enum-keys enum class and enum struct are semantically equivalent; an enumeration type declared with one of these is a scoped enumeration, and its enumerators are scoped enumerators.

[dcl.enum]/5:(...)每个枚举都有一个基础类型.这可以使用枚举库显式指定基础类型.(...)在这两种情况下,底层类型都被认为是固定.(...)

[dcl.enum]/5: (...) Each enumeration also has an underlying type. The underlying type can be explicitly specified using an enum-base. (...) In both of these cases, the underlying type is said to be fixed. (...)

[dcl.enum]/8:对于基本类型固定的枚举,枚举的值是基础类型的值.(...)

[dcl.enum]/8: For an enumeration whose underlying type is fixed, the values of the enumeration are the values of the underlying type. (...)

[expr.static.cast]/10 整数或枚举类型的值可以是显式转换为完整的枚举类型.如果枚举类型具有固定的基础类型,值是第一个如有必要,可通过积分转换将其转换为该类型,然后枚举类型.[expr.cast]/4由const_cast,static_cast,static_cast后跟const_cast,reinterpret_cast,reinterpret_cast和const_cast可以是使用显式类型转换的强制转换符号执行.(...)如果转换可以用以下列出的多种方法来解释上面,使用了列表中第一个出现的解释(...)

[expr.static.cast]/10 A value of integral or enumeration type can be explicitly converted to a complete enumeration type. If the enumeration type has a fixed underlying type, the value is first converted to that type by integral conversion, if necessary, and then to the enumeration type. [expr.cast]/4 The conversions performed by a const_cast, a static_cast, a static_cast followed by a const_cast, a reinterpret_cast, a reinterpret_cast followed by a const_cast, can be performed using the cast notation of explicit type conversion. (...) If a conversion can be interpreted in more than one of the ways listed above, the interpretation that appears first in the list is used (...)

如果基础类型不固定,则结论将有所不同.在这种情况下,[dcl.enum]/8的其余部分将适用:它或多或少地表明,如果您不在枚举的最小和最大枚举器之内,则不确定该值是否可以代表.

The conclusions would be different if the underlying type would not be fixed. In this case, the remaining part of [dcl.enum]/8 would apply: it says more or less that if you're not within the smallest and the largest enumerators of the enumeration, you're not sure that the value can be represented.

另请参阅问题是否允许枚举具有未列出的值?,这是更通用的(C ++& C),但不使用作用域枚举或指定的基础类型.

See also the question Is it allowed for an enum to have an unlisted value?, which is more general (C++ & C) but doesn't use a scoped enum nor a specified underlying type.

这里是一个代码片段,用于使用未定义枚举器的枚举值:

And here a code snippet to use the enum values for which there is no enumerator defined:

switch((Foo)bar2()) {
    case Foo::UNKNOWN:          std::cout << "UNKNWON" << std::endl;break;
    case Foo::ENUM1:            std::cout << "ENUM1" << std::endl;break;
    case Foo::ENUM2:            std::cout << "ENUM2" << std::endl;break;
    case Foo::ENUM3:            std::cout << "ENUM3" << std::endl;break;
    case static_cast<Foo>('D'): std::cout << "ENUM-SPECIAL-D" << std::endl;break;
    default:                    std::cout << "DEFAULT" << std::endl;break;
}

这篇关于C ++枚举类:强制转换为不存在的条目的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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