我正在尝试使用可变参数模板实现某种广播者/侦听器模式:
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
}
};
它说带有覆盖说明符的函数不会覆盖任何基类方法。
您可能认为您的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
}
};