【问题标题】:Underlying type of weak typed enum in C++11C++11 中弱类型枚举的底层类型
【发布时间】:2013-01-06 18:31:53
【问题描述】:

C++11 引入了强类型枚举,语法为enum class。这些与整数类型不兼容,需要显式强制转换才能获得它们的数值。 C++11 还引入了以enum name : type {} 的形式为弱类型枚举指定存储类的能力。到这里为止都很好。

但是看起来即使弱类型枚举具有给定的存储类,其项目的类型仍然是int。我尝试使用 Visual Studio 2012,11 月 CTP 版本。考虑以下代码:

enum charEnum : char { A = 'A' };
enum longEnum : long long { Tera = 1000000000000 };

void fct(char val) {}
void fct(int val) {}
void fct(long long val) {}

int main() 
{
    static_assert(sizeof(A) == sizeof(char), "check charEnum size");
    static_assert(sizeof(Tera) == sizeof(long long), "check longEnum size");
    fct('A');  // calls fct(char)
    fct(1);    // calls fct(int)
    fct(2ll);  // calls fct(long long)
    fct(A);    // calls fct(int) !
    fct(Tera); // calls fct(int), with truncation !
    fct((long long)Tera);  // calls fct(long long)
    return 0;
}

为枚举值调用的重载函数始终为fct(int),即使这会导致值被截断。当然,通过显式强制转换,我们可以调用重载函数,但这在传统的 C++03 语法中也是可能的。

我是否遗漏了一些明显的东西?这是为什么?有比显式强制转换更好的解决方法吗?

【问题讨论】:

  • 可能是因为枚举只能隐式转换为 int。
  • 您的确定性从何而来?来自特定编译器的行为?如果是这样,您使用的是哪个编译器?您是否尝试过其他编译器?
  • @Walter 你说得对,我只尝试过使用 Visual Studio 2012 CTP。也许我错误地推断标准本身。
  • @SethCarnegie:这些不是您要查找的范围枚举。作用域枚举中有一个词 classstruct(这些关键字引入了作用域;int 没有)。

标签: c++ c++11


【解决方案1】:

这是一个编译器错误。根据 §7.2/9 和 §4.5/4:

第 7.2/9 节:
枚举数或非作用域枚举类型对象的值通过整数提升(4.5)转换为整数

§4.5/4:
其基础类型是固定的(7.2)的无作用域枚举类型的纯右值可以转换为其基础类型的纯右值。此外,如果可以将整型提升应用于其基础类型,则其基础类型固定的无作用域枚举类型的纯右值也可以转换为提升的基础类型的纯右值。

最后一个应该转换为long long,而不是intThe char case is a point of contention。 (!)


测试程序:

#include <iostream>

enum charEnum : char      { A = 'A' };
enum longEnum : long long { Tera = 1000000000000 };

void fct(char val)      { std::cout << "fct(char)"      << std::endl; }
void fct(int val)       { std::cout << "fct(int)"       << std::endl; }
void fct(long long val) { std::cout << "fct(long long)" << std::endl; }

int main() 
{
    static_assert(sizeof(A)    == sizeof(char),      "check charEnum size");
    static_assert(sizeof(Tera) == sizeof(long long), "check longEnum size");

    fct('A');
    fct(1);
    fct(2ll);
    fct(A);
    fct(Tera);
    fct((long long)Tera);
}

MSVC2012NovCTP 输出:

fct(char)
fct(int)
fct(长长)
fct(int)
fct(int)
fct(long long)

g++ 4.7.1:

fct(char)
fct(int)
fct(长长)
fct(int)
fct(长长)
fct(long long)

【讨论】:

  • 你是对的!我尝试使用 GCC 4.5.3,它为 fct(Tera) 调用 long long !我想我会把这个错误提交给微软。但我还是不明白为什么fct(A) 调用fct(int) 而不是fct(char)
  • “可以转换”在这里意义不大。 char 可以转换为任何整数类型,但如果在 f(int)f(char) 之间进行选择,则会调用后者。
  • @n.m.: char,是的,但显然不是以char 作为基础类型的枚举。
  • @prapin:我也不知道,根据引号它应该调用char 重载或在这三个之间模棱两可。
  • @GManNickG:是的,我就是这个意思。
猜你喜欢
  • 2014-08-02
  • 2010-11-10
  • 1970-01-01
  • 1970-01-01
  • 2020-01-04
  • 1970-01-01
  • 1970-01-01
  • 2013-03-13
  • 1970-01-01
相关资源
最近更新 更多