首页 文章

了解非重载按位运算符的转换顺序,算术转换和整数提升

提问于
浏览
0

当编译器遇到非重载操作符以及操作了什么转换时,我想准确理解发生了什么 . 举个例子,让我们采用按位运算符,例如 & . 标准说:

[expr.bit.and]执行通常的算术转换;结果是操作数的按位AND功能 . 运算符仅适用于整数或无范围的枚举操作数 .

然后,如果我正在寻找通常的算术转换,我得到:

[expr]许多期望算术或枚举类型操作数的二元运算符会以类似的方式引起转换并产生结果类型 . 目的是产生一个通用类型,它也是结果的类型 . 此模式称为通常的算术转换,其定义如下:如果任一操作数是作用域枚举类型(7.2),则不执行任何转换;如果另一个操作数的类型不同,则表达式格式不正确 . 如果任一操作数的类型为long double,则另一个操作数应转换为long double . 否则,如果任一操作数为double,则另一个操作数应转换为double . 否则,如果任一操作数是浮点数,则另一个操作数应转换为浮点数 . 否则,应对两个操作数执行整体促销 . 然后,以下规则将应用于提升的操作数:如果两个操作数具有相同的类型,则不需要进一步转换 . 否则,如果两个操作数都具有有符号整数类型或两者都具有无符号整数类型,则具有较小整数转换等级类型的操作数应转换为具有较大等级的操作数的类型 . 否则,如果具有无符号整数类型的操作数的秩大于或等于另一个操作数的类型的秩,则带有符号整数类型的操作数应转换为具有无符号整数类型的操作数的类型 . 否则,如果带有符号整数类型的操作数的类型可以表示具有无符号整数类型的操作数类型的所有值,则具有无符号整数类型的操作数应转换为带有符号整数类型的操作数的类型 . 否则,两个操作数都应转换为与带符号整数类型的操作数类型相对应的无符号整数类型

现在,如果我们期待整数推广:

[conv.prom]:如果int可以表示所有值,则整数转换等级小于int的整数转换等级的bool,char16_t,char32_t或wchar_t之类的整数类型的prvalue可以转换为int类型的prvalue源类型;否则,源prvalue可以转换为unsigned int类型的prvalue . 可以将char16_t,char32_t或wchar_t(3.9.1)类型的prvalue转换为以下第一种类型的prvalue,它们可以表示其基础类型的所有值:int,unsigned int,long int,unsigned long int ,long long int或unsigned long long int . 如果该列表中的任何类型都不能表示其基础类型的所有值,则可以将char16_t,char32_t或wchar_t类型的prvalue转换为其基础类型的prvalue . 其基础类型未修复的未作用域枚举类型的prvalue可以转换为以下第一种类型的prvalue,它们可以表示枚举的所有值:int,unsigned int,long int,unsigned long int,long long int或unsigned long long int . 如果该列表中的所有类型都不能表示枚举的所有值,则可以将未作用域的枚举类型的prvalue转换为扩展整数类型的prvalue,其中整数转换等级最大大于long long的等级 . 可以表示枚举的值 . 如果有两种这样的扩展类型,则选择签名的类型 . 可以将其基础类型固定的未作用域枚举类型的prvalue转换为其基础类型的prvalue . 此外,如果可以对其基础类型应用整数提升,则其基础类型固定的未范围枚举类型的prvalue也可以转换为提升的基础类型的prvalue . 如果int可以表示位字段的所有值,则可以将整数位字段的prvalue转换为int类型的prvalue;否则,如果unsigned int可以表示位字段的所有值,则可以将其转换为unsigned int . 如果位字段较大,则不适用整数提升 . 如果位字段具有枚举类型,则将其视为该类型的任何其他值以用于促销目的 . bool类型的prvalue可以转换为int类型的prvalue,false变为零,true变为1 . 这些转化称为整体促销 .

但如果我们这样做:

std::integral_constant<int, 2> x;
std::integral_constant<int, 3> y;
int z = x & y;

它会工作,虽然我没有看到标准中指定的位置 . 我想确切地说,所有的转换检查这是按顺序完成的 . 我认为首先,编译器检查运算符是否具有完全取代类型的重载 . 然后我不知道编译器做了什么其他测试 . 并且可能只是在它之后它使用通常的算术转换然后是整体促销 .

那么转换测试和步骤是编译器在做什么以及遇到_671241时的顺序? (欢迎提取标准) .

1 回答

  • 1

    当编译器看到这个:

    int z = x & y;
    

    它会看到 std::integral_constant<> 没有特定的 operator & . 然而,它会看到 xy 是非 explicit operator value_type() . 由于 value_typeint ,因此可以直接匹配最常见的 operator & .

    不需要或执行算术转换或整体升级 .

    [转](2.1)说:

    用作运算符的操作数时 . 运营商对其操作数的要求决定了目的地类型 .

    [over.match]说:

    这些上下文中的每一个都以其自己独特的方式定义候选函数集和参数列表 . 但是,一旦确定了候选函数和参数列表,最佳函数的选择在所有情况下都是相同的:(2.8) - 首先,候选函数的一个子集(具有适当数量的参数并满足某些函数的函数)选择其他条件)以形成一组可行的函数(13.3.2) . (2.9) - 然后根据将每个参数与每个可行函数的相应参数匹配所需的隐式转换序列(13.3.3.1)来选择最佳可行函数 .

    [class.conv]说:

    类对象的类型转换可以由构造函数和转换函数指定 . 这些转换称为用户定义的转换,用于隐式类型转换(第4节),初始化(8.5)和显式类型转换(5.4,5.2.9) .

相关问题