C++:三元运算符(条件运算符)及其隐式类型转换规则

C++ : Ternary Operator (Conditional Operator) and its Implicit Type Conversion Rules

三目运算符的参数是否有隐式类型转换规则?

三元运算符总是需要return相同的类型。此类型仅由第二个和第三个参数 (1st ? 2nd : 3rd) 确定,因此两个参数都转换为此类型。这个类型是怎么确定的?

更具体的,我测试了一个例子:

class pointclass
{
    pointclass();

    pointclass( int i );    // (pointclass)(int)
    operator bool() const;  // (bool)(pointclass)
};

我有一个class(pointclass),它支持从intpointclass的隐式转换和从pointclass到[=18的隐式转换=].

int i;
pointclass p;
bool b;

b ? p : i;  // (bool) ? (int)(bool)(pointclass) : (int)
b ? i : p;  // (bool) ? (int) : (int)(bool)(pointclass)

使用三元运算符,我比较了 pointclassint。编译器使用从 pointclassbool 的隐式转换,然后使用从 boolint 的标准转换。这已经完成了,无论我是否交换第二个和第三个参数。 为什么不将 int 转换为 pointclass

使用比较运算符要简单得多:

p == i;     // (pointclass) == (pointclass)(int)
i == p;     // (int) == (int)(bool)(pointclass)

参数的类型仅由第一个参数决定。

但是我不明白三元运算符的类型转换规则。对我来说,这似乎只是使用大多数转换的方式。

引用 MSDN:

Conditional expressions have right-to-left associativity. The first operand must be of integral or pointer type. The following rules apply to the second and third operands:

If both operands are of the same type, the result is of that type.

If both operands are of arithmetic or enumeration types, the usual arithmetic conversions (covered in Arithmetic Conversions) are performed to convert them to a common type.

If both operands are of pointer types or if one is a pointer type and the other is a constant expression that evaluates to 0, pointer conversions are performed to convert them to a common type.

If both operands are of reference types, reference conversions are performed to convert them to a common type.

If both operands are of type void, the common type is type void.

If both operands are of the same user-defined type, the common type is that type.

If the operands have different types and at least one of the operands has user-defined type then the language rules are used to determine the common type. (See warning below.)

基本上,C++ 编译器会为第二个和第三个操作数寻找通用类型。如果它能找到它,那就是结果类型。如果找不到,则会导致编译时错误。

如果想看标准位置,可以看规则in working draft for newest standard, 5.16 (page 129).

至于不将 int 转换为 pointclass - 一般规则是您 始终在层次结构中向下,而不是向上 - 想象更高级 class等级制度;上面的某个地方可能有几十种方法可以将这两种类型转换为其他类型 class,但这真的是您想要的吗?此外,确定使用哪个 class 可能是不可能的。因此,我们垂头丧气。