Альтернатива вложенного переключателя - PullRequest
3 голосов
/ 22 марта 2012

Во время игры с НЛП я столкнулся с небольшой проблемой:

switch(var1)
{
case Variant1_1:
    if( cond1 )
    {
        if( cond2 )
        {
            if( cond3 )
            {
                switch(var2)
                {
                case Variant2_1:
                    return someExpression;
                // another five-six cases
                default:
                    return;
                }
            }
            else // cond3
            {
                switch(var2)
                {
                case Variant2_1:
                    return someExpression;
                // another five-six cases
                default:
                    return;
                }
            } 
        }
        else // cond2
        {
            if( cond3 )
            {
                switch(var2)
                {
                case Variant2_1:
                    return someExpression;
                // another five-six cases
                default:
                    return;
                }
            }
            else // cond3
            {
                switch(var2)
                {
                case Variant2_1:
                    return someExpression;
                // another five-six cases
                default:
                    return;
                }
            } 
        }
    }
    else // cond1
    {
        // same thing

    }
    break;
case Variant1_2:
    // same gigantic tree
    break;
case Variant1_3:
    // here too
    break;
default:
    return;
}

Какие альтернативы для такого "вычислительного дерева"?Единственное, что приходит мне в голову - это какой-то контейнер с деревьями с указателями функций в виде листьев и множеством мелких функций.

Ответы [ 5 ]

4 голосов
/ 22 марта 2012

(язык в щеке) Каждый раз, когда вы встречаете оператор switch в программе на C ++, вы знаете, что упустили возможность наследования.

Существует два способа рефакторинга нескольких параллельных коммутаторов: (1) создание многомерного массива указателей функций и (2) использование варианта шаблона посетителя .

1 голос
/ 22 марта 2012

Я начинаю искать подход, основанный на данных, когда код начинает выглядеть следующим образом.Это может быть так же просто, как таблица или дерево с указателями на функции, как вы предложили.

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

Я часто использую рекурсивное спуск вручнуюпарсеры.Как правило, я создаю класс, содержащий состояние, выставляю одну общедоступную функцию «Parse» и реализую каждое правило как частную функцию-член.Эти функции-члены имеют небольшие размеры и имеют явные имена, поэтому код становится вполне читабельным.Также очень легко написать тесты для него.

1 голос
/ 22 марта 2012

Хороший обходной путь - использование матрицы.

Это будет хорошо работать, если вы знаете, что все условия будут оценены в любом случае.

Создайте многомерный массив, который будет сопоставлять значения true-false с функциями обработки.

Arrayswitch[var1][cond1][cond2][cond3][var2]();
0 голосов
/ 22 марта 2012

То, что вы описываете, это то, что компилятор будет делать из вашего кода в любом случае :) Итак, вы по сути предлагаете вложенный язык программирования, который приводит к закону Гринспуна: «Любая достаточно сложная программа на C или Fortran содержит специальную, неформально заданная, подверженная ошибкам, медленная реализация половины Common Lisp. "

Есть способы написания этого кода, лучше отражающие ваши условия.когда у вас много вложенных if() { if () { if() } } } с, обычно просто пишущих if (!condition) break; или другим экранирующим методом, это упрощает код.не всегда, но много раз.

0 голосов
/ 22 марта 2012

Полиморфизм и хороший дизайн кода.http://www.cs.bu.edu/teaching/cpp/polymorphism/intro/

...