The last line of this code fails to compile with castingAndTernary.cpp:15: error: conditional expression between distinct pointer types ‘D1*’ and ‘D2*’ lacks a cast
I was not going to answer, but after posting the comment I thought, what the... it is an approach as any other:
int main() {
bool condition = true;
D1 d1;
D2 d2;
B * p = condition ? &d1 : (true? &d2 : p );
}
Basically abuse the ternary operator to extract the appropriate type. When the compiler processes the ternary operator it tries to determine whether the two operands can be implicitly converted to a common type 1, and if so, it uses that common type as the type of the expression.
In the code above, the inner ternary operator: true? &d2 : p
will try to match the type of the expression &d2
with the type of p
, it will find that there is a simple upcast that it can perform and will set the return type for that subexpression to B*
. Note that because the condition is true
, it will always yield &d2
, even if it uses the third argument to determine the type.
The same operation is performed with the enclosing expression, where now the second argument is &d1
(type D1*
) and the type of the third argument is B*
. Again, the conversion is trivial by upcasting D1*
, and the type of the whole expression is B*
.
Because all of the conversions are performed implicitly by the compiler, if you change the types of the pointers, and break the invariant that they can be implicitly converted, the compiler will tell you, solving the issue of throwing a static_cast
in the middle of the ternary operator.
1 The standard dictates a set of different conversions, depending on the types of the arguments. In the particular case of the two arguments being pointers (as is the case here) the conversions that are allowed are pointer conversions and qualification conversions.