Обычный подход заключается в сохранении указателя на условную функцию. Вы реализуете набор условий в виде отдельных функций и прикрепляете указатель к нужному условию в таблице. Каждая функция проверяет заданный набор условий. Вы перебираете список, пока одна из указанных функций не вернет true. Конечно, «текущее состояние» можно использовать как часть условий, что устраняет необходимость в двумерном массиве.
struct {
bool(*test)(); //the condition
void(*onsuccess)(); //event
} condition;
Это может быть неэффективно, если условия часто повторяются в цепочке, например:
ev1: (a && b && c)
ev2: (a && !b && c)
ev3: (a && b && d)
ev4: (a && !b && !c)
ev5: (!a)
(большинство событий тестируют a отдельно, если тестирование для a требует больших вычислительных ресурсов, это займет гораздо больше процессорного времени, чем необходимо).
В этом случае вам придется переназначить список condition_set -> event в единое дерево решений — это намного сложнее поддерживать, но более эффективно использовать ЦП:
a:
b:
c: ev1
d: ev3
!b:
c: ev2
!c: ev4
!a: ev5
Это, конечно, больше не может быть простым одномерным списком, но вместо этого требуется древовидная структура, скажем, разветвленный связанный список:
struct {
bool(*test)(); //the condition
void(*onsuccess)(); //event (if any)
condition* next_sibling; //other conditions dependent on parent but independent from this one,
condition* first_child; //other conditions dependent on this one,
} condition;
NULL для любого из указателей означает «нет такого элемента» (кроме «теста», который не может быть нулевым). И, конечно же, для обхода списка требуется рекурсия.
person
SF.
schedule
01.04.2011