Да, void*
- плохая идея. Тем более, когда задействованные типы исходят от вас, а не от пользователя!
Если различные события передают данные разных типов клиенту, то обеспечение безопасности типов очень полезно для пользователя. Это предотвращает такие вещи, как случайная передача обратного вызова, который ожидает строку, но вызывается с двойным. Вы хотите, чтобы вашим API было трудно злоупотреблять.
Например, вы можете сделать это:
template<class T>
RetCallback subscribe(EventEnum& ev, std::function<void(T)> fn) const;
Абоненты будут указывать тип на сайте вызова:
auto subscriber = Controller->subscribe<std::string>(EventEnum::FooEvent, callback);
Затем вы можете проверить subscribe
, подходит ли EventNum
к этой сигнатуре обратного вызова, или вы даже можете (в зависимости от того, сколько у вас событий и типов данных обратного вызова) иметь разные EventNum
типы для каждого типа данных обратного вызова, так что невозможно даже подписаться на вызов с несовпадающим типом события и сигнатурой обратного вызова, например: https://godbolt.org/g/7xTGiM
notify
должно быть сделано аналогично subscribe
.
Таким образом, любое несоответствие либо невозможно (т. Е. Принудительно скомпилировано), либо сразу обнаруживается в вашем API, а не вызывает неожиданные сбои приведения в дальнейшем в коде пользователя.
Редактировать: Как обсуждалось в комментариях, если закрепление пользователя по значениям события во время компиляции в порядке, вы можете даже создать шаблон для самого номера события: https://godbolt.org/g/9NYVh3