Simple wrapper for member function pointers with known signature I always wanted to know how to pass member functions as arguments, and then I stumbled across templates that could automatically deduce types, and so I rejoiced! This is used in a Publisher-Subscriber system for a game server. I wanted the subscribing to individual packet 'types' (i.e. by enum) to be simple at the calling site.

/**
* Wrapper struct for callbacks fired when RakNet::Packet*s arrive.
* TargetObj is used to identify this callback by which object it is bound to.
*/
struct PacketCallback
{
    template &lt;typename Obj&gt;
    PacketCallback(void(Obj::*mf)(const RakNet::Packet*), Obj* obj)
        : TargetObj(obj)
    {
        Func = std::bind(mf, obj, std::placeholders::_1);
    }

    std::function&lt;void(const RakNet::Packet*)&gt; Func;
    void* TargetObj = nullptr;
};


Used thus:

class ClientManagementTest : public INetworkSubscriber
{
public:

    virtual void Subscribe(NetworkPublisher* a_networkPublisher) override
    {
        a_networkPublisher-&gt;Register(ID_NEW_INCOMING_CONNECTION,
            PacketCallback(&amp;ClientManagement::OnClientConnected, this));

        a_networkPublisher-&gt;Register(ID_CONNECTION_LOST,
            PacketCallback(&amp;ClientManagement::OnClientDisconnected, this));

        a_networkPublisher-&gt;Register(ID_DISCONNECTION_NOTIFICATION,
            PacketCallback(&amp;ClientManagement::OnClientDisconnected, this));
    }


    virtual void Unsubscribe(NetworkPublisher* a_networkPublisher) override
    {
        a_networkPublisher-&gt;UnregisterAll(this);
    }

    void OnClientConnected(const RakNet::Packet* a_packet)
    {
        printf("Someone connected\n");
    }

    void OnClientDisconnected(const RakNet::Packet* a_packet)
    {
        printf("Someone disconnected\n");
    }

};


Are there any glaring flaws or possible improvements, here? Perhaps something that's incredibly unsafe?

For context, the function pointer is invoked thus, where the publisher stores the callbacks in the form std::map&lt;int, std::vector&lt;PacketCallback&gt;&gt; m_subscribers;:

void NetworkPublisher::NotifySubscribers(int a_packetType, RakNet::Packet* a_packet)
{
    auto it = m_subscribers.find(a_packetType);
    if (it != m_subscribers.end())
    {
        for (int i = 0; i &lt; it-&gt;second.size(); ++i)
        {
            it-&gt;second[i].Func(a_packet);
        }
    }
}


I'm really happy with it, but would appreciate criticism. 

Thanks!
Sorry for the brief answer, typing on phone.

Your NetworkPublisher should have Register(int signal, std::function&lt;void()&gt; callback)

And then simply do:

publisher.Register(WHATEVER_SIGNAL, std::bind(&amp;MyClass::MySignalCallback, this));


This way you dont need the PacketCallback class and your subscriber interface is more generally usable as you can now pass lamdas and free functions as well. Further more your NotifySubscribers will simplify a bit.

Side note: You might want to consider using smart pointers instead of raw pointers. Or references if null is not an allowed argument.

Edit: In reply to comments, this is one way I would consider of doing it:

enum class SignalType{
   NewConnection,
   ConnectionLost
};

const std::array&lt;SignalType,2&gt; AllSignalTypes = {
    SignalType::NewConnection,
    SignalType::ConnectionLost};

class ISubscriber{
public:
    virtual bool supportsSignal(SignalType signalType) const = 0;
    virtual void signal(SignalType signalType, const RakNet::Packet&amp; packet) = 0;
}

class Publisher{
public:
    void registerSubscriber(const std::shared_ptr&lt;ISubscriber&gt;&amp; subscriber){
        for(auto&amp; type : AllSignalTypes){
            if(subscriber-&gt;supportsSignal(type)){
                // TODO: Check for duplicates or change to std::unordered_set&lt;weak_ptr&gt;
                subscribers[type].emplace_back(subscriber);
            }
        }
    }

    void signal(SignalType signalType, const RakNet::Packet&amp; packet){
        forEachLiveSubscriber(signalType, [&amp;packet](const std::shared_ptr&lt;ISubscriber&gt;&amp; subscriber){
            subscriber-&gt;signal(signalType, packet);
            return true;
        });
    }

    void unregisterAll(const ISubscriber&amp; subscriber){
        // Technically not necessary but for good measure
        for(auto&amp; type : AllSignalTypes){
            forEachLiveSubscriber(signalType, [&amp;packet](const std::shared_ptr&lt;ISubscriber&gt;&amp; sharedSubscriber){
                return sharedSubscriber.get() != &amp;subscriber;
            });
        }
    }

private:
    std::unordered_map&lt;SignalType, std::vector&lt;std::weak_ptr&lt;ISubscriber&gt;&gt;&gt; subscribers;

    template&lt;typename Callable&gt;
    void forEachLiveSubscriber(SignalType signalType, Callable&amp;&amp; callback){
        auto&amp; signalSubscribers = subscribers[signalType];

        auto it = signalSubscribers.begin();
        while(it != signalSubscribers.end()){
            auto&amp; strongPtr = it-&gt;lock();
            if(strongPtr &amp;&amp; callback(strongPtr)){
                it++;
            }
            else{
                // The subscriber has destructed without unregistering,
                // Or the callback requested us to remove it.
                it = signalSubscribers.erase(it);
            }
        }
    }
}

class MySubscriber : public ISubscriber{
    bool supportsSignal(SignalType signalType) const override{
        return signalType == NewConnection || signalType == ConnectionLost;
    }

    void signal(SignalType signalType, const RakNet::Packet&amp; packet) override{
        switch(signalType){
            case NewConnection:
                std::cout&lt;&lt;"Someone connected"&lt;&lt;std::endl;
                break;
            case ConnectionLost:
                std::cout&lt;&lt;"Someone lost connection"&lt;&lt;std::endl;
                break;
        }
    }
}


Note that by using shared_ptr we get access to weak_ptr which in turn allows lazy garbage collection of the subscribers. In turn this means that a subscriber doesn't have to unregister if all shared pointers to it just simply die. 

The above code is untested pseudocode. Some assembly may be required :)