0

I want to create an array mapping integer values to member functions so that

(this->*actionMap[i])();

executes the method. In order to populate the array, I would like a method that sets elements of the array to the corresponding action.

I saw in an earlier question that it should use std::function and std::bind but I am not following the syntax, and I do not understand how to declare the array: How to properly pass member function as a parameter

Here is the M(non)WE Note that I want a base class to be able to execute methods on the derived object.

#include <iostream>
using namespace std;
class Base;
typedef void (Base::*Action)();

class Base {
    Action actions[3];
public:
    void setAction(int a, Action act) {
        actions[a] = act;
    }
    void f() { cout << "f"; }
    void go() {
        for (int i = 0;  i < 3; i++)
            (this->*actions[i])();
    }
};

struct Derived : public Base {
    void g() { cout << "g"; }
    void h() { cout << "h"; }
    Derived() {
        setAction(1, f);
        setAction(2, g);
        setAction(1, h);
    }
};

int main() {
    Derived d;
    d.go();
}
Ðаn
  • 10,934
  • 11
  • 59
  • 95
Dov
  • 8,000
  • 8
  • 46
  • 75

1 Answers1

2

execute methods on the derived object.

So you have to have a handle to derived object when you execute the methods. And two of the methods are not in Base::, because they are not inside Base. They are inside Derived, so the pointers could be Derived::*, but that would make no sense and break the model I guess you want to have. I guess you could make your methods g h and f virtual inside Base. But that would again, defeat the purpose, I guess of an observer-like-ish pattern.

What you want to do, is basically easily solved with proper abstraction - std::function and std::bind.

#include <iostream>
#include <array>
#include <functional>

class Base {
    std::array<std::function<void()>, 3> actions;
public:
    void setAction(int a, std::function<void()> act) {
        actions.at(a) = act;
    }
    void f() { std::cout << "f"; }
    void go() {
        for (auto&& action : actions) {
            if (action) {
                action();
            }  
        }
    }
};

struct Derived : public Base {
    void g() { std::cout << "g"; }
    void h() { std::cout << "h"; }
    Derived() {
        setAction(1, std::bind(&Derived::f, this));
        setAction(2, std::bind(&Derived::g, this));
        setAction(1, std::bind(&Derived::h, this));
    }
};

int main() {
    Derived d;
    d.go();
}
KamilCuk
  • 120,984
  • 8
  • 59
  • 111