25

After debugging I found that ternary operator ?: does not have priority. My question is why?
I have the following code:

bool T = true;
cout << ((T == true) ? "true" : "false") << endl;
cout << (T == true) ? "true" : "false";

Output:

true
1

live demo: http://ideone.com/Tkvt9q

Quest
  • 2,764
  • 1
  • 22
  • 44

7 Answers7

35

The conditional operator does have a precedence (albeit slightly complicated by its ternary nature); but that precedence is very low. Since it's lower than <<, the second is parsed as

(cout << (T == true)) ? "true" : "false";

streaming the boolean value of T == true, then evaluating (but ignoring) the expression "true". Most compilers will give a warning, if you enable a sensible set of warnings.

Here is a reference to the operator precedences, showing << with a higher precedence (7) than ?: (15): http://en.cppreference.com/w/cpp/language/operator_precedence

Mike Seymour
  • 249,747
  • 28
  • 448
  • 644
29

The conditional operator ? : does have precedence - it's number 15 in this table, lower than << and >> operators, which are number seven.

The rule that I follow to avoid mistakes like that is to use parentheses when in doubt. The rationale is simple: if you need to look up the priority in a table, good chances are that the readers of your code, including yourself, would need to do the same thing at some later time.

Sergey Kalinichenko
  • 714,442
  • 84
  • 1,110
  • 1,523
  • 8
    +1 just for that rule. Too many programmers omit parantheses unnecessary for the compiler, but useful to human readers. – Andy Thomas Aug 06 '14 at 14:50
  • 1
    You always want to please the human reader god otherwise, his wrath might strike you. – Nico Aug 06 '14 at 19:40
  • 4
    @AndyThomas There is of course a balance. Too many parens and you may as well write LISP – Cruncher Aug 06 '14 at 19:47
12

A lot of the other questions answer why you are seeing that behavior but they don't answer why the ternary operator has low priority.

The decision was made to have low ternary priority because we don't want the code

a<d ? 10 : 100

to end up meaning

a < (d ? 10 : 100) //BAD: not what we normally expect

we want it to mean

(a<d) ? 10 : 100 

Low priority for the ternary operator achieves this goal. This sort of thing is the whole reason for operator precedence that you find in languages. The goal is to make it convenient to write expressions that are expected to be normal in the language. Right? If not, it could just be left to right with parentheses. Which would be annoying to use and you'd quickly propose some sort of convenient operator precedence.

Brian C.
  • 6,455
  • 3
  • 32
  • 42
  • 1
    Thousands of LISPers would disagree with your last statement ;-) – bdesham Aug 06 '14 at 19:50
  • I think the alternative solution used in LISP to the problem of precedence is excellent. Any design decision is a compromise. I can see how one would start designing syntax and go down the path of C->perl/python/ruby where you think "I'm going to design a great easy to use syntax". They have done a great job with choices like the precedence for the ternary operator. From the C position, LISP looks like it is dodging the question of precedence when from inside of LISP it is a total, simple, easily learned solution. – Brian C. Jun 02 '15 at 14:10
7

It is true that the ?: operator has no clearly defined priority. But the example in question does not really illustrate that. The relative priorities of << and ?: are rather unambiguous. All your example shows is that the priority of << is higher than the priority of ?:.

As for the more general issue of the priority of ?: operator... ?: operator has relatively convoluted format, compared to other operators: it has three non-uniform operands. Because of that non-uniformity the part before ? has different syntactic grouping properties than the parts after ?.

After all, "priorities" are a derivative trick invented to simplify visualization and memorization of syntactic groupings defined by the grammar. Not all C++ operators conform to that trick though. The ?: operator happens to be the one that does not, which is why a properly written priority table will typically have a side note for ?: operator, explaining its unusual properties. Again, the part before the ? has different priority than the parts after the ?, which is why it is impossible to properly place the ?: operator into a linear table of priorities.

Unless I'm forgetting something, the ?: operator is the only operator without a straightforwardly definable priority.

P.S. Things with ?: operator were even worse in C. C++-related changes to the grammar made ?: to conform better to the idea of linear priority.

AnT stands with Russia
  • 312,472
  • 42
  • 525
  • 765
  • I’m just curious—regarding your postscript, do you have an example of a ternary expression that would be parsed differently in C++ than in C? – bdesham Aug 06 '14 at 19:49
  • 3
    @bdesham: The classic, often quoted example is `a ? b = c : d = e`. In C it is parsed as `(a ? (b = c) : d) = e`, while in C++ it is `a ? (b = c) : (d = e)`. (See the "Notes" section of the page linked in Mike Seymour's answer) – AnT stands with Russia Aug 06 '14 at 20:10
  • I've often thought that the proper way to parse the "?: operator" would be to regard "?" as an operator whose second operand was a special compiler-internal type which was yielded by the ":" operator. Likewise, in a language where relational operators do not work on Boolean types, relational operators could yield a special type which is implicitly convertible to Boolean, or can be accepted by another relational operator (thus allowing `x < y < z` to be parsed as "y is strictly greater than x and less than z" without weird gamesmanship in the parser). – supercat Aug 06 '14 at 20:39
  • @supercat The type of the ":" operation would not be special, it would be the type of either of its operands, or at least the type they can both be converted into, and that type would have to be compatible with whatever operator's going to be used next. `AST* term = bFloat ? new ASTInteger(0) : new ASTDouble(0.0) ;` – cardiff space man Aug 06 '14 at 23:57
  • @cardiffspaceman: I would suggest that `:` should return an operand which comprises a *pair of code paths*, and that the `?` operator, given a `bool` on the left and the aforementioned special operator on the right, would invoke one of the code paths. – supercat Aug 09 '14 at 20:55
4

Like the other answers note, the << operator has higher precedence than the ? operator. Here is my opinion on why it is so.

Using bit-shift (<<) with the choice operator makes sense; for example

(T == true) ? (whatever << 1) : (whatever << 2)
(T == true) ? whatever << 1 : whatever << 2 // same as above

When the designers of C++ invented operator overloading, they decided to reuse the bit-shift operator << as a streaming operator. Had they introduced another, completely new streaming operator (e.g. <<<), it would get very low precedence, so the code would work as expected:

cout <<< (T == true) ? "true" : "false";

However, introducing a new operator just for it to be overloaded would undermine the idea of usefulness of operator overloading, which was a fascinating idea back then. So they decided to use an old (existing) operator.

anatolyg
  • 26,506
  • 9
  • 60
  • 134
2

The ternary conditional operator does have a precedence, except that it's at the bottom of the list (value 15). Only throw and , (comma) have a lesser precedence. See this reference for C++ Operator Precedence.

Marius Bancila
  • 16,053
  • 9
  • 49
  • 91
0

because of brackets, firstly statement (T == true) is evaluated, then comes the left shift operator and 1 which was evaluated earlier is sent to cout. later, the ternary operator evaluates "true" but it is ignored.

all in all, ternary operator has precedence, but one of the lowest.

macfij
  • 3,093
  • 1
  • 19
  • 24