Я работаю над библиотекой конечных автоматов с этими публичными методами:
template <typename STATE_T>
void add_state(); // allocate STATE_T on heap - STATE_T must derive from state
template <typename FROM_STATE_T, typename TO_STATE_T>
void link_state(std::function<bool()> cond, unsigned int priority);
// search for base state pointer that can be dynamically caste d to STATE_T* type, set this state as the beginning state
template <typename STATE_T>
void begin_state();
void execute();
//STATE_T must be a user defined state class that inherits from the base state class.
Я выбрал реализацию во время выполнения, а не во время компиляции, потому что интерфейс был бы более сложным при использовании переменных параметров шаблона для состояний. Однако есть ограничения, которые я хочу применить, чтобы программист не вносил ошибок при реализации своего конечного автомата.
Вот ограничения, которые я хочу применить:
Утверждение прерывает программу и четко придерживается этих ограничений, но является ли это правильным выбором?
Возможно нарушение 1,2,3, и fsm по-прежнему находится в допустимом состоянии (просто ничего не делать), но мне не нравится идея неявной обработки их, потому что она вводит ложное чувство безопасности, скрывая ошибки программиста.
Если я выбрасываю исключения для 1,2,3, и программист перехватывает их, тогда fsm все еще может находиться в допустимом состоянии, позволяя запустить некорректно сформированный fsm.
5 это то, что не должно быть сделано. я должен обработать это, или оставить это как UB?
Какой механизм будет наиболее подходящим для этих ограничений?
Это довольно типичная проблема обработки ошибок. Ответ обычно зависит от затрат. Какова стоимость проблемы, оставшейся незамеченной? Какова стоимость программы, которая прерывается из-за исключения?
В большинстве случаев стоимость сбоя программы не так велика. Пользователь просто перезапустит его. В этом случае вы должны пойти на необработанное исключение. Таким образом, вы быстро заметите ошибки, исправите их и в итоге получите лучшую программу.
Существует гибридный подход: в сборке DEBUG обработайте ошибку с помощью окна сообщения «Ошибка подтверждения» (обычно это делается с помощью макроса ASSERT ()), но в сборке выпуска обработайте ошибку без вывода сообщений. Это, однако, позволяет проблеме оставаться незамеченной на клиентских компьютерах, часто вызывая другие ошибки, которые трудно найти.
Наконец, о ваших заботах, что программист может обработать исключение: это не то, о чем вы должны думать. Вы указали на фатальную ошибку, если программист игнорирует ее, это его вина.
Других решений пока нет …