这个用例来自于想要实现一个编译时事件总线数据结构,该结构只专门为提供的模板参数监听/注册/注销。
从一个简单的实现开始,假设我们有以下类 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
}
};
当然除非有更好的办法?这可能吗?
最佳答案
我会创建一个类来处理监听器/事件:
template <typename Listener, Event>
class EventHandler {
std::vector<Listener*> mListeners;
public:
void registerListener(Listener& listener);
void unregisterListener(Listener& listener);
void sendEvent(Event event);
};
然后,您处理所有问题的类将是:
template <typename ... Ts>
class EventBus : Ts...
{
public:
using Ts::registerListener...; // Requires C++17
using Ts::unregisterListener...; // Prior that you have to do it with recursion
using Ts::sendEvent...; // class EventBus<T, Rest...> : T, EventBus<Rest...>
};
使用方法:
EventBus<EventHandler<AListener, AEvent>, EventHandler<BListener, BEvent>> eventBus;
顺便说一句,Event
可能依赖于 Listener
,因此使用 typename Listener::Event
似乎是合适的并删除所有 Event
模板参数。
关于c++ - 使用模板类型为该模板类型生成唯一的成员名称,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54123196/