Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

How to call a non-static method from a function pointer?

I have a class "Person" like so:

typedef void (*action)();
typedef std::unordered_map<int, action> keybindMap; // maps keycodes to functions

class Person {
    keybindMap keybinds;
    void doSomething();
}

I use this to call the functions at the right times:

iter = keybinds.find(event.key.keysym.sym); // event.key.keysym.sym is the key code
if (iter != keybinds.end())
{
    (*iter->second)(); // call whatever function that key is bound to.
}

To bind a key, I used keybinds.insert_or_assign(SDLK_a, doSomething). However, this doesn’t work (because doSomething is non-static). How do I change the binding code and/or the (*iter->second)() part so that I can call something equivalent to person.doSomething?

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

>Solution :

A non-static method requires an object to call it on. An ordinary function pointer doesn’t have room to hold a reference to an object.

If you change your map to hold std::function instead, you can then use std::bind() or a lambda to associate an object with a method pointer, eg:

using action = std::function<void()>;
using keybindMap = std::unordered_map<int, action>;

class Person {
    keybindMap keybinds;
    void doSomething();
};

... 

Person p, otherP; //must outlive the map...
p.keybinds[...] = [&otherP](){ otherP.doSomething(); } 

...

iter = keybinds.find(event.key.keysym.sym);
if (iter != keybinds.end()) {
    iter->second();
}

On the other hand, if all of the target methods are in the same class/object, you can use a plain method pointer instead of std::function, which will reduce some overhead, eg:

class Person {
    using action = void (Person::*)();
    using keybindMap = std::unordered_map<int, action>; 

    keybindMap keybinds;
    void doSomething();
};

... 

keybinds[...] = &Person::doSomething;

...

iter = keybinds.find(event.key.keysym.sym);
if (iter != keybinds.end()) {
    (this->*(iter->second))();
}
Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading