Избегать повторяющегося и простого случая переключения в C / C ++?

В интернете я нашел фрагмент кода, который имеет действительно простую цель, но в нем используется безобразный подход. Предположительно, автор использует случай переключения, чтобы определить, принадлежат ли несколько (несмежных) значений ранее определенного Enum в их области видимости. Если это так, функция возвращает true и это все. Остальное возвращается false,

Это выглядит практически так:

switch(value) {
case ONE:
case TWO:
/* many similar lines later */
case TWENTY:
case TWENTY_FIVE:
/* an afternoon later */
case ONE_HUNDRED:
return true;
default:
return false;
}

Их использование регистра переключателя оправдано наличием мгновенного поиска благодаря таблице переходов, сгенерированной компилятором (хотя таблица переходов не обязательно означает мгновенный поиск из того, что я собрал). Тем не менее, это генерирует бесчисленные ненужные строки кода.

Я читал о встраивании функций и использовании массива указателей функций, но я не знаю, как использовать это в таком конкретном случае.

Как мне избежать написания много линии case X: с таким простым делом (без каламбура) как это?

2

Решение

Эффективное вычисление логического значения на основе некоторого связанного целого числа — задача для битовой перестановки:

const unsigned long long ps[2] = {0x28208a20a08a28ac, 0x800228a202088288};

bool is_prime(unsigned x)
{
return (x < 128) && ((ps[x >> 6] >> (x & 63)) & 1);
}

Если вы посмотрите на двоичное представление чисел, хранящихся в массиве, 1 бит означает простое число, а 0 бит означает составное число:

   2    8    2    0    8    a    2    0    a    0    8    a    2    8    a    c
0010 1000 0010 0000 1000 1010 0010 0000 1010 0000 1000 1010 0010 1000 1010 1100
59             47     41           31        23     17      11      5   2
61        53           43     37        29           19     13       7    3

Чтобы увеличить это до более чем 128 чисел, просто увеличьте размер массива и исправьте < сравнение в is_prime, Константы 6 и 63 вытекают из количества бит в unsigned long long,

9

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

Избегать повторяющегося и простого случая переключения в C / C ++?

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

В этом конкретном случае вы можете просто сделать это:

return (value < 100);

Я не понимаю, почему утверждение о переключении 100+ линий лучше … даже если оно быстрее (что является лишь предположением при отсутствии реальных измерений), оно будет только немного так или иначе быстрее, так ли это заслуживает всей этой суеты? Нет или, по крайней мере, нет в большинстве реальных сценариев. Если приложение настолько критично, оптимизация такого кода в любом случае лучше выполнить на ассемблере.

Что касается встраивания функций и массивов указателей функций — я не уверен, что понимаю вопросы, но, тем не менее, если вы не понимаете, как использовать такие функции для оптимизации, не используйте их … позвольте компилятору вместо этого оптимизируйте свой код.

3

Поскольку у вас есть нечетное перечисление, пропуская значения, вы можете инвертировать свое решение.
Но вам нужно будет объявить пропущенные номера (если пропускает только несколько).

if( value > ONE_HUNDRED || value < ONE )
{
return false;
}
else
{
switch(value)
{
case SKIPPED_FIRST:
case SKIPPED_SECOND:
{
return false;
}
break;
default:
{
return true;
}
}
}
0
По вопросам рекламы [email protected]