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

6
  • What should happen if func_name == "a" and args has two values? And, conversely, if func_name == "b" and args has just one value? Commented Oct 1, 2012 at 14:44
  • 1
    What you want might be possible via the magic of macros. check out this. Commented Oct 1, 2012 at 15:30
  • @ahenderson, variadic macros look interesting... Going to give it a try. Commented Oct 1, 2012 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) Commented Oct 1, 2012 at 15:54
  • 1
    Because C++ is not a dynamic language i think you have to make a compromise. A possible compromise is to define a macro that allows for upto a fix sequence of parameters. Commented Oct 1, 2012 at 15:59

3 Answers 3

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.

Sign up to request clarification or add additional context in comments.

Comments

1

Just pass the parameters as a collection:

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

No need for callbacks or varargs.

5 Comments

I assume the OP plans to use this for more than just functions which take N ints.
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 parameters of type void* that can point to anything. Anyway, if you need this, there's probably a larger design issue which needs addressing.
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.
It can only do that because it has a special preprocessing step and reflection. C++ can't.
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.

2 Comments

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: 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.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.