Broadcaster/Listener 使用可变参数模板的模式

Broadcaster/Listener pattern using variadic templates

我正在尝试使用可变参数模板实现一种 Broadcaster/Listener 模式:

template <typename... Args>
class WithListeners {
public:
    class Listener {
    public:
        virtual void operator()(Args&&... args) = 0;
    };
private:
    std::list<std::shared_ptr<Listener>> listeners;
public:
    void addListener(std::shared_ptr<Listener> l) {
        if (std::find(listeners.begin(), listeners.end(), l) == listeners.end())
            listeners.push_back(l);
    }
    void removeListener(std::shared_ptr<Listener> l) {
        listeners.remove(l);
    }
    void callListeners(Args&&... args) const {
        for (auto l : listeners) {
            if (l) (*l)(std::forward<Args>(args)...);
        }
    }
};

问题是我可以用 <> 编译它,但不能用 <int>。因此,例如,这不会编译:

class MyClassWithListener : public WithListeners<int>::Listener{
public:
    virtual void operator()(int value) override {
        //my handling code
    }
};

它表示带有覆盖说明符的函数不会覆盖任何基础 class 方法。

您可能认为您的operator()使用了完美转发,但事实并非如此。 Args... 模板参数在考虑 operator() 方法时已完全解析,因此它只将所有参数作为常规 RValue 引用。

因此,您的覆盖需要做同样的事情:

class MyClassWithListener : public WithListeners<int>::Listener{
public:
    virtual void operator()(int&& value) override {
        //my handling code
    }
};

在这种情况下,您最好直接使用直接参数:

template <typename... Args>
class WithListeners {
public:
    class Listener {
    public:
      virtual void operator()(Args... args) = 0;
    };

    void callListeners(Args... args) const {
        for (auto l : listeners) {
            if (l) (*l)(std::move(args)...);
        }
    }
};

因为您仍然可以完全定义监听器的参数:

class MyClassWithListener : public WithListeners<const int&>::Listener{
public:
    virtual void operator()(const int& value) override {
        //my handling code
    }
};