How can I pass a void function as a parameter

Hi,

How can I pass a function as a parameter?

I have a class that I'm trying to reuse and one of the methods in this class need to take three parameters, two ints and a function. In other words I want to be able to call a custom function every time this method is invoked when used in other classes. The function I want to call will not return any values, its a void function.

In my Class:
1
2
3
4
5
6
7
8
9
10
11
void Utility::someFunction(int var1, int var2, void customFunction)
{
  int num1 = var1;
  int num2 = var2;
  //do some verification here
  ...
  if()
  {
    // call customFunction here
  }
}



Usage in an other class:
1
2
Utility *myUtility;
myUtility->someFunction(5, 6, someCustomFunctionCall);


Thanks

Something like this:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
#include <iostream>
#include <functional>
#include <cstdio>

struct utility
{
    template< typename FUNCTION, typename... ARGS >
    void some_function( int a, int b, FUNCTION custom_function, ARGS... args )
    {
        if( a < b )
        {
            // call custom function
            const auto fn = std::bind( custom_function, args... ) ;
            fn() ;
        }
    }
};

struct foo
{
    void operator() ( int x, double y ) const
    { std::cout << "foo::operator() (" << x << ',' << y << ")\n" ; }
};

int main()
{
    utility u ;

    u.some_function( 1, 2, std::puts, "hello world!" ) ;

    u.some_function( 3, 4, [] { std::cout << "main::anonymous_lambda\n" ; } ) ;

    u.some_function( 5, 6, foo{}, 12345, 67.89 ) ;
}

http://coliru.stacked-crooked.com/a/82f09ceb4d34260f
old c-style way of doing it:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
#include <iostream>

using namespace std;

void pfunc1()
{
	cout << "pfunc1 called" << endl;
}

void pfunc2(int x, int y)
{
	cout << "pfunc2 called - x = " << x << " and y = " << y << endl;
}

void myfunc1(void (*pfunc)())
{
	pfunc();
}

void myfunc2(int x, int y, void (*pfunc)(int, int))
{
	pfunc(x, y);
}

// or simplifying:
typedef void (*mypfunc)(int, int);
void myfunc3(int x, int y, mypfunc pf)
{
	pf(x, y);
}

int main()
{
	myfunc1(pfunc1);
	myfunc2(2, 3, pfunc2);
	myfunc3(7, 88, pfunc2);
}
Thank you all for your reply, I will give it a try.
@tipaye
I tried one of your examples and works just fine but when I try to do the same thing using classes I get an error that says:
reference to non-static member function must be called; did you mean to call it with no arguments?
error: cannot initialize a parameter of type 'void (*)()' with an rvalue of type 'void'
Utility->myfunc2(2, 3, myFunction);


ONE OF YOUR EXAMPLES: Which woks fine
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
#include <iostream>
using namespace std;

void myFunction()
{
	cout << "This function has been called" << endl;
}

void myfunc2(int x, int y, void (*pfunc)())
{
    pfunc();
	
}

int main()
{
	myfunc2(2, 3, myFunction);
        return 0;
}


MY CLASS: Which does not work

Utility Class:
1
2
3
4
5
6
7
8
9
10
void Utility::myfunc2(int var1, int var2, void (*pfunc)())
{
  int num1 = var1;
  int num2 = var2;

  if(num1 < num2)
  {
    pfunc();
  }
}



OtherClass:
1
2
3
4
5
6
7
8
9
#include "Utility"

void OtherClass::myFunction()
{
	cout << "This function has been called" << endl;
}

Utility *myUtility;
myUtility->myfunc2(2, 3, myFunction);


Any idea why this is not working when used within classes?

Again, I get the following errors:
reference to non-static member function must be called; did you mean to call it with no arguments?
error: cannot initialize a parameter of type 'void (*)()' with an rvalue of type 'void'
myUtility->myfunc2(2, 3, myFunction);


Last edited on
You're right, you can't do that - myFunction is a member of OtherClass and only has meaning when properly scoped (OtherClass::myFunction). To use it as a function pointer the way you want, I think myFunction has to be a static member, which means it can only access other static members, but at least you can take it's address:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
#include <iostream>

using namespace std;

class MyClass
{
	static int y;
	int x;
public:
	MyClass(int _x) : x(_x) { cout << "MyClass(" << x << ")" << endl; }
	void showX() { cout << "x is " << x << endl; }
	static void changeY(int y);
};

int MyClass::y = 0;

void MyClass::changeY(int _y)
{
	y = _y;
	cout << "y is " << y << endl;
}

void myFunc(int y, void (*func)(int))
{
	func(y);
}

void myFunc2(void (*fn)())
{
	fn();
}

int main()
{
	MyClass mc(3);
	// myFunc2(&mc.showX); is impossible
	myFunc(77, MyClass::changeY); // pointer to changeY
	return 0;
}

Please forgive the contrived nature of this code, it's been a long day.

An alternative is the pointer to member syntax, but it's a tad clumsy - I've copied some illustrative code from Thinking in C++ Volume 1 chapter 11 here:
1
2
3
4
5
6
7
8
9
10
//: C11:PmemFunDefinition.cpp
class Simple2 {
public:
int f(float) const { return 1; }
};
int (Simple2::*fp)(float) const;
int (Simple2::*fp2)(float) const = &Simple2::f;
int main() {
fp = &Simple2::f;
} ///:~ 


Ultimately, if you're not trying the sort of quick and dirty experiment I assumed you were, I suggest taking time to examine the newer paradigm as proposed by @JLBorges
Thank you all for your help I will try to figure this out using the example given here. Thanks
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
#include <iostream>
#include <functional>

struct utility
{
    template< typename FUNCTION, typename... ARGS >
    void some_function( int a, int b, FUNCTION custom_function, ARGS... args )
    {
        if( a < b )
        {
            // call custom function
            const auto fn = std::bind( custom_function, args... ) ;
            fn() ;
        }
    }
};

int main()
{
    utility u ;

    struct other_class
    {
        void my_function() { std::cout << "other_class::my_function(" << this << ")\n" ; }
        int another_function( int a ) const
        {
            std::cout << "other_class::another_function(" << this << ',' << a << ")\n" ;
            return a*a ;
        }
    };

    other_class object ;
    std::cout << "address of object: " << &object << '\n' ;

    u.some_function( 1, 2, &other_class::my_function, &object ) ;
    u.some_function( 3, 4, &other_class::another_function, &object, -7 ) ;
}

http://coliru.stacked-crooked.com/a/afee357e4e3963e8
@JLBorges - You code does what I need, I was just trying to see if there was something simpler since there are some C++ concepts in your code I still don't fully understand (looking into those concepts right now).

Templeates
struts
auto ...

Thanks a lot
Topic archived. No new replies allowed.