Имеет ли смысл унарные операторы быть ассоциативными?

Таблица приоритетов оператора C ++ из http://en.cppreference.com/w/cpp/language/operator_precedence (Я знаю, что это не нормативно, но стандарт не говорит о приоритетности или ассоциативности) помечает унарные операторы как правые / левые ассоциативные.

От обсуждения другого вопроса у меня остались сомнения. Имеет ли смысл унарные операторы быть ассоциативными?

12

Решение

Это просто артефакт того, как ассоциативность получена из грамматики.

причина это дополнение левоассоциативно в том, что одно из произведений для Добавка-выражение является Добавка-выражение + мультипликативный выражение, с аддитивным выражением слева. Итак, когда вы видите:

a + b + c

это должно быть эквивалентно (a + b) + cпотому что единственный способ сопоставить производство с a + b как Добавка-выражение а также c как мультипликативный выражение. a сам по себе является Добавка-выражение, но b + c это не мультипликативный выражение так что a + b + c не соответствует производству, если мы пытаемся взять a как Добавка-выражение.

Если вы еще этого не сделали, я рекомендую вам прочитать главу «Выражения», игнорируя семантику: посмотрите только на грамматические произведения. Тогда вы увидите только как это то, что приоритет и ассоциативность определяются грамматикой. Большая хитрость в том, что каждый тип выражения с «высоким приоритетом» IS-A тип выражения «с низким приоритетом». Так что каждый мультипликативный выражение является Добавка-выражение, но не наоборот, и это то, что делает умножение «связывать крепче», чем сложение.

Префиксные унарные операторы определены в грамматике следующим образом: Унарное выражение: ++ монолитно-выражение и так далее, с оператором слева для префикса и справа для постфикса. Другими словами, мы «вставляем скобки» слева для постфикса и справа для префикса. То есть мы можем сказать, что группировка слева направо для постфиксных операторов и справа налево для префиксных операторов. И действительно, стандарт C ++ говорит именно об этом (5.2 / 1 и 5.3 / 1 в C ++ 03). Это может быть злоупотребление терминологией или, по крайней мере, новая чеканка, обозначающая эту унарную группировку как «ассоциативность». Но это не главное, так как очевидно, что нужно иметь в виду.

Единственное отличие здесь между бинарными и унарными операторами состоит в том, что синтаксис все еще имеет смысл, если бинарные операторы сгруппированы в противоположном направлении, поэтому a - b - c средства a - (b - c), Это было бы удивительно, но никак не повлияло бы на язык. С унарными операторами было бы более чем удивительно группировать !!a как (!!)aязык также должен был бы предоставить имея в виду для под-выражения !!, которого в настоящее время нет. Функциональный язык может придать этому значение: !! может означать функцию, состоящую из ! а также !то есть та же операция, что и static_cast<bool>(), но C ++ не имеет понятия составления функций или операторов. Причина, по которой С ++ не нужно указывать это значение, заключается в том, что ! «группы справа налево». Который (из-за большого трюка в грамматике) является просто еще одним способом сказать, что !! не является синтаксически правильным выражением, поэтому никогда не является подвыражением чего-либо.

Так что да, это делает Имеет смысл сказать, что префиксные операторы группируются справа налево, а постфиксные операторы — слева направо. Но также «очевидно», что так должно быть, из-за других вещей, которые мы знаем о языке C ++.

Кстати, я думаю, что технически говоря на C ++, по крайней мере, postfix ++ является не унарный оператор. Это постфиксный оператор. Но это на самом деле не имеет значения, за исключением того, что это терминология в стандарте, потому что, очевидно, это оператор и у него есть один операнд, поэтому он «унарный» в английском языке.

9

Другие решения

Ассоциативность оператора в случае унарных операторов просто определяет, на какой стороне операнда появляется оператор.

2

Рассмотрим следующий фрагмент кода

int *p;
*p++;

Выражение *p++ можно оценить как (*p)++ (увеличивая объект, на который указывает p) или *(p++) (указывая на следующий объект, указанный p).

Поскольку унарные операторы ассоциативны справа, выражение *p++ будет оцениваться как *(p++), (Я придумал это во время чтения Керниган и Ричи.)

Кажется, что приоритет и ассоциативность были изменены и постфикс ++ имеет более высокий приоритет, чем разыменование * оператор.

Согласно C11 вышеупомянутое выражение будет оцениваться как *(p++),

Я надеюсь, что это делает более понятным, почему унарные операторы имеют ассоциативность.

Благодаря Люциан Григоре за указание на это.

2

Не уверен, но если следующее было верно, да.

++i--

а как нет и выкидывает ошибку

lvalue required as increment operand

Все поведение унарного оператора можно объяснить только с точки зрения приоритета.

1