Std::Map of Member Function Pointers

std::map of member function pointers?

This is about the simplest I can come up with. Note no error checking, and the map could probably usefully be made static.

#include <map>
#include <iostream>
#include <string>
using namespace std;

struct A {
typedef int (A::*MFP)(int);
std::map <string, MFP> fmap;

int f( int x ) { return x + 1; }
int g( int x ) { return x + 2; }

A() {
fmap.insert( std::make_pair( "f", &A::f ));
fmap.insert( std::make_pair( "g", &A::g ));
}

int Call( const string & s, int x ) {
MFP fp = fmap[s];
return (this->*fp)(x);
}
};

int main() {
A a;
cout << a.Call( "f", 0 ) << endl;
cout << a.Call( "g", 0 ) << endl;
}

C++ Map of string and member function pointer

See std::map::insert and std::map for value_type

myMap.insert(std::map<std::string, myFunc>::value_type("test", &Test::TestFunc));

and for operator[]

myMap["test"] = &Test::TestFunc;

You cannot use a pointer to member function without an object. You can use the pointer to member function with an object of type Test

Test t;
myFunc f = myMap["test"];
std::string s = (t.*f)("Hello, world!");

or with a pointer to type Test

Test *p = new Test();
myFunc f = myMap["test"];
std::string s = (p->*f)("Hello, world!");

See also C++ FAQ - Pointers to member functions

C++ map of member function pointers of different classes

In order to do this all my classes inherit an Object class which only has default constructor, virtual destructor and a virtual ToString() const method.

This is a bad solution for storing polymorphic functions with similar signatures.

Here are two better solutions:

'1. Implement your function pointers as specializations of a base interface (Object in your case). Then, in the client code store the interfaces themselves:

struct Object { virtual void Execute() = 0; }

/// old: map<Object*, void (Object::*)()> mapOfMethodPointers;
/// new:
std::vector<Object*> objects;
objects[10]->Execute(); // execution is agnostic of whichever instance you you use

In this solution, Execute would resolve to A::Execute, as defined below:

class A : public Object
{
void AFunc();
public:
virtual void Execute() override { AFunc(); }
};

With this solution, you do not need a function map (because the virtual table of Object is essentially a function map).

'2. Implement your function map in terms of generic functions, then fill it with lambdas:

Code:

/// old: map<Object*, void (Object::*)()> mapOfMethodPointers;
/// new:
map<Object*, std::function<void()>> mapOfMethodPointers;

// filling the map:
class A // not needed: public Object
{
public:
void AFunc(); // this is our interesting function

string ToString() const override;
};

A obj;
mapOfMethodPointers[&obj] = [&obj]() { obj.AFunc(); };

How to store methods as function pointers in a map container?

You can use std::function with a lambda or std::bind :

class reader
{
std::map<std::string, std::function<void()>> functionCallMap;

void readA() { std::cout << "reading A\n"; };
void readB() { std::cout << "reading B\n"; };

public:
reader()
{
functionCallMap["A"] = [this]() { readA(); };
functionCallMap["B"] = std::bind(&reader::readB, this);
}

void read()
{
functionCallMap["A"]();
functionCallMap["B"]();
}
};

C++ map of events and member function pointers

Madness lies, this way: Don't bind callbacks to specific classes. Instead, use a std::function<Signature> object and create suitable function objects: when you need to operate on different classes, you also need to operate on objects of different types. Using a std::function<...> should do the trick, e.g.:

std::map<std::string, std::function<void()>> operations;
operations["talk"] = std::bind(&ChildA::Talk, ChildA());
operations["walk"] = std::bind(&ChildB::Walk, ChildB());
operations["talk"]();

How do I insert a member-function pointer into a map?

In order for a member function pointer to be callable you must bind it to an object. Thus, provided a Manager object (e.g., Manager m) you can use std::bind to bind a member function (e.g., void Manager::foo(std::string const&)) and then insert it in your std::map as follows:

struct Manager {
void foo(std::string const& str) { std::cout << str << std::endl; }
};

int main() {
std::map<std::string, std::function<void(std::string const&)>> cMap;
Manager m;
cMap.insert(std::make_pair("test", std::bind(&Manager::foo, &m, std::placeholders::_1)));
cMap["test"]("Hello, world!");
}

LIVE DEMO



Related Topics



Leave a reply



Submit