1

How do I properly pass member function as a parameter?

MyCode:

#include <iostream>

using namespace std;

class Test
{
public:
    int add(int a, int b)
    {
        return a + b;
    }
    int sub(int a, int b)
    {
        return a - b;
    }
    typedef int (*funcPtr)(int a, int b);
    int myFunc(funcPtr func, int a, int b)
    {
        return func(a, b);
    }
    void setup()
    {
        cout << myFunc(&Test::add, 5, 3) << endl;
        cout << myFunc(&Test::sub, 5, 3) << endl;
    }
};

int main()
{
    Test test;
    test.setup();
}

Result:

Error: Cannot initialize a parameter of type 'Test::funcPtr' (aka 'int ()(int, int)') with an rvalue of type 'int (Test::)(int, int)'

Expected Result:

8
2
Zack Lee
  • 2,784
  • 6
  • 35
  • 77

3 Answers3

3

Your methods should be "regular" functions. add static to them to allow to use them with function pointers:

class Test
{
public:
    static int add(int a, int b)
    {
        return a + b;
    }
    static int sub(int a, int b)
    {
        return a - b;
    }
// ...
};

If you really pointer on method, you should replace int (*funcPtr)(int a, int b) by int (Test::*funcPtr)(int a, int b) and use something like that instead:

class Test
{
public:
    int add(int a, int b)
    {
        return a + b;
    }
    int sub(int a, int b)
    {
        return a - b;
    }
    typedef int (Test::*funcPtr)(int a, int b);
    int myFunc(funcPtr func, int a, int b)
    {
        return (this->*func)(a, b);
    }
    void setup()
    {
        cout << myFunc(&Test::add, 5, 3) << endl;
        cout << myFunc(&Test::sub, 5, 3) << endl;
    }
};
Jarod42
  • 203,559
  • 14
  • 181
  • 302
  • So is it not possible to pass member functions? – Zack Lee Jul 13 '19 at 14:49
  • @ZackLee it is possible, but in your example you do not use `this` so it is not clear if you really need it. If you really need a member function then there is no enough information in your question - if you want to pass member function to be called with `this` later or you want to pass `this` with it so even non member can call it later. – Slava Jul 13 '19 at 14:50
  • If you add 3rd way - passing lambda with captured this so method can be called as regular function )and describe the difference) IMHO that will make your answer complete. – Slava Jul 13 '19 at 15:03
1

You should read about std:: function and std::bind. The first thing will allow you to store a function pointer with multiple form (Functor, lamda, binded), and the second will allow you to bind parameters to your function call (In your case, you want to bind the instance of the class that is needed to call your function).

std:: function<int(int, int)> func = std::bind(&Class::Method, instancePtr, std::placeholders::_1, std:: placeholders::_2);
int result = func(a, b);

However, in your context, your methods should be marked as static (They are not using any non-static member of your class), but the example and the explanation I provided answer to your base question

Adrien Givry
  • 956
  • 7
  • 18
0

Firstly, based on your question the best solution here will be without using the pointer instead declare your methods as static and call them directly as given below.

That solution will generate the right results without using the complexity of pointers.

Simple is better if you do not need to use pointers it is better to not use them. code will be more readable as well.

Following code works i tested it:

#include <iostream>

using namespace std;



class Test
{
public:
  static  int add(int a, int b)
    {
        return a + b;
    }
   static int sub(int a, int b)
    {
        return a - b;
    }


    void setup()
    {
        cout << add( 5, 3) << endl;
        cout << sub(5, 3) << endl;
    }

};

int main()
{
    Test test;
    test.setup();
}
A 786
  • 488
  • 1
  • 6
  • 16