C++: Function pointer to functions with variable number of arguments
Solution 1
You could use std::function<>
and std::bind()
.
#include <functional>
using std::placeholders::_1;
typedef std::function<bool(MyClass&)> my_fun_t;
my_fun_t my_fun;
if (condition1)
my_fun = std::bind(&MyClass::function_one, _1);
else if (condition2)
my_fun = std::bind(&MyClass::function_two, _1, a, b);
else if (condition3)
my_fun = std::bind(&MyClass::function_three, _1, a, b, c);
else if (condition4)
my_fun = std::bind(&MyClass::function_four, _1, a, b, c, d);
while (my_fun(my_class)) { ... }
These assumes you will use C++11. If you can't use C++11 but can use TR1, replace all std::
with std::tr1::
. There is also a Boost implementation.
Solution 2
This works for me:
#include <iostream>
#include <cstdarg>
using namespace std;
class MyInterface
{
public:
virtual bool func(int argc, ...) = 0;
};
class MyImpl : public MyInterface
{
public:
virtual bool func(int argc, ...);
};
bool MyImpl::func(int argc, ...)
{
va_list varargs;
va_start(varargs,argc);
cout << "Arguments passed:" << endl;
for(int i = 0; i < argc; ++i)
{
// expect double values
double val = va_arg(varargs,double);
cout << val << endl;
}
va_end(varargs);
return true;
}
typedef bool (MyInterface::*MyFunc)(int, ...);
int main() {
MyImpl impl;
MyInterface* interface = &impl;
MyFunc pfunc = &MyInterface::func;
if(!(interface->*pfunc)(2,double(3.14),double(2.72)))
{
return 1;
}
return 0;
}
Output:
Arguments passed:
3.14
2.72
Obviously you CAN declare and use function pointers for (member-)functions using variable arguments.
Solution 3
You want std::function
, a polymorphic function object, and std::bind
to create function objects by binding arguments to the parameters of other functors.
If you can't use C++11, then boost::function
and boost::bind
are equivalent, although slightly more restrictive.
std::function<bool()> my_fun;
if (condition1)
my_fun = std::bind(&MyClass::function_one, my_class);
else if (condition2)
my_fun = std::bind(&MyClass::function_two, my_class, a, b);
else if (condition3)
my_fun = std::bind(&MyClass::function_three, my_class, a, b, c);
else if (condition4)
my_fun = std::bind(&MyClass::function_four, my_class, a, b, c, d);
while (my_fun())
{ ... }
Solution 4
I'm trying to figure out a way of how to be able to assign a function pointer to functions with different number of arguments.
You can’t. Function pointers are specific to one function signature. This is entirely logical: how would you invoke such a function? (Yes, C allows invoking functions without specifying in their declaration how many parameters the function has, but this doesn’t work in C++ since it subverts the type system.)
Are functoids something I should look at?
Generally yes, but they don’t solve this problem.
Related videos on Youtube
jaho
Updated on October 24, 2022Comments
-
jaho over 1 year
I'm trying to figure out a way of how to be able to assign a function pointer to functions with different number of arguments.
I have a while loop which takes a number of different functions as a conditional statement, so instead of writing multiple while loops with exactly the same code inside I'd like to have one with a function pointer. All the functions are of format
bool f(...)
. I think some code will best illustrate what I mean:int a, b, c, d; MyClass* my_class; typedef bool (MyClass::*my_fun_t)(); my_fun_t my_fun; if (condition1) my_fun = &MyClass::function_one(); else if (condition2) my_fun = &MyClass::function_two(a, b); else if (condition3) my_fun = &MyClass::function_three(a, b, c); else if (condition4) my_fun = &MyClass::function_four(a, b, c, d); while ((my_class->*my_fun)()) { ... }
Now this obviously doesn't work because the functions have different signatures. Is it at all possible to make it work in a similar fashion? Are functoids something I should look at?
-
user268396 almost 12 yearsIf you can use C++ 11 then you can also use lambda functions and pull the variables from the enclosing lexical scope. Whichever you prefer, I guess.
-
Mike Seymour almost 12 years@user268396: Probably. For the time being, I'm stuck with a compiler that doesn't support lambdas, so I don't know much about them.
-
πάντα ῥεῖ almost 12 yearsHmm, but just the 'signature' of a function with variable arguments is still unique, isn't it? The '...' variable arguments part is at least just a camouflage of 'va_list' used inside the functions implementation. Invoking such a function through a function pointer wouldn't (shouldn't) differ anyhow from invoking such function in the usual way (with a variable list of arguments).
-
Konrad Rudolph almost 12 years@g-makulik Variable arguments work, but that’s a specific signature, it’s not the same as binding to different function signatures.
-
πάντα ῥεῖ almost 12 yearsAhh, I see your point!. But the OP didn't mention binding explicitely (may be I read his 'pseudo' code wrong). Using interface definitions (polymorphism) it might still be possible to achieve what the OP wants (intended).