【发布时间】:2012-12-21 19:11:03
【问题描述】:
回复this question about overload resolution with enums时出现这个问题。
虽然long long 的情况绝对是 MSVC2012NovCTP 中的一个错误(根据标准文本和 gcc 4.7.1 的测试),但我无法弄清楚为什么会出现以下行为:
#include <iostream>
enum charEnum : char { A = 'A' };
void fct(char) { std::cout << "fct(char)" << std::endl; }
void fct(int) { std::cout << "fct(int)" << std::endl; }
void fct(long long) { std::cout << "fct(long long)" << std::endl; }
int main()
{
fct('A');
fct(A);
}
MSVC2012NovCTP 和 gcc 4.7.1 都同意这个输出:
fct(char)
fct(int)
不应该将A 从charEnum 转换为char 吗?为什么A 被转换为int?
编辑:clang 抱怨电话不明确,这与我在下面的解释一致;也就是说,如果仅将其视为底层类型,我仍然会发现它更加直观。
两个相关的标准摘录是 §7.2/9:
枚举数或非作用域枚举类型的对象的值通过整数提升(4.5)转换为整数
以及§4.5/4:
其基础类型固定(7.2)的无作用域枚举类型的纯右值可以转换为其基础类型的纯右值。此外,如果可以将整型提升应用于其基础类型,则其基础类型固定的无作用域枚举类型的纯右值也可以转换为提升的基础类型的纯右值。
所以charEnum 可以转换为char,或者char 的任何积分提升,例如int。
但这对我来说很模糊,因为“可以”并不能完全说明实际会选择哪个。如果有的话,这应该与此措辞模棱两可,因为在 char 或其任何促销活动之间没有优先考虑。如果您注释掉fct(int),则调用 不明确。为什么int 很特别?
我唯一能想到的是积分提升是递归应用的,但我没有看到强制它。
【问题讨论】:
-
只是猜测:为了保持旧代码正常工作,因为在 C++11 之前,枚举转换为
int。现在使用类型说明符(在您的情况下为char,我不知道如何正确调用它),我们只想说应该使用什么类型来表示它,而不是在转换中如何处理它。 -
@leemes:嗯,有点。 “旧式”枚举转换为其基础类型,即
int、unsigned int、long等,直到正确保存所有枚举值。所以这个会转换为unsigned int:enum foo { X = 0, Y = UINT_MAX };。不管你的观点仍然成立:它从来没有“少于”int。但是由于固定底层类型的整个概念是新的,因此在没有兼容性的情况下打破直觉是很奇怪的。 -
在我看来,标准对整体促销的描述存在缺陷。提到的所有其他类型都被描述为能够提升为零或一个精确指定的提升类型。因此,当标准的其他部分说“整体推广”时,每个人都清楚它是做什么的。但是这里听起来好像有两种可能的提升类型??
-
看看这个:ideone.com/8zuGEp - 编辑:嗯,我认为它没有显示任何新内容。我们可以重现一些赞成/反对我的论点的东西吗?
-
哦,等等...也许“最好”的转换是最大尺寸的转换(基础类型,默认类型)? (对于默认类型,我的意思是如果我们不指定类型,枚举将具有的类型)。至少,这可以解释为什么在我的 ideone 代码中,
fct(A)使用uint,而不是int,因为它不能...
标签: c++ c++11 enums overloading overload-resolution