I'm looking at the following problem:
I get strings that are formatted like this:
functionname_parameter1_parameter2_parameter3
otherfunctionname_parameter1_parameter2
.
.
.
and i would like to call the function with the given parameters. So let's say i have a function test:
void test(int x, float y, std::string z) {}
and i get a message:
test_5_2.0_abc
then i would like the function test to be automatically invoked like this:
test(5, 2.0, "abc");
Do you have any hints on how to accomplish this in C++?
I modified @Xeo's code to work with gcc properly, so it ensures the parameters are pulled in the right order. I'm only posting this since it took me a while to understand the original code and splice in the order-enforcement. Full credit should still go to @Xeo. If I find anything wrong with my implementation I'll come back and edit, but thus far in my testing I haven't seen any problems.
This also works with Visual Studio 2013, have not tried earlier versions.
Update: Updated
stream_function
to fix the argument-evaluation-order problem @Nawaz mentioned in the comments, and also removed thestd::function
for improved efficiency.Note that the evaluation-order fix only works for Clang, as GCC doesn't follow the standard here.An example for GCC, with manual order-enforcement, can be found here.This is generally not that easy to accomplish. I wrote a little wrapper class around
std::function
once that extracts the arguments from astd::istream
. Here's an example using C++11:Compiles under Clang 3.3 and works as expected (small live example).
It was fun to hack that class together again, hope you enjoy. Note that you need to modify the code a little to work for your example, since C++ IOstreams have whitespace as delimiter, so you'd need to replace all underscores in your message with spaces. Should be easy to do though, after that just construct a
std::istringstream
from your message:You pretty much can't, C++ doesn't have any kind of reflection on functions.
The question then is how close you can get. An interface like this is pretty plausible, if it would suit:
Where
registered_functions
is amap<string,std::function<void,string>>
, and you have to explicitly do something like:for each function that can be called in this way.
make_registration
would then be a fairly hairy template function that takes a function pointer as a parameter and returns astd::function
object that when called splits the string into chunks, checks that there are the right number there, converts each one to the correct parameter type with aboost::lexical_cast
, and finally calls the specified function. It would know the "correct type" from the template argument tomake_registration
-- to accept arbitrarily many parameters this would have to be a C++11 variadic template, but you can fake it with:Dealing with overloads and optional parameters would add further complication.
Although I don't know anything about them, I expect that there are C++ support frameworks out there for SOAP or other RPC protocols, that might contain some relevant code.
You could parse the string, separate the arguments and send them to the function with no problem, but what you cannot do is reference the function with its name on a string, because the function doesn't have a name anymore at runtime.
You could have a if-else if chain that checks for the function name, and then parse the arguments and call the specific function.
What you are looking for is reflection. And it is not possible in C++. C++ is designed with speed in mind. If you require inspection of a library or code and then identify the types in it and invoke methods associated with those types (usually classes) then I am afraid it is not possible in C++.
For further reference you can refer to this thread.
How can I add reflection to a C++ application?
http://en.wikibooks.org/wiki/C%2B%2B_Programming/RTTI
Why does C++ not have reflection?