C++: почему iter++-›empty() допустим?

В упражнении 4.20 из C++ Primer, 5e задается вопрос, допустимо ли выражение iter++->empty();. Предположим, что iter является vector<string>::iterator.

Это выражение является законным. Я скомпилировал его с помощью gcc, и ответы на еще один вопрос о переполнении стека обращался к этому много. Однако я не понимаю, почему это законно.

Этот ответ на аналогичный вопрос дает следующее как эквивалентную пару выражений:

iter->empty();
iter++;

В таблице приоритетов операторов в моей книге указано, что -> имеет более высокий приоритет, чем постфиксный оператор ++. Это соответствует явному порядку операций в эквивалентном коде выше. Однако я привык видеть, что операторы применяются ко всему, что находится рядом с ними. В случае с -> я ожидал, что компилятор применит его к ++ (сам по себе, без iter) и выдаст ошибку. Другими словами, я попытался заключить исходное выражение в скобки как iter(++->empty());, что явно недопустимо.

Итак, похоже, что С++ требует от компиляторов более сложного разбора выражений, чем просто заключение в скобки на основе приоритета и ассоциативности. Это правильно? Если есть простой способ объяснить, как это происходит на самом деле, я хотел бы знать об этом.


person Kevin Bradner    schedule 29.12.2020    source источник
comment
Как вы думаете, почему этого не должно быть? Какой тип контейнера iter откуда?   -  person πάντα ῥεῖ    schedule 29.12.2020
comment
Моя таблица говорит, что они имеют одинаковый приоритет.   -  person HolyBlackCat    schedule 29.12.2020
comment
Будьте осторожны, чтобы не спутать юридический как в компиляции, потому что он синтаксически действителен с юридическим, как в имеет определенное поведение.   -  person tadman    schedule 29.12.2020
comment
Я бы подумал, что явно незаконный подход, который вы считаете логичным, будет сильным аргументом в пользу того, почему он этого не делает; эта попытка синтаксического анализа не имеет смысла, поскольку вы не можете присоединить оператор к оператору, он должен быть присоединен к выражению, и поэтому iter++ должен выполнить привязку первым. Кроме того, ваша книга неверна, или вы неправильно ее читаете; постфикс ++ имеет тот же приоритет, что и -> ( префикс ++ имеет более низкий приоритет, чем любой из них, но здесь он не задействован).   -  person ShadowRanger    schedule 29.12.2020
comment
Ваше эквивалентное выражение также неверно, поскольку iter должно быть увеличено до вызова empty. Новички часто путаются в том, когда возникают побочные эффекты до и после инкремента.   -  person john    schedule 29.12.2020
comment
Хотя, глядя на ответ, который вы связали, он не говорит, что два выражения эквивалентны, он просто говорит, что вы должны предпочесть вторую версию.   -  person john    schedule 29.12.2020
comment
@john Я неправильно прочитал твой комментарий. Удаление.   -  person NathanOliver    schedule 29.12.2020
comment
@NathanOliver Я думаю, это могло бы быть яснее, слишком поздно   -  person john    schedule 29.12.2020
comment
Чтобы было ясно, эквивалентная последовательность будет выглядеть примерно так: auto temp = iter; iter++; temp->empty();   -  person john    schedule 29.12.2020
comment
Я просмотрел таблицу приоритетов в C++ Primer, и она определенно неверна и даже бессмысленна по нескольким причинам. Postfix++ имеет правильную ассоциативность? Действительно? Я хотел бы попробовать, что они курили. Как вы интерпретируете это утверждение?   -  person n. 1.8e9-where's-my-share m.    schedule 29.12.2020


Ответы (1)


По cppreference, ++ и -> имеют одинаковый приоритет и левостороннюю ассоциативность. Это означает, что сначала выполняется iter++, а затем ->empty() применяется к результату iter++, что равно iter (до приращения), поскольку это постфиксное приращение.

person NathanOliver    schedule 29.12.2020
comment
Интересно, спасибо за ссылку. Это противоречит странице 166 таблицы C++ Primer, 5-е издание. Есть вероятность, что это было недавнее изменение стандарта? - person Kevin Bradner; 29.12.2020
comment
@KevinBradner Насколько я знаю, так было всегда. - person NathanOliver; 29.12.2020
comment
@KevinBradner Разный приоритет для разных постфиксных унарных операторов не имеет большого смысла (то же самое и для префиксных). - person HolyBlackCat; 29.12.2020
comment
Я предполагал, что это связано с ассоциативностью. Согласно моей ссылке, (-›) ассоциативен слева, а постфикс (++) ассоциативен справа. Я не уверен, как это разрешается, если операторы имеют один и тот же уровень приоритета. - person Kevin Bradner; 29.12.2020
comment
@KevinBradner эта таблица? - person Alan Birtles; 29.12.2020
comment
@AlanBirtles да, это похоже на то же самое. - person Kevin Bradner; 29.12.2020
comment
@KevinBradner Согласно cppreference, оба имеют одинаковую ассоциативность. Я не думаю, что ассоциативность имеет смысл даже для унарных операторов. - person HolyBlackCat; 29.12.2020
comment
@KevinBradner Я нашел PDF-версию книги здесь, но не могу найти таблицу по адресу стр. 166. Вы знаете, в каком разделе он находится? - person NathanOliver; 29.12.2020
comment
@NathanOliver раздел 4.12. Обратите внимание, что она соответствует ссылке, предоставленной AlanBirtles выше. - person Kevin Bradner; 29.12.2020
comment
@KevinBradner Спасибо. Мне кажется плохой стол. - person NathanOliver; 29.12.2020
comment
Я предполагаю, что строка выше приращения постфикса является ошибкой или просто предназначена для разделения левого и правого ассоциативных операторов, в целом не самая четкая таблица, остальное выглядит правильно - person Alan Birtles; 29.12.2020
comment
@HolyBlackCat справедливо указывает на ассоциативность ++. Эта ссылка кажется актуальной: stackoverflow.com/questions/12961351/ - person Kevin Bradner; 29.12.2020