将枚举类型转换为int比将枚举类型转换为无符号整数更好,这是为什么?

7
在下面的代码中,重载的f(int)被选择而不是f(unsigned)。在clang 3.0和gcc 4.8测试通过。
enum E
{
};

E f(int);
int f(unsigned);

E e = f(E(0));

我的理解是,enum -> intenum -> unsigned都是标准的转换序列,它们只包含整数转换。根据[conv.integral],枚举类型的rvalue可以转换为整数类型的rvalue。根据[over.best.ics],仅包含整数转换的标准转换序列的等级为“Conversion”。根据[over.ics.rank],除非适用以下规则之一,否则无法区分两个相同形式的隐式转换序列:[...]。在比较这两个标准转换序列时,似乎没有适用的规则。我错过了什么吗?

你必须使用 std::underlying_type 来确定枚举的基础类型。 - Kerrek SB
积分提升。它实际上不是积分转换;请参见[conv.prom]。 - dyp
枚举(7.2)不是整数;然而,可以将枚举提升为int、unsigned int、long或unsigned long,如4.5中所指定的那样。但是,C++03的4.5没有提到枚举! - willj
请记住,枚举可以是负数和正数; enum {Val1 = -1};,因此将其转换为int更自然。 - Steztric
1
@Steztric:接近了,但不完全正确。每个“枚举”都是一个独立的类型,并且转换规则因范围而异。由于原始示例“enum E”没有负数,因此它受到与您的示例不同的规则约束。 - MSalters
显示剩余2条评论
1个回答

6

C++11:

[conv.prom]/3

一个未作用域限定的枚举类型的prvalue,其底层类型不是固定的(7.2),可以转换为以下第一个类型的prvalue,该类型可以表示枚举中的所有值(即在7.2中描述的b min到b max范围内的值):intunsigned intlong intunsigned long intlong long intunsigned long long int

(强调是我的)

然后,[over.ics.rank]/4:

标准转换序列按其等级排序:精确匹配比提升更好,提升比转换更好。

因此,在表达式f(E(0))的重载解析中,重载E f(int);仅需要整数提升(从Eint,通过[conv.prom]),其等级高于int f(unsigned);所需的整数转换(从Eunsigned通过[conv.integral])。


对于C++03,论据相同,尽管第一段引文略有不同: [conv.prom]/2

类型为wchar_t(3.9.1)或枚举类型(7.2)的rvalue可以转换为以下第一个类型的rvalue,该类型可以表示其底层类型的所有值:intunsigned intlongunsigned long

[over.ics.rank]/4相同。


据我所知,积分提升并不是一个广为人知的功能。 - dyp
2
@willj 这也有点违反直觉,例如char会转换成int而不是unsigned char(或者short)进行重载决议,原因相同。 - dyp

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接