I have a class member function that needs to call other class member functions depending on an integer value, like this:
class foo {
public:
foo() {
mTestMap[1] = (*this).test1;
mTestMap[2] = (*this).test2;
mTestMap[3] = (*this).test3;
}
bool test1 () {}
bool test2 () {}
bool test3 () {}
bool execute_test(int test_num) {
if (mTestMap.count(test_num) > 0)
return mTestMap[test_num]();
return false;
}
std::map<int,std::function<bool()>> mTestMap;
};
The problem is, this code results in a compilation error:
Error C3867 'foo::test1': non-standard syntax; use '&' to create a pointer to member
What am I doing wrong? I know that I can assign a member function through a pointer to a specific object to a std::function
. Something similar works if the map and the assignment occur outside the class. Why not from inside the class?
std::function<bool()>
This std::function
wraps a callable object that takes no parameters and which returns a bool
. That's what this means.
bool test1 () {}
You'll be surprised to learn that this is really not a function that takes no parameters and which returns a bool
. It is a class method that takes no parameters and returns a bool. Big difference. Hence, the compilation error.
There are two basic approaches to correctly use this kind of a dispatch:
The simplest one is to use std::bind
:
mTestMap[1] = std::bind(&foo::test1, this);
mTestMap[2] = std::bind(&foo::test2, this);
mTestMap[3] = std::bind(&foo::test3, this);
A variation of this would use lambdas, but that amounts to the same thing. This is the simplest change. However if instances of this class get copied or moved, this is going to go south, very, very quickly.
Use a map of class method pointers. This requires more work:
std::map<int, bool (foo::*)()> mTestMap;
// ...
mTestMap[1] = &foo::test1;
mTestMap[2] = &foo::test2;
mTestMap[3] = &foo::test3;
// ...
bool execute_test(int test_num) {
if (mTestMap.count(test_num) > 0)
return (this->*mTestMap[test_num])();
return false;
With this approach there will be fewer unexpected surprises after an instance of this class gets copied or moved.