【问题标题】:enum underlying type vs normal type枚举基础类型与普通类型
【发布时间】:2016-11-30 19:39:31
【问题描述】:

如果我尝试编译下面的代码,它会给我错误'枚举器值对于底层类型'char'来说太大

enum class Status:char{one=126,two=127,three=128};
Status s = Status::three;

但是,如果我执行以下代码,编译器不会给我任何错误,并且会默默地忽略超过 char 上限

char x = 128;

那么,编译器在普通数据类型的情况下不检查并在枚举基础类型的情况下检查范围有什么具体原因。

【问题讨论】:

  • 我猜是为了向后兼容。如果不允许这样做,您可能会觉得将返回的 int 的 API(如 getchar()istream::get())转换为 char 非常烦人。
  • 看起来char 已在您的实现中签名。它的值可能在 -128 到 127 之间。128 会溢出char,但不是格式错误的。请注意,有符号溢出是未定义的行为。不过,我想有一个未定义值的常量是不正确的。
  • 您使用的是哪个编译器? gcc-6.1 说error: enumerator value 128 is outside the range of underlying type ‘char’

标签: c++ c++11 enums


【解决方案1】:

C++11 引入了对“缩小转换”的限制,以及它们在哪里和不允许的地方。隐藏在 5.19§3 中的是一个描述“转换的常量表达式”并明确排除缩小转换的子句,然后指出此类表达式可以在 [...] 枚举器初始化程序中使用。因此,您不能这样做:

enum class Foo : char { one = 128 };
unsigned char uc1 = {-1};

但你可以做到

enum class Foo : char { one = (char)128 };
unsigned char uc1 = -1;

5.19 [expr.const] §3

[...] T 类型的转换常量表达式是一个表达式,隐式转换为 T 类型的纯右值,其中转换后的表达式是核心常量表达式,隐式转换序列仅包含用户定义的转换,左值-torvalue 转换 (4.1)、积分提升 (4.5) 和积分转换 (4.7),而不是缩小转换 (8.5.4)。 [ 注意:此类表达式可用于新表达式 (5.3.4)、case 表达式 (6.4.2)、如果基础类型固定 (7.2) 则用作枚举数初始化器、数组边界 (8.3.4) 以及整数或枚举非类型模板参数 (14.3)。 ——尾注]

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2019-08-29
    • 1970-01-01
    • 2012-03-09
    • 2010-10-25
    • 1970-01-01
    • 2013-01-13
    • 2012-09-15
    相关资源
    最近更新 更多