Этот вариант использования исходит из желания реализовать структуру данных шины событий времени компиляции, которая только прослушивает / регистрирует / отменяет регистрацию специально для предоставленных аргументов шаблона.
Начиная с наивной реализации, скажем, у нас есть следующие классы AListener
, AEvent
, BListener
, BEvent
.
Я хочу, чтобы мой EventBus
класс выглядел так:
class EventBus {
std::vector<AListener*> aListeners;
std::vector<BListener*> bListeners;
public:
void registerListener(AListener& listener);
void unregisterListener(AListener& listener);
void sendEvent(AEvent event);
void registerListener(BListener& listener);
void unregisterListener(BListener& listener);
void sendEvent(BEvent event);
};
Есть ли способ, которым я могу шаблонизировать его и рекурсивно построить класс? Например:
EventBus<AListener, AEvent, BListener, BEvent> eventBus;
AListener aListener;
eventBus.registerListener(aListener);
AEvent aEvent;
eventBus.sendEvent(aEvent);
BListener bListener;
eventBus.registerListener(bListener);
BEvent bEvent;
eventBus.sendEvent(bEvent);
Желательно было бы сделать новый vector
для каждого типа слушателя, потому что было бы неэффективно помещать все указатели в один список, так как длинный список неактуальных слушателей будет пустой тратой производительности. Поскольку в шине событий будет проходить множество событий, важна производительность. Желательно перебирать только те, которые нам нужны.
Наконец, предположим, что мы не будем специализировать какого-либо слушателя, поэтому нам не нужно беспокоиться о наследовании, все классы в списке шаблонов считаются окончательными.
Моя проблема:
Как мне обойти название? Хотя я предполагаю, что специализировать шаблоны в рекурсивном определении с помощью перегрузки методов это нормально, потому что, надеюсь, компилятор сделает идеальную вещь ... Я не уверен, как обрабатывать разные имена членов.
Мой план состоял в том, чтобы взять список и вытащить двух членов, примерно так ( ПРИМЕЧАНИЕ. Это псевдокод, который почти наверняка не компилируется, или, если это происходит, просто случайно ) :
// Pseudocodey C++ template rough idea
template <typename Listener, typename Event, typename Args...>
class EventBus : public EventBus<Args...> {
// ???
public:
void registerListener(Listener& listener) {
// emplace back
}
void unregisterListener(Listener& listener) {
// erase remove
}
void sendEvent(Event event) {
// send for each
}
};
Конечно, если нет лучшего способа? Это возможно?