На этот вопрос нет хороших ответов :-(
потому что большая часть ответа зависит от
- Эффективные цели (что означает «оптимизировать», что неприятно во вложенных переключателях)
- Контекст, в котором будет применяться эта конструкция (каковы конечные потребности приложения)
TokenMacGuy был мудрым, чтобы спросить о целях. Я нашел время, чтобы проверить вопрос и его ответы на французском сайте, и все еще озадачен целями ... Последний ответ Драна Дейна, похоже, указывает на уменьшение количества кода / улучшение читабельности, но давайте рассмотрим наверняка:
- Скорость обработки: не проблема, вложенные переключатели достаточно эффективны, возможно, не более 3-х умножений, чтобы получить индекс для таблицы карты, но, возможно, даже нет.
- Удобочитаемость: да, возможно, проблема, так как число переменных и уровень увеличиваются, начинается комбинаторный взрыв, а также формат оператора switch имеет тенденцию распространять точку ветвления и связанные значения по длинному вертикальному отрезку. В этом случае 3-мерная (или более) таблица инициализируется с помощью fct. pointers объединяет значения разветвления и функцию для вызова в одну строку.
- Написание меньшего количества кода: Извините, здесь не так много помощи; в конце дня мы должны учитывать относительно большое количество комбинаций, и «карта», независимо от ее формы, должна быть где-то записана. Генераторы кода, такие как TokenMacGuy, могут пригодиться, в этом случае это кажется излишним. Генераторы имеют свое место, но я не уверен, что это так. Один из двух случаев: если количество переменных и уровня достаточно мало, генератор не стоит этого (для его настройки требуется больше времени, чем для написания реального кода), если количество переменных и уровней равно важно, что сгенерированный код трудно читать, трудно поддерживать ...)
Вкратце, моя рекомендация в отношении того, чтобы сделать код более читабельным (и немного быстрее писать), - это таблично-матричный подход, описанный на французском сайте.
Это решение состоит из двух частей:
однократная инициализация трехмерного массива (для 3 уровней); (или более «причудливая» структура контейнера, если предпочтительнее: например, дерево). Это делается с помощью кода вроде:
// This is positively more compact / readable
...
FctMap[1][4][0] = fctAlphaOne;
FctMap[1][4][1] = fctAlphaOne;
..
FctMap[3][0][0] = fctBravoCharlie4;
FctMap[3][0][1] = NULL; // impossible case
FctMap[3][0][2] = fctBravoCharlie4; // note how the same fct may serve in mult. places
И относительно простой фрагмент кода, где нужно вызывать функции:
if (FctMap[cond1][cond2][cond3]) {
retVal = FctMap[cond1][cond2][cond3](Arg1, Arg2);
if (retVal < 0)
DoSomething(); // anyway we're leveraging the common api to these fct not the switch alternative ....
}
Случай, который может подсказать один НЕ , использующий вышеупомянутое решение, равен , если пространство комбинации сравнительно редко заполнено (многие «ветви» в «дереве» коммутатора не используются) или , если для некоторых функций требуется другой набор параметров ; Для обоих этих случаев я бы хотел подключить решение, предложенное Джоэлем Гудвином сначала здесь , и которое по существу объединяет различные ключи для нескольких уровней в один более длинный ключ (с символом-разделителем, если необходимо), по сути сведение проблемы обратно к длинному, но одноуровневому переключателю .
Сейчас ...
Реальное обсуждение должно быть о , зачем нам сначала нужно такое отображение / дерево решений . Чтобы ответить на это, к сожалению, необходимо понять истинную природу основного приложения. Конечно, я не говорю, что это свидетельствует о плохом дизайне. Большой раздел диспетчеризации может иметь смысл в некоторых приложениях. Тем не менее, даже с языком C (который авторы французского сайта, по-видимому, дисквалифицировали для объектно-ориентированного дизайна), можно принять объектно-ориентированную методологию и шаблоны. В любом случае, я расходлюсь ...) Вполне возможно, что приложение в целом будет лучше обслуживаться альтернативными шаблонами проектирования, где «информационное дерево о том, что вызывать, когда» будет распределено в нескольких модулях и / или нескольких объектах.
Извините, чтобы говорить об этом в довольно абстрактных терминах, это просто отсутствие специфики приложения ... Суть остается: бросить вызов идее, что нам нужно это большое диспетчерское дерево; подумайте об альтернативных подходах к применению в целом.
Алорс, Бонн Шанс! ; -)