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

标签 c++ c++11 enums overloading overload-resolution

回答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:

The value of an enumerator or an object of an unscoped enumeration type is converted to an integer by integral promotion (4.5)

和§4.5/4:

A prvalue of an unscoped enumeration type whose underlying type is fixed (7.2) can be converted to a prvalue of its underlying type. Moreover, if integral promotion can be applied to its underlying type, a prvalue of an unscoped enumeration type whose underlying type is fixed can also be converted to a prvalue of the promoted underlying type.

因此 charEnum 可以转换为 char,或者 char 的任何整数提升,例如 int .

但这对我来说是模糊的,因为“可以”并没有完全说明实际上会选择哪个。如果有的话,这个措辞应该是模棱两可的,因为在 char 或其任何促销事件之间没有给出任何偏好。如果您注释掉 fct(int),则调用 是不明确的。为什么 int 很特别?

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

最佳答案

在 C++03 中,规则是:

An rvalue of an unscoped enumeration type (7.2 [dcl.enum]) can be converted to an rvalue of the first of the following types that can represent all the values of the enumeration (i.e. the values in the range bmin to bmax as described in 7.2 [dcl.enum]): int, unsigned int, long int, unsigned long int, long long int, or 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) 都是可能的,但都不是首选)。

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

A conversion that promotes an enumeration whose underlying type is fixed to its underlying type is better than one that promotes to the promoted underlying type, if the two are different.

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

关于c++ - 为什么具有固定底层 char 类型的枚举的值解析为 fct(int) 而不是 fct(char)?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29584756/

相关文章:

c++ - 使用带有 std::unique_ptr 元素的 boost::multi_index::multi_index_container 的初始化列表

PHP + SQL 查询 : Selecting Enum Values

c++ - 在ubuntu上编译c++项目

c++ - 在类范围内获取虚方法的类型

java - 未在此范围内声明 GetByteArrayElements

c++ - 基于整数范围的模板特化

c++ - 为什么大小不是 std::initializer_list 的模板参数?

c++ - C++ 11 future / promise 中没有状态错误

c# - lambda 表达式中的枚举的编译方式不同;重载分辨率改进的结果?

c - 在 header 中声明枚举,在源文件中不可见?