非固定类型的枚举范围定义的动机 [英] Motivation of the enumeration range definition with non-fixed type

查看:111
本文介绍了非固定类型的枚举范围定义的动机的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

以下一段文字来自 C ++ 14 N4296工作草稿7.2 / 8 [dcl.enum]


对于其底层类型是固定的枚举,
枚举的值是底层类型的值。否则,对于
枚举,其中 emin 是最小的枚举器, emax
最大,枚举的值是在范围
bmin到b max中的值,定义如下:对于二的补码
表示,使 K 为1对于一个补码或符号幅度的
表示为0。 b max是大于或等于
max(| emin | -K,| emax |)且等于 2M- 1 ,其中M是非负数
整数。如果 emin 是非负数并且 - (bmax + K),则 bmin code>
否则。


让我们通过例子来考虑它是如何工作的。以下声明的枚举类型是非固定的:

 枚举E {x = -2,y = 2} 

假设实现定义签名的量值 c $ c> K = 0 。现在 emin = -2,emax = 2 bmax = 2 ^ 2 -1 = 3 bmin = 2 。因此,枚举值的范围是从2到3.这是什么意思?这个时间间隔应该告诉我们什么?我们不能将间隔中的值分配给枚举类型的变量。观看:

  #include< iostream> 

枚举A {x = -2,y = 2};

A a = 2; //无法初始化类型为'int'的类型为'A'的变量
A b = 3; //无法初始化类型为'int'的类型为'A'的变量

int main(){}

DEMO

解决方案

您的范围不正确


<如果emin是非负的,则p> bmin为零,而 - (bmax + K)则为


bmax = 3(即2 2 -1),因此bmin = - (3 + 0)或-3

这是什么意思?


脚注96通知您:



< blockquote>

96)这组值用于定义枚举类型的提升和转换语义。它不排除枚举类型的表达式具有落在该范围之外的值。


由于枚举的基本类型总是积分,范围也隐含地限制任何给定枚举(在这种情况下为7,但是当值超出此范围时会发生什么)的可用不同值的数量。



此公式会产生最小的类型,可容纳每个被选为基础类型的值。它还允许枚举的值小于其底层类型的范围打包成位字段。


我们不能将间隔中的值赋给枚举类型的变量


/ p>

  A a = static_cast< A>(2) 

如果你在枚举范围外投一个整数,那么你最终会得到一个未指定的但有效)值



[expr.static.cast]


可以将积分或枚举类型的值显式转换为枚举类型。如果原始值在枚举值(7.2)的范围内,则值不变。 [...]


缺陷 1766 已将此功能强化为未来版本的标准


10整数或枚举类型的值可以显式转换为完整的枚举类型。如果原始值在枚举值(7.2)的范围内,则值不变。否则,行为是未定义的。 [...]


无论如何,你几乎总是不应该将整数转换为枚举。


The following piece of text is from the C++14 N4296 working draft 7.2/8 [dcl.enum]:

For an enumeration whose underlying type is fixed, the values of the enumeration are the values of the underlying type. Otherwise, for an enumeration where emin is the smallest enumerator and emax is the largest, the values of the enumeration are the values in the range bmin to bmax, defined as follows: Let K be 1 for a two’s complement representation and 0 for a one’s complement or sign-magnitude representation. bmax is the smallest value greater than or equal to max(|emin| − K, |emax|) and equal to 2M − 1, where M is a non-negative integer. bmin is zero if emin is non-negative and −(bmax + K) otherwise.

Let's consider how it works by example. The enum declared below has non-fixed underlying type:

enum E { x = -2, y = 2 }

Assume that implementation defines signed magnitude representation, therfore K = 0. Now emin = -2, emax = 2 and bmax = 2^2 -1 = 3, bmin = 2. Therefore values of the enumeration are from range from 2 to 3. What does that mean? What should that interval tell us about? We can't assign a value from the interval to a variable of the enumeration type. Watch:

#include <iostream>

enum A { x = -2, y = 2 };

A a = 2; // cannot initialize a variable of type 'A' with an rvalue of type 'int'
A b = 3; // cannot initialize a variable of type 'A' with an rvalue of type 'int'

int main(){ }

DEMO

解决方案

Your range is incorrect

bmin is zero if emin is non-negative and −(bmax + K) otherwise.

bmax = 3 (i.e. 22 -1), therefore bmin = -(3 + 0) or -3

What does that mean? What should that interval tell us about?

As footnote 96 informs you:

96) This set of values is used to define promotion and conversion semantics for the enumeration type. It does not preclude an expression of enumeration type from having a value that falls outside this range.

Since the underlying type of enums is always integral, the range also implicitly limits the number of usable distinct values for any given enum (in this case 7, but see below for what happens when values are outside this range).

This formula results in the smallest possible type that can hold every value being selected as the underlying type. It also allows values of an enum with a range shorter than its underlying type to be packed into bitfields.

We can't assign a value from the interval to a variable of the enumeration type

Yes you can

A a = static_cast<A>(2);

If you cast an integer outside the enum's range however you will end up with an unspecified (i.e. worthless, but valid) value

[expr.static.cast]

10 A value of integral or enumeration type can be explicitly converted to an enumeration type. The value is unchanged if the original value is within the range of the enumeration values (7.2). Otherwise, the resulting value is unspecified (and might not be in that range).[...]

Defect 1766 has strengthened this to undefined behaviour in the next version of the standard

10 A value of integral or enumeration type can be explicitly converted to a complete enumeration type. The value is unchanged if the original value is within the range of the enumeration values (7.2). Otherwise, the behavior is undefined. [...]

Either way you almost always shouldn't be casting integers to enums in the first place.

这篇关于非固定类型的枚举范围定义的动机的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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