涉及旧式枚举和整数类型的重载解析
Overload resolution involving old-style enums and integral types
考虑以下代码
#include <iostream>
using namespace std;
enum myEnum { a, b, c };
void test(myEnum e) {
cout << "myEnum overload" << endl;
}
void test(unsigned int i) {
cout << "unsigned int overload" << endl;
}
int main() {
test(a);
test(1);
test(1u);
return 0;
}
(我知道 enum class
对于这种事情比 enum
更安全,但我使用的是具有旧式枚举的开源代码。)
当我用 g++ 4.4.7 和 运行 编译它时,我得到
myEnum overload
unsigned int overload
unsigned int overload
即编译器更喜欢将 int
转换为 unsigned int
而不是将其转换为 myEnum
。这就是我想要的,但我想知道这是否始终得到保证。该标准没有具体指定 myEnum
的基础类型应该是什么,所以我想如果它恰好是 int
,也许这比 unsigned int
.
更受青睐
但是当我注释掉 unsigned int
重载时,我得到这个错误:
enum_overload.cpp: In function ‘int main()’:
enum_overload.cpp:17: error: invalid conversion from ‘int’ to ‘myEnum’
enum_overload.cpp:17: error: initializing argument 1 of ‘void test(myEnum)’
enum_overload.cpp:18: error: invalid conversion from ‘unsigned int’ to ‘myEnum’
enum_overload.cpp:18: error: initializing argument 1 of ‘void test(myEnum)’
这是否意味着旧式枚举隐式地将 转换为 它们的基础类型,而不是 从 这些类型?如果是这样的话,那么这将回答我之前的问题:如果整数类型不能转换为 myEnum
,那么重载决议保证表现如上。
A prvalue of an unscoped enumeration type can be converted to a
prvalue of an integer type.
反之则不然。没有从整数类型到无范围枚举类型的隐式转换:
您似乎将此与 将整数值转换为枚举类型 混淆:[expr.static.cast]/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
([dcl.enum]). Otherwise, the behavior is undefined. A value of
floating-point type can also be explicitly converted to an enumeration
type. The resulting value is the same as converting the original value
to the underlying type of the enumeration ([conv.fpint]), and
subsequently to the enumeration type.
(强调我的)
但这只能通过显式转换来完成:
E x1 = static_cast<E>(1) // yes
E x2 = E(1); // yes
E x3 = 1; // no
E x4(1); // no
我建议你阅读 this link。
如前所述,
An enumeration such as enum Color { red, white, blue };
is its own
type. It is not of type int
.
myEnum
既不是 int
也不是 unsigned int
。
此外,我建议不要通过直接将 int
转换为 myEnum
来使用 myEnum
(这样做:test(static_cast<myEnum>(0))
)。
实际上,编译器不会检查您提供的值是否有效,这可能会导致意外行为。
考虑以下代码
#include <iostream>
using namespace std;
enum myEnum { a, b, c };
void test(myEnum e) {
cout << "myEnum overload" << endl;
}
void test(unsigned int i) {
cout << "unsigned int overload" << endl;
}
int main() {
test(a);
test(1);
test(1u);
return 0;
}
(我知道 enum class
对于这种事情比 enum
更安全,但我使用的是具有旧式枚举的开源代码。)
当我用 g++ 4.4.7 和 运行 编译它时,我得到
myEnum overload
unsigned int overload
unsigned int overload
即编译器更喜欢将 int
转换为 unsigned int
而不是将其转换为 myEnum
。这就是我想要的,但我想知道这是否始终得到保证。该标准没有具体指定 myEnum
的基础类型应该是什么,所以我想如果它恰好是 int
,也许这比 unsigned int
.
但是当我注释掉 unsigned int
重载时,我得到这个错误:
enum_overload.cpp: In function ‘int main()’:
enum_overload.cpp:17: error: invalid conversion from ‘int’ to ‘myEnum’
enum_overload.cpp:17: error: initializing argument 1 of ‘void test(myEnum)’
enum_overload.cpp:18: error: invalid conversion from ‘unsigned int’ to ‘myEnum’
enum_overload.cpp:18: error: initializing argument 1 of ‘void test(myEnum)’
这是否意味着旧式枚举隐式地将 转换为 它们的基础类型,而不是 从 这些类型?如果是这样的话,那么这将回答我之前的问题:如果整数类型不能转换为 myEnum
,那么重载决议保证表现如上。
A prvalue of an unscoped enumeration type can be converted to a prvalue of an integer type.
反之则不然。没有从整数类型到无范围枚举类型的隐式转换:
您似乎将此与 将整数值转换为枚举类型 混淆:[expr.static.cast]/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 ([dcl.enum]). Otherwise, the behavior is undefined. A value of floating-point type can also be explicitly converted to an enumeration type. The resulting value is the same as converting the original value to the underlying type of the enumeration ([conv.fpint]), and subsequently to the enumeration type.
(强调我的)
但这只能通过显式转换来完成:
E x1 = static_cast<E>(1) // yes
E x2 = E(1); // yes
E x3 = 1; // no
E x4(1); // no
我建议你阅读 this link。
如前所述,
An enumeration such as
enum Color { red, white, blue };
is its own type. It is not of typeint
.
myEnum
既不是 int
也不是 unsigned int
。
此外,我建议不要通过直接将 int
转换为 myEnum
来使用 myEnum
(这样做:test(static_cast<myEnum>(0))
)。
实际上,编译器不会检查您提供的值是否有效,这可能会导致意外行为。