25

这个问题是在用 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应该从转换charEnumchar?为什么A被转换为int?

编辑:clang 抱怨这个电话是模棱两可的,这与我在下面的解释一致;也就是说,如果仅将其视为基础类型,我仍然会发现它更加直观。


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

枚举数或无作用域枚举类型的对象的值通过整数提升(4.5)转换为整数

和§4.5/4:

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

所以charEnum既可以转换为char,也可以是任何整数提升char,例如int.

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

我唯一能想到的是积分提升是递归应用的,但我没有看到任何强制它。

4

2 回答 2

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 under type,此措辞已更改为您在 §4.5/4 中引用的段落,从阅读缺陷报告来看,委员会的意图似乎是fct(char)(基础类型)被选中。

但是,根据核心问题 1601下的讨论,C++11 中的文本实际上使转换模棱两可(fct(char)并且fct(int)两者都是可能的,但都不是首选)。

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

如果两者不同,则提升其基础类型固定为其基础类型的枚举的转换优于提升为提升的基础类型的转换。

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

于 2013-01-08T05:00:27.607 回答
4

根据我对当前标准的解释,调用必须是模棱两可的。跟随一个解释。

每 4.5/4:

“其基础类型固定(7.2)的无范围枚举类型的纯右值可以转换为其基础类型的纯右值。此外,如果可以将整数提升应用于其基础类型,则其基础类型的无范围枚举类型的纯右值is fixed 也可以转换为提升的基础类型的纯右值。”

这提供了两种可选的提升:提升到底层类型,提升到提升的底层类型。因此,仅此一段就在解决对重载函数的函数调用时应该使用这些替代方案中的一个提出了歧义。

然后,第 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,它说:

“标准转换序列按其等级排序:精确匹配比提升转换更好,提升比转换更好。具有相同等级的两个转换序列无法区分,除非适用以下规则之一:”

然后,接下来是一组不适用于我们情况的规则。

因此,我们有两个单步转换序列,由具有相同排名的单个Promotion组成。根据上述对现行标准的解释,调用必须是模棱两可的

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

于 2013-01-08T13:42:58.633 回答