C ++枚举类:强制转换为不存在的条目 [英] C++ enum class: Cast to non existing entry
问题描述
我在一个项目中遇到这种情况,我们有一些套接字通信,主要交换字符以进行流控制.我们将这些字符转换为 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
andenum 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屋!