C Почему невозможно перегрузить троичный оператор переполнения стека в систему перегрузки

7 мая 2020 Автор: Forexguru

Почему нельзя перегружать троичный оператор?
Почему невозможно перегрузить троичный оператор ‘?:’?
Я часто использую троичный оператор для объединения операторов if, и мне любопытно, почему разработчики языка решили запретить перегружать этот оператор. Я искал объяснение, почему в C ++ Operator Overloading, но не нашел объяснения, почему это невозможно. Единственная информация, которую предоставляет сноска, состоит в том, что она не может быть перегружена.

Мое первоначальное предположение состоит в том, что перегрузка оператора почти всегда будет нарушать номер один или два из принципов, приведенных в ссылке выше. Значение перегрузки редко будет очевидным или ясным, или оно будет отклоняться от своей первоначальной известной семантики..
Поэтому мой вопрос больше в том, почему это невозможно, а не как, поскольку я знаю, что это невозможно.

5 ответов 5.
Я думаю, что главная причина в то время, что не стоило усилий изобретать новый синтаксис только для этого оператора. Токена нет ?:, поэтому вам нужно создать ряд специальных правил грамматики только для него. (У текущего правила грамматики есть оператор, за которым следует оператор, который является единственным токеном.)
Как мы научились (из опыта) более разумно использовать перегрузку операторов, стало очевидным, что мы действительно не должны были допускать перегрузку && и || либо по причинам, указанным в других ответах, и, вероятно, также не запятой оператора (поскольку перегруженные версии не будут иметь точку последовательности, которую ожидает пользователь).

Почему нельзя перегружать троичный оператор?
Почему невозможно перегрузить троичный оператор ‘?:’?
Я часто использую троичный оператор для объединения операторов if, и мне любопытно, почему разработчики языка решили запретить перегружать этот оператор. Я искал объяснение, почему в C ++ Operator Overloading, но не нашел объяснения, почему это невозможно. Единственная информация, которую предоставляет сноска, состоит в том, что она не может быть перегружена.

Мое первоначальное предположение состоит в том, что перегрузка оператора почти всегда будет нарушать номер один или два из принципов, приведенных в ссылке выше. Значение перегрузки редко будет очевидным или ясным, или оно будет отклоняться от своей первоначальной известной семантики..
Поэтому мой вопрос больше в том, почему это невозможно, а не как, поскольку я знаю, что это невозможно.

5 ответов 5.
Я думаю, что главная причина в то время, что не стоило усилий изобретать новый синтаксис только для этого оператора. Токена нет ?:, поэтому вам нужно создать ряд специальных правил грамматики только для него. (У текущего правила грамматики есть оператор, за которым следует оператор, который является единственным токеном.)
Как мы научились (из опыта) более разумно использовать перегрузку операторов, стало очевидным, что мы действительно не должны были допускать перегрузку && и || либо по причинам, указанным в других ответах, и, вероятно, также не запятой оператора (поскольку перегруженные версии не будут иметь точку последовательности, которую ожидает пользователь).

Так что мотивация поддержать его еще меньше, чем была изначально.
если бы вы могли переопределить троичный оператор, вы должны написать что-то вроде этого:
Чтобы вызвать переопределение, компилятор должен вычислить значение как trueVal, так и falseVal.

Это не то, как работает встроенный троичный оператор — он вычисляет только одно из этих значений, поэтому вы можете написать что-то вроде:
не беспокоясь о непрямом указателе через NULL.
Один из принципов троичного оператора заключается в том, что выражение true / false оценивается только на основе истинности или ложности условного выражения.
В этом примере expr1 оценивается только в том случае, если cond равно true, а expr2 оценивается только в том случае, если cond имеет значение false. Учитывая это, давайте посмотрим, как будет выглядеть сигнатура для троичной перегрузки (здесь используются фиксированные типы вместо шаблона для простоты)
Эта подпись просто не является законной, потому что она нарушает точную семантику, которую я описал.

C Почему невозможно перегрузить троичный оператор переполнения стека в систему перегрузки

Чтобы вызвать этот метод, язык должен был бы оценить и expr1, и expr2, следовательно, они больше не являются условно оцененными. Для поддержки троичного оператора оператору потребуется.
Возьмите лямбду для каждого значения, чтобы оно могло производить их по требованию.

C Почему невозможно перегрузить троичный оператор переполнения стека в систему перегрузки

Это обязательно усложнит вызывающий код, потому что он должен был бы учитывать семантику лямбда-вызовов, когда логически нет лямбды. Тернарному оператору нужно будет возвращать значение, чтобы указать, должен ли компилятор использовать expr1 или expr2..
РЕДАКТИРОВАТЬ.

Некоторые могут утверждать, что отсутствие короткого замыкания в этом сценарии это хорошо. Причина в том, что C ++ уже позволяет нарушать короткое замыкание в перегрузках операторов с помощью || а также &&
Хотя я все еще нахожу это поведение непонятным даже для C++.
По той же причине, по которой вы действительно не должны (хотя и можете) перегружать && или || операторы — это приведет к отключению короткого замыкания на этих операторах (оценивая только необходимую часть, а не все), что может привести к серьезным осложнениям.

Краткий и точный ответ просто «потому что это то, что решил Бьярне».
Хотя аргументы о том, какие операнды должны оцениваться и в какой последовательности дают технически точное описание того, что происходит, они мало что делают (ничего, действительно), чтобы объяснить, почему этот конкретный оператор не может быть перегружен.
В частности, те же основные аргументы одинаково хорошо применимы и к другим операторам, таким как operator && и operator || , Во встроенной версии каждого из этих операторов левый операнд вычисляется, тогда и только тогда, когда это дает 1 для && или 0 для || , правильный операнд оценивается. Аналогично, (встроенный) оператор запятой оценивает свой левый операнд, затем его правый операнд.
В перегруженной версии любого из этих операторов оба операнда всегда оцениваются (в неопределенной последовательности).

C Почему невозможно перегрузить троичный оператор переполнения стека в систему перегрузки

В этом отношении они по существу идентичны перегруженному троичному оператору в этом отношении. Все они теряют одинаковые гарантии относительно того, какие операнды оцениваются и в каком порядке..
Что касается того, почему Бьярне принял это решение: я вижу несколько возможностей.

Во-первых, хотя это технически оператор, троичный оператор в первую очередь предназначен для управления потоком, поэтому его перегрузка будет больше похожа на перегрузку, если или пока, чем на перегрузку большинства других операторов..
Другая возможность состоит в том, что это будет синтаксически безобразно, требуя, чтобы синтаксический анализатор имел дело с чем-то вроде оператора ?:, который требует определения?: В качестве маркера и т. Д. — все это требует довольно серьезных изменений в грамматике Си. По крайней мере, на мой взгляд, этот аргумент выглядит довольно слабым, так как C ++ уже требует гораздо более сложного синтаксического анализатора, чем C, и это изменение действительно будет намного меньше, чем многие другие изменения, которые были сделаны..
Возможно, самый сильный аргумент из всех — просто то, что казалось, что он многого не достигнет.

Поскольку он в основном посвящен управлению потоком, изменение того, что он делает для некоторых типов операндов, вряд ли приведет к чему-то очень полезному.

Похожие статьи

Оставить комментарий

XHTML: Разрешенные теги: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>