我正在尝试实现一个通用的Messenger回调类。它基本上是字符串到通用成员函数向量的映射。
std::map<Message, std::vector<std::function<void()>>> _receivers;
该类具有静态函数,基本上允许您将枚举消息注册到成员函数,如下所示:
Messenger::GetInstance()->RegisterObserver(Message::QUIT, std::bind(&System::OnQuit, this));
然后,只要消息在某处广播,就会发生回调。
Messenger::GetInstance()->Broadcast(Message::QUIT);
实施如下。
class Messenger
{
public:
template <typename Receiver>
void RegisterObserver(Message msg, Receiver&& receiver)
{
_receivers[msg].push_back(std::forward<Receiver>(receiver));
}
static Messenger* GetInstance();
void Broadcast(Message msg) const
{
for (const auto& obs : _receivers.at(msg)) obs();
}
void Broadcast(Message msg, void* param) const;
{
for (const auto& obs : _receivers.at(msg)) obs(param); // Does NOT work
}
~Messenger();
private:
Messenger() { };
std::map<Message, std::vector<std::function<void()>>> _receivers;
static Messenger* _instance;
};
实施效果很好,没有参数。
现在我还需要这个来处理void *参数,这样我就可以在广告中传递任何内容,以便在回调中调用它。
这就是我想要实现的目标。
Messenger::GetInstance()->Broadcast(Message::QUIT, *param);
非常感谢任何建议或解决方案。这将有助于我保持设计理智。
我尝试将地图更改为 -
std::map<Message, std::list<std::function<void(void*)>>> _receivers;
然后将呼叫签名更改为 void CallbackName(void * param)。但是我收到错误
error C2064: term does not evaluate to a function taking 1 arguments
可能是因为:
Messenger::GetInstance()->RegisterObserver(Message::QUIT, std::bind(&System::OnQuit, this));
答案 0 :(得分:0)
您可以创建2个地图,并使用2个注册方法。 如果您想要相同的名称,可以使用SFINAE作为以下内容:Live example
class Messenger
{
public:
template <typename Receiver>
auto RegisterObserver(Message msg, Receiver&& receiver) -> decltype(receiver(), void())
{
_receivers0[msg].push_back(std::forward<Receiver>(receiver));
}
template <typename Receiver>
auto RegisterObserver(Message msg, Receiver&& receiver) -> decltype(receiver(nullptr), void())
{
_receivers1[msg].push_back(std::forward<Receiver>(receiver));
}
// Others methods
private:
std::map<Message, std::vector<std::function<void()>>> _receivers0;
std::map<Message, std::vector<std::function<void(void*)>>> _receivers1;
};