Using function pointer to change function signatures

Hey guys, i have a pointer-to-function variable which is supposed to store 'any type of function' with 'any amount of parameters'. I think this is possible so here is what i've tried so far;
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
#include <iostream>
using namespace std;

void Output(int num = 0) {
	cout << num << endl;
}

class A {
private:
	void (*funcptr)(void);
public:
	template<typename ... Args>
	void set(void func(Args... temp), Args... args) {
		funcptr = new ((void) func(args...));
	}
	void invoke() {
		funcptr(5); // should send the 'args...' but thats a question for later
	}
};

void main() {
	A firstfunc;
	firstfunc.set(Output, 4);
	firstfunc.invoke();
	system("pause");
}


The code is obviously not working but it may help you understand what exactly i am going for in this. The question, in simpler words, is How do i store a function with any number of parameters, to a variable, with which i can call that function later?.
Last edited on
Instead of storing a function pointer you could use std::function to store a lambda that captures the function and all the arguments and calls the function when invoked.
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
#include <iostream>
#include <functional>

using namespace std;

void Output(int num = 0) {
	cout << num << endl;
}

class A {
private:
	std::function<void()> fun;
public:
	template<typename ... Args>
	void set(void func(Args... temp), Args... args) {
		fun = [=](){ func(args...); };
	}
	void invoke() {
		fun();
	}
};

int main() {
	A firstfunc;
	firstfunc.set(Output, 4);
	firstfunc.invoke();
}
Last edited on
Wow, thanks @Peter87, that worked like a charm. Just a small complication, still, i want to set() member function to take 'any' type of parameters, for some reason, it does not work for char * parameter;
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
40
41
42
43
44
45
#include <iostream>
#include <functional>
using namespace std;

class A {
private:
	std::function<void()> fun;
public:
	template<typename ... Args>
	void set(void func(Args... temp), Args... args) {
		fun = [=]() { func(args...); };
	}
	void invoke() {
		fun();
	}
	void test()
	{
		cout << "Passed! " << endl;
	}
};

void Output(int num = 0) {
	cout << num << endl;
}

void names(char *name)
{
	cout << name << endl;
}

void objects(A obj)
{
	obj.test();
}

int main() {
	A firstfunc, secfunc, thirdfunc;
	firstfunc.set(Output, 6); // works
	firstfunc.invoke(); // works
	secfunc.set(objects, firstfunc); // works
	secfunc.invoke(); // works
	thirdfunc.set(names, "Ryan"); // does not work
	thirdfunc.invoke(); // does not work
	system("pause");
}


Actually, i checked int, custom class, float and some other parameters, it works in all of them, but not sure why it does not work for char *, and maybe there is some limitation to this. If so, please let me know.

Thanks once again.
The characters of a string literal are const (i.e. they cannot be modified) so the parameter of your names function should be a pointer to a const char.

1
2
3
4
void names(const char *name)
{
	cout << name << endl;
}
Note that the way the set function has been written the parameter types must match the types of arguments exactly. This will prevent you from passing an int to a function that takes a double, or a string literal to function that takes a std::string. To fix this you can add another template argument for the function type so that it becomes independent of the variadic argument list.

1
2
3
4
	template<typename F, typename ... Args>
	void set(F func, Args... args) {
		fun = [=]() { func(args...); };
	}
Last edited on
Thanks a lot Peter87, that information is pretty darn good. Solved.
Oh wait, how do i provide default values for following parameters?
1
2
3
4
template<typename ... Args>
	void set(void func(Args... temp), Args... args) {
		fun = [=]() { func(args...); };
	}


And in my actual code, i can not use those 2 parameters, the compilation stops with error;

Error LNK2019 unresolved external symbol "public: __thiscall Rects::Rects<int>(unsigned int,unsigned int,unsigned int,unsigned int,char *,void (__cdecl*)(int),int)" (??$?0H@Rects@@QAE@IIIIPADP6AXH@ZH@Z) referenced in function _main Project11 ...path\Project11\Project11\Source.obj 1


Here is my actual constructor;
1
2
3
4
5
6
7
8
9
10
11
12
public:
	template<typename ... Args>
	Rects(unsigned int xPos, unsigned int yPos, unsigned int width, unsigned int height, char *text, void BoundTo(Args...), Args... args);

// Definition;
template<typename ... Args>
Rects::Rects(unsigned int xPos, unsigned int yPos, unsigned int width, unsigned int height, char *text, void BoundTo(Args...), Args... args)
{
        /* ... */
	func = [=]() { BoundTo(args...); };
        /* ... */
}
Last edited on
Making the function type a template argument as I showed in my last post should fix this problem as well.
Alright i figured that out. Moreover, i was using typename template in .cpp (function definitions) file which was causing linker error. Fixed that as well.

Thanks for the help once again Peter!
Registered users can post here. Sign in or register to post.