涉及旧式枚举和整数类型的重载解析

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,那么重载决议保证表现如上。

[conv.integral]/1:

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)))。 实际上,编译器不会检查您提供的值是否有效,这可能会导致意外行为。