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.
但是如果我显式指定底层类型与函数参数的整数值完全匹配,那么我认为不会发生隐式转换:
enum days : unsigned char{sat = 1, sun, mon, tue, wed, thu, fri};
void foo(unsigned char x){
std::cout << "foo(unsigned char)\n";
}
void foo(int){
std::cout << "foo(int)\n";
}
foo(tue); // foo(unsigend char)
因此,正如您所看到的,枚举器值 tue
未提升为 int
,我得到的版本是 foo(unsigned char)
而不是 foo(int)
。
那么他的意思是如果枚举基础类型与函数参数不同,那么枚举数不会提升为char
而是提升为int
或大整数类型?
我认为在他的 enum tokens
示例中,如果底层类型是 unsigned char
那么函数调用中将不会有积分提升:newf(VIRTUAL); // calls newf(int)
和选择了 newf(unsigned char)
版本。你怎么看?
来自 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.
你好,我从 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 value129
. That value can be represented by the typeunsigned char
, and many compilers will useunsigned char
as the underlying type for Tokens. Regardless of its underlying type, objects and the enumerators ofTokens
are promoted toint
. Enumerators and values of anenum
type are not promoted tounsigned char
, even if the values of the enumerators would fit.
但是如果我显式指定底层类型与函数参数的整数值完全匹配,那么我认为不会发生隐式转换:
enum days : unsigned char{sat = 1, sun, mon, tue, wed, thu, fri}; void foo(unsigned char x){ std::cout << "foo(unsigned char)\n"; } void foo(int){ std::cout << "foo(int)\n"; } foo(tue); // foo(unsigend char)
因此,正如您所看到的,枚举器值 tue
未提升为 int
,我得到的版本是 foo(unsigned char)
而不是 foo(int)
。
那么他的意思是如果枚举基础类型与函数参数不同,那么枚举数不会提升为
char
而是提升为int
或大整数类型?我认为在他的
enum tokens
示例中,如果底层类型是unsigned char
那么函数调用中将不会有积分提升:newf(VIRTUAL); // calls newf(int)
和选择了newf(unsigned char)
版本。你怎么看?
来自 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
, orunsigned 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
, orunsigned 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 oflong 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.