Reputation: 27
I have a set of functions with the same number of arguments, but different names (suppose each implement different method). I have the name of the requested method in a string. Is it possible to call the corresponding function using the method name. to make it clear, suppose that I have the following function (I just mentioned their name and argument):
search_esa(int a, int b);
search_tss(int a, int b);
search_fss(int a, int b);
search_ds(int a, int b);
now lets assume I have the name of the requested method, lets assume esa, in a string:
string methodName = "esa"
is it possible to call the corresponding function by using macros? I tested
#define CALL_SEARCH_MV(method) search_##method
and then try to call it by:
CALL_SEARCH_MV(methodName.c_str())
but it calls search_methodName function, which does not exist. Any other suggestions would be greatly appreciated (except suggesting switch case method or if).
Upvotes: 0
Views: 478
Reputation: 256
You can use a combination of Macros, function pointers and clever hacking to achieve the desired result with ease.
In your main.cpp (or where the search functionality lives):
#include <map>
#include <string>
#include <iostream>
typedef int(*search)(int a, int b);
#define SEARCH(x) int search_##x(int a, int b);
#include "search_func.incl"
#undef SEARCH
#define SEARCH(x) {#x, search_##x},
std::map<std::string, search> search_funcs = {
#include "search_func.incl"
};
#undef SEARCH
int main(char** argv, int argc)
{
std::cout << search_funcs["esa"](1, 2) << std::endl;
std::cout << search_funcs["tss"](3, 4) << std::endl;
std::cout << search_funcs["fss"](5, 6) << std::endl;
std::cout << search_funcs["ds"](7, 8) << std::endl;
return 0;
}
int search_esa(int a, int b) { return 100 * a + 10 * b + 0; }
int search_tss(int a, int b) { return 100 * a + 10 * b + 1; }
int search_fss(int a, int b) { return 100 * a + 10 * b + 2; }
int search_ds(int a, int b) { return 100 * a + 10 * b + 3; }
In search_func.incl
SEARCH(esa)
SEARCH(tss)
SEARCH(fss)
SEARCH(ds)
How this works The search_func.incl file specifies the name of your search functions with a macro. When you include the file, you switch up the definition of the macro so that the included functions are presented differently.
SEARCH(abc)
becomes a function declaration on the first include:
int search_abc(int a, int b);
and a key value pair {string, function pointer} on the second include:
{"abc", search_abc},
These KVP are in a map, so when you need to call a function, the string maps to the function name automatically.
Upvotes: 0
Reputation: 16090
You can store function pointers in containers. So you can map pretty much anything. The syntax is pretty simple:
#include <iostream>
#include <map>
using namespace std;
int f1(int a, int b) { return a+b; }
int f2(int a, int b) { return a*b; }
int main() {
int x = 5;
int y = 3;
map<string, int(*)(int, int)> f;
f["add"] = &f1;
f["mul"] = &f2;
cout << f["add"](x,y) << "\n";
cout << f["mul"](x,y) << "\n";
return 0;
}
Live: http://ideone.com/wLjw1i.
So you can store any function with matching signature (+return type). This is a the expense of one indirection. The means they are harder to be optimized, because the jump target is set in the run time.
You can make it a bit more general using std::function
, again at slight performance expense.
Upvotes: 1
Reputation: 20396
Something like this would probably work:
std::map<std::string, std::function<void(int, int)>> functions{
{"esa", search_esa},
{"tss", search_tss},
{"fss", search_fss},
{"ds", search_ds}
};
int main(int argc, char ** argv) {
std::string cmd = argv[1];
functions.at(cmd)(5, 10);
return 0;
}
It's worth noting, though, that you can't really generalize this. If you added another function, like say, search_rsa
, you'd have to manually add an entry for it to the map. C++ doesn't have the comprehensive reflection capabilities that a language like Java or Python has, so you can't just write a function that takes a string and searches for a method that has a name matching that string.
Upvotes: 4
Reputation: 1
Not Possible! the methods defined must be call with the same name. we cannot manipulate the method name.
Upvotes: -1