【问题标题】:Overload resolution involving old-style enums and integral types涉及旧式枚举和整数类型的重载解决方案
【发布时间】:2019-11-19 13:07:33
【问题描述】:

考虑下面这段代码

#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,那么重载决议的行为就可以保证如上。

【问题讨论】:

    标签: c++ enums implicit-conversion overload-resolution


    【解决方案1】:

    [conv.integral]/1:

    无范围枚举类型的纯右值可以转换为 整数类型的纯右值。

    反之则不成立。没有从整数类型到无范围枚举类型的隐式转换:

    您似乎将此与 强制 将整数值转换为枚举类型混淆了:[expr.static.cast]/10

    整数或枚举类型的值可以显式转换为完整的枚举类型。如果 原始值在枚举值范围内 ([dcl.enum])。否则,行为未定义。一个值 浮点类型也可以显式转换为枚举 类型。结果值与转换原始值相同 枚举的基础类型([conv.fpint]),以及 在枚举类型之后。

    (强调我的)

    但这只能通过显式强制转换来完成:

    E x1 = static_cast<E>(1) // yes
    E x2 = E(1);             // yes
    E x3 = 1;                // no
    E x4(1);                 // no
    

    【讨论】:

      【解决方案2】:

      我建议你阅读this link

      如前所述,

      enum Color { red, white, blue }; 等枚举是它自己的 类型。它不是int 类型。

      myEnum 既不是 int 也不是 unsigned int

      另外,我建议不要使用myEnum,直接将int 转换为myEnum(这样做:test(static_cast&lt;myEnum&gt;(0)))。 事实上,如果提供的值是有效值,编译器不会为您检查,这可能会导致意外行为。

      【讨论】:

      • 谢谢!这也解释了为什么没有强制转换的转换只能在一个方向上进行:将枚举转换为其基础类型将始终给出有效值;在另一个方向,情况并非如此。
      猜你喜欢
      • 2010-11-07
      • 1970-01-01
      • 2012-11-15
      • 1970-01-01
      • 2014-04-10
      • 2014-04-07
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多