繁体   English   中英

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

[英]Why does a value of an enum with a fixed underlying type of char resolve to fct(int) instead of fct(char)?

用枚举回答有关重载解析的问题时,出现了这个问题

尽管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

编辑:clang抱怨该呼叫不明确,这与我在下面的解释一致; 也就是说,如果仅将其视为基础类型,我仍然会发现它更加直观。


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

枚举提升(4.5)将枚举数或无范围枚举类型的对象的值转换为整数

以及第4.5 / 4节:

固定基础类型(7.2)的无范围枚举类型的prvalue可以转换为其基础类型的prvalue。 此外,如果可以将积分提升应用于其基础类型,则其基础类型固定的无范围枚举类型的prvalue也可以转换为提升的基础类型的prvalue。

所以charEnum可以被转化为char ,或任何整促进char ,诸如int

但这对我来说是模糊的,因为“可以”并不能完全确定将实际选择哪个。 如果有的话,这应该与该措词不明确,因为在char或其任何促销之间没有优先选择。 如果您注释掉fct(int) ,则该调用不明确的。 为什么int特别?

我唯一能想到的是,积分促销是递归应用的,但我认为没有什么强制执行的。

在C ++ 03中,规则是:

可以将无范围枚举类型的右值(7.2 [dcl.enum])转换为可以表示该枚举的所有值的以下第一种类型的右值(即,如b所述,在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)

根据我对当前标准的解释, 该调用必须是模棱两可的 遵循说明。

根据4.5 / 4:

“可以将基础类型为固定(7.2)的无作用域枚举类型的prvalue转换为其基础类型的prvalue。此外,如果可以对其基础类型应用积分提升,则其基础类型的无作用域枚举类型的prvalue固定值也可以转换为提升的基础类型的prvalue。”

这提供了两个替代的提升 :提升为基础类型和提升为提升的基础类型。 因此,仅此段就引起歧义,因为在解决对重载函数的函数调用时应使用这些备选方案中的一种。

然后,第13.3.3节根据“转换序列”确定哪个是过载集的最佳可行函数。 特别是与此相关的是13.3.3.1(“ 隐式转换序列 ”),更具体地说是13.3.3.1.1(“ 标准转换序列 ”),它定义了构成这些转换序列的基本步骤。

13.3.3.1.1 / 1和表12将这些步骤分为四类,其中PromotionConversion ,并根据构成这些序列的单个转换的类别对转换序列进行排名。

在我们的情况下,我们有两个由一个推广步骤组成的单长度转换序列 (均由4.5./4允许)。

转换顺序根据13.3.3.2。进行排序。 特别地,在13.3.3.2/3中提到,在以下情况下,转换序列S1比转换序列S2更可取:

S1 的等级 [即晋升,转换等] 优于 S2 的等级 ,或者S1和S2具有相同的等级,并且可以通过以下段落中的规则加以区分 ;或者,如果不是,则[。 。]”

提到的“ 下面的段落 ”是13.3.3.2/4,它表示:

“标准转换顺序按其排名排序:“完全匹配”比“晋升”更好,比“转换”更好。 除非具有以下规则之一,否则两个具有相同排名的转换序列是无法区分的 :”

然后,遵循的是一组不适用于我们的情况的规则。

因此,我们有两个由一个具有相同等级的促销构成的单步转换序列。 根据当前标准的上述解释, 调用必须是模棱两可的

但是,就我个人而言,我同意需要进行更改以使转换为无作用域枚举的固定基础类型优于其他可能的转换。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM