Search code examples
c++language-lawyerternary-operatorassignment-operatorconditional-operator

Can I assign a value to a conditional expression in C++?


Is it valid to simplify this...

if (bool_b) {
    int_i1 = int_i3;
} else {
    int_i2 = int_i3;
}

..into the following?

(bool_b ? int_i1 : int_i2) = int_i3;

It seems to work on my compiler. But I think the draft C++11 standard: N3337 says it's invalid:

  • conditional-expression:
    • logical-or-expression
    • logical-or-expression ? expression : assignment-expression
  • assignment-expression:
    • conditional-expression
    • logical-or-expression assignment-operator initializer-clause
    • throw-expression

If I understand it well, the part at the left of = should be a logical-or-expression. But even though logical-or-expression are conditional-expressions, the reciprocal is false.


Solution

  • Yes, it's valid if the two alternatives of the ternary operator are both lvalues of the same type.

    N3242 5.16/4 : If the second and third operands are glvalues of the same value category and have the same type, the result is of that type and value category

    The ternary operator is called conditional operator.

    Gramar aspects:

    The following gramar production :

    conditional-expression:
        logical-or-expression
        logical-or-expression ? expression : assignment-expression
    

    allow statements like:

    true ? b : a = 20;      // yields b. if condition would be false, would yield a =20
    true ? b = 11 : a = 21; // yields b=11 
    

    As the gramar shows well the assignement would be limited to one of the branch

    However, if we consider the full chain of gramar productions:

    assignment-expression: 
        logical-or-expression assignment-operator initializer-clause
        ...
    logical-or-expression:
        logical-and-expression
        logical-or-expression || logical-and-expression
    logical-and-expression:
        inclusive-or-expression
        logical-and-expression && inclusive-or-expression
    ...  
    primary-expression: 
        (expression) 
        ...  
    

    So you could then write expressions like :

    (true ? a : b) = 10;    // a and b are lvalues,  a or be are set to 10 depending on the condition