Reputation: 327
In C++, let the following construct :
template<typename ValueType>
ValueType * func(Foo * foo)
{
Bar bar;
return foo && typeid(foo) == typeid(ValueType) ? &static_cast<ValueType*>bar : 0;
}
How is the return statement evaluated? Like so?
if ((bar && typeid(bar)) == typeid(ValueType))
return &static_cast<ValueType*>bar
return false;
Upvotes: 1
Views: 122
Reputation: 213306
The posted answer correctly addresses operator precedence with this:
(foo && (typeid(foo) == typeid(ValueType))) ? (&(static_cast<ValueType*>(bar))) : 0;
That's how the expression will be parsed - which operands the compiler will regard as if belonging to which operator. That does however not state how the expression is evaluated (basically "executed"). So it does not answer the question:
How is this boolean expression evaluated?
The expression is evaluated as:
foo
is evaluated.
false
, then (typeid(foo) == typeid(ValueType))
will not get evaluated and the whole subexpression will be evaluated as false
.true
then (typeid(foo) == typeid(ValueType))
will get evaluated. Both operands of the ==
will get evaluated (and overloaded operators called if applicable). If that whole expression is true
then the result of the &&
is also true
.true
, then the 2nd operand (&(static_cast<ValueType*>(bar)))
will get evaluated.false
, then the 3rd operand 0
will get evaluated.Notably, the 2nd and 3rd operands of ?:
need to be of the same type. In case of pointers that means exactly the same type, although if one operand is a null pointer as in this case, the result will be of the type of the other operand. In case of arithmetic types, the 2nd and 3rd operand will get "balanced" as per the usual arithmetic conversions.
The expression &static_cast<ValueType*>bar
is also very fishy in many ways. Apart from the missing parenthesis, you cannot cast bar
to a pointer type and you mostly likely shouldn't be doing wild type punning between types like this either.
Upvotes: 0
Reputation: 106068
foo && typeid(foo) == typeid(ValueType) ? &static_cast<ValueType*>bar : 0;
...corrected with parenthesis after the static_cast<>
, is evaluated as...
(foo && (typeid(foo) == typeid(ValueType))) ? (&(static_cast<ValueType*>(bar))) : 0;
The precedence rules are listed here. Notice that the ?:
ternary operator is at precedence level 15 in this list - lower than the other operators you've used, so it defines the outer structure of the evaluation. &&
is at 13 - way below ==
at 9. (I don't think these numbers are used anywhere in the Standard, but they're convenient references for pointing out things in the cppreference table).
Upvotes: 5