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
How to Use C Source Files in a C++ Project
Is Returning a 2-Tuple Less Efficient Than Std::Pair
How to Disable Exceptions in Stl
C++ Meta-Programming Doxygen Documentation
What Happens When Queryperformancecounter Is Called
Interfaces VS Templates for Dependency Injection in C++
How to Define Template Function Within Template Class in *.Inl File
Should We Still Be Optimizing "In the Small"
Calculating Large Factorials in C++
Linking Boost Library with Boost_Use_Static_Lib Off on Windows
Using Zeromq Together with Boost::Asio
Double to String Without Scientific Notation or Trailing Zeros, Efficiently
"Enum Class" Emulation or Solid Alternative for Msvc 10.0
Is Array Name a Constant Pointer in C++