c ++在表达式中找到隐式类型转换

c++ find implicit type conversion in the expression

对于下面的表达式:-

int main()
{
    unsigned ui = 1;
    float fval = 2.5;
    cout << sizeof(ui) << endl << sizeof(fval) << endl;
    cout << typeid(ui+fval).name();
}

我们得到以下输出:-

4
4
f

好像ui+fval是个浮点数

但是,鉴于 float 和 unsigned int 都是 4 个字节,并且并非所有 unsigned int 值都可以放入 float 中,难道不应该将 fval 转换为 unsigned int 吗?

算术运算符的规则实际上与一般函数重载决策的规则略有不同。

来自 arithmetic operators 上的 cppreference:

Conversions

If the operand passed to an arithmetic operator is integral or unscoped enumeration type, then before any other action (but after lvalue-to-rvalue conversion, if applicable), the operand undergoes integral promotion. If an operand has array or function type, array-to-pointer and function-to-pointer conversions are applied.

For the binary operators (except shifts), if the promoted operands have different types, additional set of implicit conversions is applied, known as usual arithmetic conversions with the goal to produce the common type (also accessible via the std::common_type type trait). If, prior to any integral promotion, one operand is of enumeration type and the other operand is of a floating-point type or a different enumeration type, this behavior is deprecated. (since C++20)

  • If either operand has scoped enumeration type, no conversion is performed: the other operand and the return type must have the same type
  • Otherwise, if either operand is long double, the other operand is converted to long double
  • Otherwise, if either operand is double, the other operand is converted to double
  • Otherwise, if either operand is float, the other operand is converted to float

[snip]

因此,非常明确地,当我们执行 unsigned + float 时,unsigned 会转换为 float。这是第一个适用的规则,所以我们遵循它。

但是,对于一般的重载解析,从unsignedfloat的转换等同于从floatunsigned的转换。因此,例如在以下代码片段中:

unsigned add(unsigned l, unsigned r) { return l + r;  }
float add(float l, float r) { return l + r;  }

int main()
{
    unsigned ui = 1;
    float fval = 2.5;
    add(ui, fval);
}

无法决定使用哪个版本的add,编译失败