尝试使用void *参数获取std :: function

时间:2014-06-22 12:44:10

标签: c++

我正在尝试实现一个通用的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));

1 个答案:

答案 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;
};