回答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(炭)
fct(int)
不应A
从charEnum
转换为char
吗?为什么A
被转换为int
?
两个相关的标准摘录是§7.2/ 9:
通过整数提升(4.5)将枚举数或无范围枚举类型的对象的值转换为整数
并且§4.5/ 4:
其底层类型为固定(7.2)的未作用域枚举类型的prvalue可以转换为其基础类型的prvalue。此外,如果可以将整数提升应用于其基础类型,则其基础类型固定的未范围枚举类型的prvalue也可以转换为提升的基础类型的prvalue。
因此,charEnum
可以转换为char
,也可以转换为char
的任何整体推广,例如int
。
但这对我来说很模糊,因为“可以”并不能说实际上会选择哪一个。如果有的话,这个措辞应该含糊不清,因为在char
或其任何促销活动之间没有给出优先权。如果您注释掉fct(int)
,那么的调用是不明确的。为什么int
特别?
我唯一能想到的是递归推广整体促销活动,但我认为没有任何要求。
答案 0 :(得分:9)
在C ++ 03中,规则是:
无范围枚举类型的右值(7.2 [dcl.enum])可以 转换为可以的以下第一种类型的右值 表示枚举的所有值(即,枚举中的值) 范围bmin到bmax,如7.2 [dcl.enum]中所述):int,unsigned int, long int,unsigned long int,long long int或unsigned long long int。
在C ++ 03编译器中,将选择int
,因为它是第一个
在名单上。
在C ++ 11中,引入了底层类型。因此,通过685. Integral promotion of enumeration ignores fixed underlying type ,这个措辞改为§4.5/ 4中引用的段落,并且从阅读缺陷报告开始,委员会的意图似乎是fct(char)
(基础类型)被选中。
但是,根据core issue 1601下的讨论,C ++ 11中的文字实际上使转换变得模糊(fct(char)
和fct(int)
都是可能的,并且两者都不是首选。)< / p>
以下修正案被提出并被C ++ 14接受:
促进其基础类型为的枚举的转换 固定到它的底层类型比促进它的一个更好 如果两者不同,则提升基础类型。
由于它被报告为C ++ 11中的缺陷,编译器应该在C ++ 11模式下应用此修复并调用fct(char)
。
答案 1 :(得分:3)
根据我对当前标准的解释,呼叫必须含糊不清。遵循解释。
每4.5 / 4:
“其底层类型固定的无范围枚举类型的prvalue(7.2)可以转换为其基础类型的prvalue。此外,如果可以将整数提升应用于其基础类型,则可以使用它的prvalue。其基础类型固定的未作用域枚举类型也可以转换为升级基础类型的prvalue。“
这提供了两种替代促销:对基础类型的促销,以及对提升的基础类型的促销。因此,这个段落单独引入了歧义,因为在解析对重载函数的函数调用时应该使用这些替换的。
然后,第13.3.3段根据“转换序列”决定哪个是过载集的最佳可行函数。特别是,与此问题相关的是13.3.3.1(“隐式转换序列”),更具体地说,13.3.3.1.1(“标准转换序列”),它定义了这些转换序列的基本步骤。
13.3.3.1.1 / 1和表12将这些步骤分为四类,其中促销和转换,以及基于个人类别的等级转换序列构成这些序列的转换。
在我们的案例中,我们有两个单一长度转换序列,由一个 Promotion 步骤组成(均由4.5./4允许)。
转换序列根据13.3.3.2排名。特别是,13.3.3.2 / 3提到转换序列S1优于转换序列S2,如果:
“等级 [即促销,转换等] 的优于 S2的等级,或者S1和S2具有相同等级,可通过以下段落中的规则区分,或者,如果不是,[...]“
提到的“段落”是13.3.3.2/4,其中说:
“标准转换序列按其排名排序:完全匹配是一种比促销更好的转换,这是一种比转换更好的转换。具有相同排名的两个转换序列无法区分,除非一个适用以下规则:“
然后,接下来是一组在我们的情况下不适用的规则。
因此,我们有两个一步转换序列,由一个具有相同排名的 Promotion 组成。根据上述对当前标准的解释,呼叫必须含糊不清。
但是,就个人而言,我同意需要进行更改,以便转换为无范围枚举的固定基础类型,而不是其他可能的转换。