Return type of '?:' (ternary conditional operator)

Why does the first return a reference?

int x = 1;
int y = 2;
(x > y ? x : y) = 100;

While the second does not?

int x = 1;
long y = 2;
(x > y ? x : y) = 100;

Actually, the second did not compile at all - "not lvalue left of assignment".


Solution 1:

Expressions don't have return types, they have a type and - as it's known in the latest C++ standard - a value category.

A conditional expression can be an lvalue or an rvalue. This is its value category. (This is somewhat of a simplification, in C++11 we have lvalues, xvalues and prvalues.)

In very broad and simple terms, an lvalue refers to an object in memory and an rvalue is just a value that may not necessarily be attached to an object in memory.

An assignment expression assigns a value to an object so the thing being assigned to must be an lvalue.

For a conditional expression (?:) to be an lvalue (again, in broad and simple terms), the second and third operands must be lvalues of the same type. This is because the type and value category of a conditional expression is determined at compile time and must be appropriate whether or not the condition is true. If one of the operands must be converted to a different type to match the other then the conditional expression cannot be an lvalue as the result of this conversion would not be an lvalue.

ISO/IEC 14882:2011 references:

3.10 [basic.lval] Lvalues and rvalues (about value categories)

5.15 [expr.cond] Conditional operator (rules for what type and value category a conditional expression has)

5.17 [expr.ass] Assignment and compound assignment operators (requirement that the l.h.s. of an assignment must be a modifiable lvalue)

Solution 2:

The type of the ternary ?: expression is the common type of its second and third argument. If both types are the same, you get a reference back. If they are convertable to each other, one gets chosen and the other gets converted (promoted in this case). Since you can't return an lvalue reference to a temporary (the converted / promoted variable), its type is a value type.