为什么具有固定底层类型char的枚举值会解析为fct(int)而不是fct(char)?

GMa*_*ckG 25 c++ enums overloading overload-resolution c++11

在回答有关使用枚举的重载解析的问题时,出现了此问题.

虽然案例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);
}
Run Code Online (Sandbox Code Playgroud)

MSVC2012NovCTP和gcc 4.7.1都同意此输出:

fct(char)
fct(int)

A应该转换charEnumchar?为什么A被转换成int

编辑:clang抱怨说这个电话含糊不清,这与我在下面的解释一致; 那说,如果它只被认为是潜在的类型,我仍然会发现它更直观.


两个相关的标准摘录是§7.2/ 9:

枚举器的值或未范围的枚举类型的对象通过整数提升转换为整数(4.5)

并且§4.5/ 4:

其底层类型为固定(7.2)的无范围枚举类型的prvalue可以转换为其基础类型的prvalue.此外,如果可以对其基础类型应用整数提升,则其基础类型固定的未范围枚举类型的prvalue也可以转换为提升的基础类型的prvalue.

因此,charEnum可以转换为char,或任何整体推广char,如int.

但这对我来说很模糊,因为"可以"并不能说实际上会选择哪一个.如果有的话,这个措辞应该含糊不清,因为它们之间char或其任何促销都没有优先权.如果你注释掉fct(int),那么这个电话不明确的.为什么int特别?

我唯一能想到的是递归应用积分促销,但我认为没有任何要求.

Jes*_*ood 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.枚举的整体推广忽略了固定的基础类型,这个措辞改为§4.5/ 4中引用的段落,并且从阅读缺陷报告中看来,委员会的意图似乎是fct(char)(基础类型)被选中.

然而,根据核心问题1601下的讨论,C++ 11中的文本实际上使转换变得模糊(fct(char)并且fct(int)都是可能的,并且两者都不是优选的).

在C++ 14中提出并接受以下修复:

如果两者不同,那么促进其基础类型固定为其基础类型的枚举的转换优于促进提升的基础类型的转换.

由于它被报告为C++ 11中的缺陷,因此编译器应该在C++ 11模式下应用此修复并调用fct(char).