Reputation: 133
Are there rules for implicit type conversion for arguments of the ternary operator?
The ternary operator always needs to return the same type. This type is determined solely by the second and third argument (1st ? 2nd : 3rd
), therefore both arguments are converted to this type. How is this type determined?
To be more specific, I tested an example:
class pointclass
{
pointclass();
pointclass( int i ); // (pointclass)(int)
operator bool() const; // (bool)(pointclass)
};
I have a class (pointclass
), which enables implicit conversion from int
to pointclass
and implicit conversion from pointclass
to bool
.
int i;
pointclass p;
bool b;
b ? p : i; // (bool) ? (int)(bool)(pointclass) : (int)
b ? i : p; // (bool) ? (int) : (int)(bool)(pointclass)
Using the ternary operator, I compare pointclass
and int
. The compiler uses implicit conversion from pointclass
to bool
and then the standard conversion from bool
to int
. This is done, no matter if I exchange 2nd and 3rd arguments. Why does it not convert int
to pointclass
?
Using a comparison operator is much more straightforward:
p == i; // (pointclass) == (pointclass)(int)
i == p; // (int) == (int)(bool)(pointclass)
The type of the arguments is simply determined by the first argument.
But I don't understand the type conversion rules of the ternary operator. For me it seems just like using the way of most conversions.
Upvotes: 13
Views: 3429
Reputation: 1091
Quoting 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.)
Basically what happens is that C++ compiler looks for common type for second and third operand. If it can find it, that's result type. If it can't find it, it results in a compilation time error.
If you want to see standard position, you can see the rules in working draft for newest standard, 5.16 (page 129).
As of not converting int to pointclass - general rule is that you always go down the hierarchy, not up - imagine more advanced class hierarchy; somewhere up there could be dozens of ways to convert both types up to some other class, but is that really what you want? Moreover, determining which class to use could be impossible. Therefore, we downcast.
Upvotes: 7