C++ 初级枚举和隐式转换

C++ primer enums and implicit conversion

你好,我从 C++ 入门第 5 版中得到了这个:

// unscoped enumeration; the underlying type is machine dependent

enum Tokens {INLINE = 128, VIRTUAL = 129};

void newf(unsigned char);

void newf(int);

unsigned char uc = VIRTUAL;

newf(VIRTUAL); // calls newf(int)

newf(uc); // calls newf(unsigned char)

The enum Tokens has only two enumerators, the larger of which has the value 129. That value can be represented by the type unsigned char, and many compilers will use unsigned char as the underlying type for Tokens. Regardless of its underlying type, objects and the enumerators of Tokens are promoted to int. Enumerators and values of an enum type are not promoted to unsigned char, even if the values of the enumerators would fit.

因此,正如您所看到的,枚举器值 tue 未提升为 int,我得到的版本是 foo(unsigned char) 而不是 foo(int)

来自 cppreference 对 enums 的描述:

Values of unscoped enumeration type are implicitly-convertible to integral types. If the underlying type is not fixed, the value is convertible to the first type from the following list able to hold their entire value range: int, unsigned int, long, unsigned long, long long, or unsigned long long, extended integer types with higher conversion rank (in rank order, signed given preference over unsigned) (since C++11). If the underlying type is fixed, the values can be converted to their underlying type (preferred in overload resolution), which can then be promoted.

所以关于 foo 的哪个重载将被 selected 你是对的,但你错了,没有发生隐式转换。 days 仍然是与 unsigned char 不同的类型,但它会隐式转换为一个。

你也错了,如果实现碰巧 select unsigned char 作为 enum Tokens 的基础类型,它将因此隐式转换为 unsigned char.如果您自己修复基础类型而不是让实现决定,则隐式转换为比 int 更窄的基础类型 才会发生。

您引用的 Primer 中的文字仅描述了您未明确指定基础类型时的情况。

引自 draft standard、expr.conv.prom:

A prvalue of an unscoped enumeration type whose underlying type is not fixed can be converted to a prvalue of the first of the following types that can represent all the values of the enumeration ([dcl.enum]): int, unsigned int, long int, unsigned long int, long long int, or unsigned long long int. If none of the types in that list can represent all the values of the enumeration, a prvalue of an unscoped enumeration type can be converted to a prvalue of the extended integer type with lowest integer conversion rank ([conv.rank]) greater than the rank of long long in which all the values of the enumeration can be represented. If there are two such extended types, the signed one is chosen.

A prvalue of an unscoped enumeration type whose underlying type is fixed ([dcl.enum]) can be converted to a prvalue of its underlying type. Moreover, if integral promotion can be applied to its underlying type, a prvalue of an unscoped enumeration type whose underlying type is fixed can also be converted to a prvalue of the promoted underlying type.

来自 over.ics.rank:

A conversion that promotes an enumeration whose underlying type is fixed to its underlying type is better than one that promotes to the promoted underlying type, if the two are different.