首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >为什么具有固定基础类型char的枚举值解析为fct(int)而不是fct(char)?

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

Stack Overflow用户
提问于 2013-01-08 00:22:53
回答 2查看 2.3K关注 0票数 25

这个问题是在回答this question about overload resolution with enums时出现的。

虽然long long的情况肯定是MSVC2012NovCTP中的一个bug (根据标准文本和gcc 4.7.1的测试),但我不知道为什么会发生以下行为:

代码语言:javascript
复制
#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节:

其基础类型为fixed (7.2)的非作用域枚举类型的prvalue可以转换为其基础类型的prvalue。此外,如果可以将积分提升应用于其基础类型,则其基础类型为fi的非作用域枚举类型的prvalue也可以转换为提升的基础类型的prvalue。

因此,charEnum既可以转换为char,也可以转换为char的任何整体推广,例如int

但这对我来说是模糊的,因为“可以”并不能确切地说明哪一个会被选中。如果有的话,这应该是不明确的措辞,因为没有优先考虑char或它的任何晋升。如果您注释掉了fct(int),那么调用是不明确的。为什么int特别?

我唯一能想到的是,整体晋升是递归应用的,但我没有看到任何强制要求。

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2013-01-08 05:00:27

在C++03中,规则是:

未限定范围的枚举类型(7.2 dcl.enum)的r值可以转换为第一种类型的rvalue,这些类型可以表示枚举的所有值(如7.2 dcl.enum中描述的bmin到bmax范围内的值):int、无符号int、长int、无符号长int、长int或无符号长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提出并接受了以下修复方法:

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

因为它被报告为C++11中的一个缺陷,所以编译器应该在C++11模式下应用这个修复并调用fct(char)

票数 9
EN

Stack Overflow用户

发布于 2013-01-08 13:42:58

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

每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将这些步骤分为四类,其中升级和转换,以及基于构成这些序列的个别转换类别的等级转换序列。

在我们的例子中,我们有两个由一个促进步骤组成的单长度转换序列(这两个步骤都是4.5./4所允许的)。

转换序列按照13.3.3.2排列为。特别是,13.3.3.2/3提到,在以下情况下,转换序列S1比转换序列S2更可取:

S1的等级,即晋升、转换等,比 S2的等级要好,或者S1和S2的等级相同,按照__下面段落中的规则,或者,如果不是这样,.

下面提到的“段落”为13.3.3.2/4,内容如下:

“标准转换序列按等级排序:完全匹配比升级更好,这比转换更好。除非下列规则之一适用于__,否则具有相同等级的标准转换序列是不可区分的:”

然后,下面是在我们的情况下不应用的一组规则。

因此,我们有两个一步转换序列,由一个级别相同的单一升迁组成。根据以上标准的解释,的调用必须是模棱两可的。

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

票数 4
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/14206403

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档