Как избежать switch case при множественном выборе?
От: alx7235  
Дата: 30.04.11 12:47
Оценка:
Привет.
Допустим я имею 100 функций, которые должны вызываться при получении определенного значения, т.е.

switch (a)
{
case 1:
f_1();
break;

case 300:
f_300();
break;

case 500:
f_500();
break;

case 654:
f_654();
break;
....
//всего 100 case-ов
.....
.....
};
Значений 100 и они не идут подряд.
Можно ли избежать такой громоздкой конструкции?
Re: Как избежать switch case при множественном выборе?
От: BulatZiganshin  
Дата: 30.04.11 12:51
Оценка: +1
Здравствуйте, alx7235, Вы писали:

A>Можно ли избежать такой громоздкой конструкции?


в чём её громоздкость для тебя?
Люди, я люблю вас! Будьте бдительны!!!
Re: Как избежать switch case при множественном выборе?
От: okman Беларусь https://searchinform.ru/
Дата: 30.04.11 12:59
Оценка: 1 (1)
Здравствуйте, alx7235, Вы писали:

A>Привет.

A>Допустим я имею 100 функций, которые должны вызываться при получении определенного значения, т.е.

A>switch (a)

A>{
A>case 1:
A>f_1();
A>break;

A>case 300:

A>f_300();
A>break;

A>case 500:

A>f_500();
A>break;

A>case 654:

A>f_654();
A>break;
A>....
A>//всего 100 case-ов
A>.....
A>.....
A>};
A>Значений 100 и они не идут подряд.
A>Можно ли избежать такой громоздкой конструкции?

Можно применить std::map (отображение) с a в виде ключей и указателями на соответствующие
функции в виде значений. Тогда вместо switch/case будет просто бинарный поиск в map.
Возможно, это будет работать даже быстрее.
Re: Как избежать switch case при множественном выборе?
От: Brutalix  
Дата: 30.04.11 12:59
Оценка: +1
Здравствуйте, alx7235, Вы писали:

A>Привет.

A>Допустим я имею 100 функций, которые должны вызываться при получении определенного значения, т.е.

A>switch (a)

A>{
A>case 1:
A>f_1();
A>break;

A>//всего 100 case-ов

A>.....
A>.....
A>};
A>Значений 100 и они не идут подряд.
A>Можно ли избежать такой громоздкой конструкции?

Можно, например, с помощью виртуальных функций (но есть шанс, что долбежа потребуется еще больше).
Или можно, забабахать например std::map<тип_определенного_значения, указатель_на_функцию> f, и потом вызывать что-нить типа такого f[a]()
Но, как говорил дедушка Фрейд — сны, они иногда, просто сны иногда switch тоже вполне не плох
Re: Как избежать switch case при множественном выборе?
От: uzhas Ниоткуда  
Дата: 30.04.11 13:04
Оценка:
Здравствуйте, alx7235, Вы писали:

A>Можно ли избежать такой громоздкой конструкции?

путей несколько
1) заменить на if\else
2) засунуть все функции в std::map
typedef std::map<int, functionType> FunctionMap;
FunctionMap FillAllCases()
{
  FunctionMap result;
  result[1] = &f_1;
  result[300] = &f_300;
  result[500] = &f_500;
  result[654] = &f_654;
  return result;
}

std::map<int, functionType> cases = FillAllCases();
//use iterators if you like
if (cases.count(a))
{
  return cases[a]();
}
// default section, function does not exist

если функции имеют разные сигнатуры, то можно поиграться с boost(tr1)::bind (чтобы адаптировать к единому интерфейсу) и засунуть boost(tr1)::function в std::map

3)...999) Применить какой-нибудь OOP паттерн
Re[2]: Как избежать switch case при множественном выборе?
От: uzhas Ниоткуда  
Дата: 30.04.11 13:26
Оценка:
Здравствуйте, okman, Вы писали:

O>Тогда вместо switch/case будет просто бинарный поиск в map.

O>Возможно, это будет работать даже быстрее.
лично я в этом сомневаюсь, т.к. компилятор может jump-table использовать или теоретически хешированный контейнер
http://stackoverflow.com/questions/2129718/switch-optimization-for-many-cases-guarantees-equal-access-time-for-any-case-c
Re[3]: Как избежать switch case при множественном выборе?
От: okman Беларусь https://searchinform.ru/
Дата: 30.04.11 13:41
Оценка:
Здравствуйте, uzhas, Вы писали:

U>Здравствуйте, okman, Вы писали:


O>>Тогда вместо switch/case будет просто бинарный поиск в map.

O>>Возможно, это будет работать даже быстрее.
U>лично я в этом сомневаюсь, т.к. компилятор может jump-table использовать или теоретически хешированный контейнер
U>http://stackoverflow.com/questions/2129718/switch-optimization-for-many-cases-guarantees-equal-access-time-for-any-case-c

Это было бы неплохим вопросом для собеседования.
Re: Как избежать switch case при множественном выборе?
От: Skipy Rich Россия  
Дата: 30.04.11 13:46
Оценка: :)))
Здравствуйте, alx7235, Вы писали:

A>Допустим я имею 100 функций

A>Значений 100 и они не идут подряд.
A>Можно ли избежать такой громоздкой конструкции?

Boost.Preprocessor
BOOST_PP_SEQ_FOR_EACH
т.е. можно задать список значений, а потом макросами разворачивать его в различные конструкции.
Re[2]: Как избежать switch case при множественном выборе?
От: Skipy Rich Россия  
Дата: 30.04.11 15:49
Оценка: +1
uzhas, можешь прокомментировать улыбочку?
скорость switch-а оптимизации не требует, поэтому я сделал вывод, что требуется уменьшить кол-во писанины, что вполне достигается указанными макросами.
Re: Как избежать switch case при множественном выборе?
От: Геннадий Васильев Россия http://www.livejournal.com/users/gesha_x
Дата: 01.05.11 02:30
Оценка: 2 (2) +1
Здравствуйте, alx7235, Вы писали:

A>Привет.

A>Допустим я имею 100 функций, которые должны вызываться при получении определенного значения, т.е.

[...]

A>Значений 100 и они не идут подряд.

A>Можно ли избежать такой громоздкой конструкции?

Скорее всего — нет, поскольку тебе так или иначе придётся где-то записать соответствие между значением и именем функции, а будет это в форме:

case 1: f_1(); break;


или в форме:

someMap[1] = &f_1;


...по-моему, никакой разницы.

Можно немного облегчить писанину, добавив макрос:

#define FUNC_BY_VALUE(val, func) case val: func(); break;

...
switch(a) {
  FUNC_BY_VALUE( 1, f_1 );
  FUNC_BY_VALUE( 100, f_100 );
  ...
}


То есть сложность сопровождения такого списка в любом случае будет пропорциональна количеству пар "значение-функция", будь это скрипты, мап или свитч. Если список не меняется или меняется редко, ИМХО, switch — оптимальное решение.

А с точки зрения оптимизации... Тут вопрос спорный, вполне вероятно, что компилятор вставит что-то вроде бинарного поиска по упорядоченному списку констант, и соответственно, std::map не даст выигрыша, хотя заморочек добавит.

На мой взгляд, единственная ситуация, которая оправдывает применение "хранилища" для такой диспетчеризации — это предоставление возможности модифицировать такой список извне. Тогда — да, вполне имеет смысл завести что-то вроде std::map, к которому будет доступ через какие-нибудь registerFunction(int, Func)/unregisterFunction(int) и т.п.
Я знаю только две бесконечные вещи — Вселенную и человеческую глупость, и я не совсем уверен насчёт Вселенной. (c) А. Эйнштейн
P.S.: Винодельческие провинции — это есть рулез!
Re: Как избежать switch case при множественном выборе?
От: LaptevVV Россия  
Дата: 02.05.11 11:28
Оценка:
Здравствуйте, alx7235, Вы писали:
A>Допустим я имею 100 функций, которые должны вызываться при получении определенного значения, т.е.
A>Значений 100 и они не идут подряд.
A>Можно ли избежать такой громоздкой конструкции?
1. Хеш-таблица. Элементом таблицы является либо-либо:
а) объект-функтор
б) указатель-на функцию.
Ключом — число.
Основная работа — на этапе инициализации — заполнение таблицы.
На этапе вызова все выливается в 1 строку — вызов элемента хеш-таблицы по ключу.

Если допустимы некоторые потери памяти, то вместо хеш-таблицы можно использовать массив (или вектор). Число — это индекс.
Значение элемента массива — см. выше.

Ну, или map использовать, как тут уже писали.
Хочешь быть счастливым — будь им!
Без булдырабыз!!!
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.