Подсмотрел у Алексея Пахунова
Все описанное относится к конечным автоматам, но никто не мешает применять эту технику и других подходящих ситуациях.
Лично мне это очень сильно напомнило подходы из BOOST_PP, но есть случаи, когда стоит "повоевать" и вручную...
Есть простой и довольно удобный способ держать список состояний/событий конечного автомата в одном месте. А то обычно они норовят расползтись по разным углам: enum, объявляющий соответствующие константы, массив имен состояний для отладки, большой switch, выбирающий что делать, в зависимости от состояния…
Делается примерно следующее (препроцессорная магия):
После этого можно сами объявлять константы:
А можно – объявить прототипы функций-обработчиков для каждого из состояний:
Или массив имен состояний, удобный для отладки:
Все описанное относится к конечным автоматам, но никто не мешает применять эту технику и других подходящих ситуациях.
Лично мне это очень сильно напомнило подходы из BOOST_PP, но есть случаи, когда стоит "повоевать" и вручную...
Есть простой и довольно удобный способ держать список состояний/событий конечного автомата в одном месте. А то обычно они норовят расползтись по разным углам: enum, объявляющий соответствующие константы, массив имен состояний для отладки, большой switch, выбирающий что делать, в зависимости от состояния…
Делается примерно следующее (препроцессорная магия):
#define FOR_ALL_STATES(Action) \
Action(StateInitial) \
Action(StateInitializing) \
Action(StateReady) \
Action(StateTerminating)
После этого можно сами объявлять константы:
#define DEFINE_ENUM(Name) Name,
enum States {
FOR_ALL_STATES(DEFINE_ENUM)
};
#undef DEFINE_ENUM
А можно – объявить прототипы функций-обработчиков для каждого из состояний:
#define DEFINE_HANDLER(Name) \
States On ##Name(Events Event);
FOR_ALL_STATES(DEFINE_HANDLER)
#undef DEFINE_HANDLER
Или массив имен состояний, удобный для отладки:
#define DEFINE_NAME(Name) #Name,
static const char* StateNames[] = {
FOR_ALL_STATES(DEFINE_NAME)
};
#undef DEFINE_NAME
Комментариев нет:
Отправить комментарий