Ole Wagner
Ole Wagner

Reputation: 37

Calling array elements that are pointer-to-member functions

I have an array of pointer-to-member functions in class A and need to access the elements in class B. My problem is either always getting a 1 returned when trying to access an array element or types not matching with each other.

What I've got so far is:

A.h:

#include <vector>

class A {

public:
    typedef void(*func_ptr)(void);

    A();

    void func1();
    void func2();
    void func3();

    std::vector<void(A::*)()> aFuncs;

private:
    void appendFunc(void(A::*function)());

};

A.cpp

#include "A.h"

void A::func1 {...}
void A::func2 {...}
void A::func3 {...}

void A::appendFunc(void(A::*function)()) {
    aFuncs.push_back(function);
}

A::A() {
    appendFunc(&A::func1);
    appendFunc(&A::func2);
    appendFunc(&A::func3);
}

B.h

#include "A.h"

class B {

    A a;

    void test(int value);

};

B.cpp

#include "B.h"

void B::test(int value) {
    // here i need to access the elements of the array aFuncs, so that i can 
    // call the functions of A
    // something like
    a.aFuncs[value];
}

The problem here e.g. is, that a.aFuncs[value] always returns 1 if I use it like this.

The only thing that worked for me so far is:

void B::test(int value) {
    typedef void (a::*fn)();

    fn funcPtr = &a::func1;

    (a.*funcPtr)();
}

But that solution is not using the array so not really helpful right now. Can someone help me with this problem? Is there something fundamental im not understanding?

Upvotes: 0

Views: 114

Answers (3)

Nicko Po
Nicko Po

Reputation: 727

You can also use an alternative method by leveraging std::function if your compiler supports it:

std::array<std::function<void(Foo&)>, 3> a = {
    &Foo::one,
    &Foo::two,
    &Foo::three
};

and then calling with:

foo.a[0](foo);

Upvotes: 0

NathanOliver
NathanOliver

Reputation: 180510

You need to use a twice in order to call the function. Once to access the vector and then again to call the function. That monstrosity looks like

void B::test(int value) {
    (a.*a.aFuncs[value])();
}

To make it cleaner you can copy the function pointer into a variable and then use that function pointer to call the function. That would look like

void B::test(int value) {
    auto func = a.aFuncs[value];
    (a.*func)();
}

And you can see it working at this Live Example.

Upvotes: 2

0x5453
0x5453

Reputation: 13589

(a.*aFuncs[value])() works if aFuncs is global. In your example you should be able to do (a.*a.aFuncs[value])().

#include <iostream>
#include <array>
struct Foo {
    int one()   { std::cout << "one\n"; return 1; }
    int two()   { std::cout << "two\n"; return 2; }
    int three() { std::cout << "three\n"; return 3; }
};
std::array<int(Foo::*)(), 3> a = {{
    &Foo::one,
    &Foo::two,
    &Foo::three,
}};
int main() {
    Foo f;
    std::cout << "1: " << (f.*a[0])() << "\n";
    std::cout << "2: " << (f.*a[1])() << "\n";
    std::cout << "3: " << (f.*a[2])() << "\n";
}

Output:

one
1: 1
two
2: 2
three
3: 3

https://ideone.com/dd5TWP

Upvotes: 0

Related Questions