2

Exercise 4.20 of C++ Primer, 5e asks whether the expression iter++->empty(); is legal. Assume that iter is a vector<string>::iterator.

This expression is legal. I compiled it with gcc, and the answers to another question on Stack Overflow have addressed this much. However, I'm confused as to why it is legal.

This answer to a similar question gives the following as an equivalent pair of expressions:

iter->empty();
iter++;

The operator precedence table in my book lists -> as having higher precedence than the postfix ++ operator. This matches the explicit order of operations in the equivalent code above. However, I am used to seeing operators apply to whatever is right next to them. In the case of ->, I expected the compiler would to apply it to ++ (by itself, without iter) and throw an error. In other words, I tried to parenthesize the original expression as iter(++->empty());, which is obviously illegal.

So, it seems like c++ requires compilers to parse expressions in a more complex way than just parenthesizing based on precedence and associativity. Is that right? If there is an easy way to explain how this actually happens, I would like to know about it.

Alan Birtles
  • 32,622
  • 4
  • 31
  • 60
Kevin Bradner
  • 438
  • 4
  • 11
  • 1
    [Why do you think it shouldn't be?](https://en.cppreference.com/w/cpp/string/basic_string/empty) Which container type is `iter` from? – πάντα ῥεῖ Dec 29 '20 at 18:55
  • 1
    [My table](https://en.cppreference.com/w/cpp/language/operator_precedence) says they got equal precedence. – HolyBlackCat Dec 29 '20 at 18:57
  • 2
    Do be careful to avoid confusing "legal" as in "compiles because it is syntactically valid" with "legal" as in "has defined behaviour". – tadman Dec 29 '20 at 18:57
  • I would think the "obviously illegal" approach you think is logical would be a strong argument for why it doesn't do that; that attempt at parsing doesn't make sense, since you can't attach an operator to an operator, it has to attach to an expression, and so `iter++` has to bind first. Also, your book is wrong, or you're misreading it; [postfix `++` has the *same* precedence as `->`](https://en.cppreference.com/w/cpp/language/operator_precedence) (prefix `++` has lower precedence than either, but it's not involved here). – ShadowRanger Dec 29 '20 at 18:57
  • Your equivalent expression is incorrect too, since `iter` must be incremented before `empty` is called. Beginner often get confused about when the pre and post increment side effects occur. – john Dec 29 '20 at 19:05
  • Although looking at the answer you linked it doesn't say the two expressions are equivalent, it just says you should prefer the second version. – john Dec 29 '20 at 19:07
  • @john I read your comment wrong. Deleting. – NathanOliver Dec 29 '20 at 19:09
  • @NathanOliver I guess it could be clearer, too late now – john Dec 29 '20 at 19:10
  • Just to be clear about this, the equivalent sequence would be something like this `auto temp = iter; iter++; temp->empty();` – john Dec 29 '20 at 19:13
  • 1
    I've looked at the precedence table in the C++ Primer and it is definitely wrong and even meaningless on several counts. Postfix ++ has right associativity? Really? I'd like to try what they were smoking. How do you ever interpret this statement? – n. m. could be an AI Dec 29 '20 at 19:28

1 Answers1

5

Per cppreference, ++ and -> have the same precedence and have left to aright associativity. That means that iter++ is executed first, and then ->empty() is applied to the result of iter++, which is just iter (from before the increment) since it is postfix increment.

NathanOliver
  • 171,901
  • 28
  • 288
  • 402
  • Interesting, thanks for the link. This contradicts the table page 166 of C++ Primer, 5th edition. Any chance this was a recent change to the standard? – Kevin Bradner Dec 29 '20 at 19:01
  • @KevinBradner AFAIK, it's always been like this. – NathanOliver Dec 29 '20 at 19:02
  • @KevinBradner Having different precedence for different postfix unary operators wouldn't make a lot of sense (same for prefix ones). – HolyBlackCat Dec 29 '20 at 19:04
  • I was assuming it had to do with associativity. According to my reference, (->) is left associative, and postfix (++) is right associative. I'm not sure how these resolve if the operators are at the same precedence level. – Kevin Bradner Dec 29 '20 at 19:06
  • @KevinBradner this [table](https://www.oreilly.com/library/view/c-primer-fifth/9780133053043/ch04lev1sec12.html)? – Alan Birtles Dec 29 '20 at 19:06
  • @AlanBirtles yes, that seems like the same one. – Kevin Bradner Dec 29 '20 at 19:07
  • @KevinBradner According to cppreference, both have same associativity. I don't think associativity even makes sense for unary operators. – HolyBlackCat Dec 29 '20 at 19:08
  • @KevinBradner I've found a PDF version of the book [here](http://www.charleshouserjr.com/Cplus2.pdf) but am not finding the table at page 166. Do you know what section it is in? – NathanOliver Dec 29 '20 at 19:08
  • @NathanOliver the section is 4.12. Note that it matches the link provided by AlanBirtles above. – Kevin Bradner Dec 29 '20 at 19:09
  • 2
    @KevinBradner Thanks. Looks like a bad table to me. – NathanOliver Dec 29 '20 at 19:10
  • I guess the line above postfix increment is an error or just there to separate the left and right associative operators, overall not the clearest table, the rest looks correct – Alan Birtles Dec 29 '20 at 19:11
  • @HolyBlackCat fair point about the associativity of ++. This link seems relevant: https://stackoverflow.com/questions/12961351/does-it-make-sense-for-unary-operators-to-be-associative – Kevin Bradner Dec 29 '20 at 19:12