Обновить

Комментарии 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 тоже может быть оптимизирован автоматически и превратиться в переходы, вероятно компиляторы такое умеют.

Так что да, кажется и в том, что это не важные детали реализации критики тоже правы.

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

Зарегистрируйтесь на Хабре, чтобы оставить комментарий

Публикации