4

Let's say I have two functions:

void a(int arg1) { ... }
void b(int arg1, arg2) { ... }

And I also have a string with the name of the function I want to call, and an array with all parameters:

string func_name = "b"; // 'a' or 'b'
int args[] = { 1, 2 }; // has either 1 or 2 values

I need to call the function dynamically. Doing it with a function that has no arguments is really easy, I just created a map (string function_name => pointer to function).

Now I also want to pass the arguments, so I want to convert an array to actual arguments, something like this:

auto f = std::bind(b, args); // Doesn't compile, requires 1,2 as arguments

I hope the problem is clear and that it is solvable.

Thanks

Alex
  • 34,581
  • 26
  • 91
  • 135
  • What should happen if `func_name == "a"` and `args` has two values? And, conversely, if `func_name == "b"` and `args` has just one value? – Gorpik Oct 01 '12 at 14:44
  • 1
    What you want might be possible via the magic of macros. check out [this](http://en.wikipedia.org/wiki/Variadic_macro). – andre Oct 01 '12 at 15:30
  • @ahenderson, variadic macros look interesting... Going to give it a try. – Alex Oct 01 '12 at 15:39
  • @ahenderson, this macro is really cool, it does allow me to specify any number of parameters, but I need to send an array that has to be converted to those parameters (kind of what you can do in python with *args) – Alex Oct 01 '12 at 15:54
  • 1
    Because C++ is not a dynamic language i think you have to make a compromise. A possible [compromise](http://stackoverflow.com/a/1287060/942596) is to define a macro that allows for upto a fix sequence of parameters. – andre Oct 01 '12 at 15:59
  • @ahenderson, thank you so much! That's exactly what I'm looking for. So easy... Why didn't I think about a macro for converting an array to arguments?.. Please post an answer so I can accept it. – Alex Oct 01 '12 at 16:15

3 Answers3

3

Inspired by this answer https://stackoverflow.com/a/1287060/942596 you can achieve what you want using macro's

#define BUILD0(x) x[0]
#define BUILD1(x) BUILD0(x), x[1]
#define BUILD2(x) BUILD1(x), x[2]
#define BUILD3(x) BUILD2(x), x[3]
#define BUILD(x, i) BUILD##i(x)


void foo(int i) {std::cout << i << std::endl;}
void foo(int i, int j) {std::cout << j << std::endl;}
void foo(int i, int j, int k) {std::cout << k << std::endl;}
void foo(int i, int j, int k, int l) {std::cout << l << std::endl;}

int main() {
    int x[] = {1, 2, 3};
    boost::bind(foo, BUILD(x, 2))();
}

Node: this does not account for this situation of 0 parameters.

Community
  • 1
  • 1
andre
  • 7,018
  • 4
  • 43
  • 75
1

Just pass the parameters as a collection:

void a(std::vector<int> args)
{
    //...
}

No need for callbacks or varargs.

Luchian Grigore
  • 253,575
  • 64
  • 457
  • 625
  • 2
    I assume the OP plans to use this for more than just functions which take N ints. – Benj Oct 01 '12 at 14:43
  • That's true, I want to use other types (strings and floats) as well. Besides, 'real' variables like 'user_name' and 'age' are a lot cleaner than args[0] and args[1] – Alex Oct 01 '12 at 15:35
  • @Alex parameters of type `void*` that can point to anything. Anyway, if you need this, there's probably a larger design issue which needs addressing. – Luchian Grigore Oct 01 '12 at 15:48
  • Oh, now I see what you mean. No, that'll not work (see my args[0], args[1] comment). This is not a design issue. I want to implement the same thing ASP.NET MVC does: convert query string parameters to function parameters. – Alex Oct 01 '12 at 15:55
  • It can only do that because it has a special preprocessing step and reflection. C++ can't. – Puppy Oct 01 '12 at 16:06
1

You'd need dynamic type checking to make this work- that would mean, by the way, a dynamic language like Lua or Python.

Edit: ASP.NET does this through a special preprocessing step and reflection. C++ has neither of those things. You will have to perform the conversion.

Puppy
  • 144,682
  • 38
  • 256
  • 465
  • Unfortunately, using dynamic languages is not an option for me... It has been implemented in C# in ASP.NET MVC. Query string parameters are converted to function's parameters. C# is a static language, so there must be a way to do that in C++. – Alex Oct 01 '12 at 15:36
  • @Alex: C# has *reflection* - it can examine types and interfaces, and retrieve classes and functions by name, *at runtime*, so it is far less "static" than C++ which has no such thing. That said, I have no idea how ASP.NET MVC is implemented. – molbdnilo Oct 01 '12 at 16:01