
Комментарии 5
Но и от своего твёрдого убеждения, что реализовывать данную синтаксическую конструкцию нельзя ни как иначе, нежели при помощи таблицы переходов, не отступаю! Всех с наступающим, надеюсь данное чтиво кому нибудь пригодится или будет интересно.
Зачем "намертво" выбирать конкретную деталь реализации, если стандарт языка (например, в случае C++) этого не требует?
Почему не реализовывать наиболее оптимальным в каждой конкретной ситуации образом?
Какой вообще плюс в "выборе намертво - чтобы обязательно через таблицу переходов"?
Формально автор прав, switch не эквивалентен набору if-else, а значит не является синтаксическим сахаром вокруг If. Фактически и Вы правы, ничего не мешает современным компиляторам развернуть и цепочку if-else через таблицу переходов (которая далеко не во всех случаях вообще будет быстрее), а значит и разница не так велика.
А я вот вспомню, что операторы break в ветках switch в наборе языков (как минимум на базе C) опциональны, и хоть чаще это создаёт проблемы из-за забытого break, иногда это используется для полезного, например техники loop unrolling и вот это вот принципиально не эквивалентно If-else цепочкам.
Но и от своего твёрдого убеждения, что реализовывать данную синтаксическую конструкцию нельзя ни как иначе, нежели при помощи таблицы переходов, не отступаю!
Для реализации таблицей переходов следущего switch-a
switch (x) {
case 1014593462573: //...
case 5: //...
case 1113567: //...
}потребуется таблица из 1014593462569 элементов. Это точно не перебор?
Современная Java, например, хитрее (сужу по smali-коду для android) : в зависимости от набора значений в case-ах, порождает 3 разных варианта кода: тривиальный код на сравнениях, либо табличный переход за O(1), либо двоичный поиск в отсортированной компилятором таблице "ключ -> метка" за O(log(N)) в случае, если таблица переходов оказывается слишком разрежённой.
https://stackoverflow.com/questions/60109992/why-is-a-switch-not-optimized-the-same-way-as-chained-if-else-in-c-c – 5 лет назад MSVC и CLang благополучно оптимизировали цепочки if-else.
А нежелание использовать switch-case скорей обусловлено его недоработанностью (где типы, отличные от целочисленных? где интервалы?) в C. Плюс поверх ещё место для ошибок при проваливании из кейса в кейс (благо, в C++ в конце концов сделали [[fallthrough]]). Ну, зато на нём Duff's device можно собрать :-)
Выглядит так, что вы доказали, что ваши оппоненты правы - это действительно сахар.
Таблица переходов будет оптимальной только при определенной структуре значений данных. Разреженные данные все равно приведут к неэффективным сценарием сравнения с частью вариантов.
В то же время if точно так же может быть построен бинарным деревом, чтобы уменьшить количество сравнений.
Более того, для оптимальности может быть полезнее не таблица переходов, а статистика по используемым значениям переходов, чтобы самые частые варианты сравнивались напрямую первыми.
В конечном итоге if тоже может быть оптимизирован автоматически и превратиться в переходы, вероятно компиляторы такое умеют.
Так что да, кажется и в том, что это не важные детали реализации критики тоже правы.
Надо сказать, что на хардварном уровне любое обращение к адресу строится на двоичных переходах.
Операторы «case» и «switch» это не сахар