c++ - 使用模板类型为该模板类型生成唯一的成员名称

标签 c++ templates c++17

这个用例来自于想要实现一个编译时事件总线数据结构,该结构只专门为提供的模板参数监听/注册/注销。

从一个简单的实现开始,假设我们有以下类 AListenerAEventBListenerBEvent .

我希望我的 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/

相关文章:

c++ - 在存在异常的情况下使用 for_each? std::exception_list

c++ - 有没有一种方法可以在不使用两个 for 循环的情况下迭代两个容器

c++ - 带有加密 std::string 的 sqlite 查询(无法识别的 token )

c++ - 为什么在 C++11 的开发过程中改变了变量的定义?

python - Python中是否有用于纯文本文件的 native 模板系统?

c++ - 统一扩展两个参数包

c++ - 为什么我的字符串标记在我的 c++ bison 程序中最终减少时会换行?

c++ - 我丢失的 Edge 在哪里?

c++ - 如何通过静态结构数组专门化模板函数

c++ - 如何避免 C++17 中的虚拟继承?