Calling the appropriate methods for a given command - c++

I am making a command prompt in C++. I would like a user to enter a line such as "say something". This will then be split up so that "say" would be the command name and "something" would be a parameter. So far, so good - this is already working.
I would then like to use the name of the command to call the appropriate method. I could use some kind of look-up table but is there a better method?

probably you need something like map of command keywords and function or method pointers
#include <string>
#include <map>
class CmdHandler // our handler class
{
public:
void Handler(const std::string &arg){}//our handler method
};
typedef void (CmdHandler::*MethodPtr)(const std::string &); // make typedef to easily deal with the type of the member-function pointer
std::map<std::string, MethodPtr> my_handlers; // make our method lookup table
int _tmain(int argc, _TCHAR* argv[])
{
CmdHandler handler;
//add a real member-function pointer for the "say" command
my_handlers.insert(std::make_pair("say", &CmdHandler::Handler));
//look for the handler of command "say" and call it instantly
(handler.*my_handlers["say"])("something");
return 0;
}

C++ doesn't support any kind of reflection: some sort of table mapping names to function objects is the best approach I'm aware of.

A look up table is the usual method. Usually, a std::map...and if you're using boost, you might want to look at boost::function and boost::bind.
Also note that you might find the compiler macro __FUNCTION__ (which expands to the undecorated name of the current function at compile time, and is often used in error messages - you might have to strip class names from member function names) useful in command functions, in order register functions in your map so that you can avoid misspellings and extra typing.
(Note that BOOST_CURRENT_FUNCTION might be a more portable macro.)

Related

How can I add a global std::map to chaiscript?

I would like to pass a std::map to chaiscript. However, I'm not sure how to do this. My code is currently as follows:
#include <map>
#include <string>
#include <chaiscript/chaiscript.hpp>
int main(int argc, char* argv[]) {
chaiscript::ChaiScript chai;
auto data = std::map<std::string, std::string>{
{ "key1", "val1"},
{ "key2", "val2"},
};
chai.add_global(chaiscript::var(&data), "data");
chai.eval(R"(
print(data["key1"]);
)");
}
However, this code crashes with an exception saying, that chaiscript doesn't know what to do with the bracket [] operator. How can I fix this?
I could tell chaiscript what the right function is, but I would prefer it, if the map is compatible with chaiscripts internal Map type!
Update:
I found a bit in the documentation, which explains that the chaiscript map type supports arbitrary input. Looking at the code, this seems to be done by the Boxed_Value type. However, this probably means that it is fundamentally impossible to directly insert std::map into scripts.
I'm now thinking about either writing a custom type, or a conversion function to solve the problem. Keeping you posted...
As far as I can see, out-of-the-box-chaiscript only provides you with the std::map<std::string,chaiscript::Boxed_Value> map type. Therefore, if you want to add your own map to a script, you need to either provide chaiscript with a new type, or convert to the given one. Thus, I see the following solutions:
Case 1: You only need to get out a map from chaiscript to c++
This case can be found in the documentation. You need to supply a conversion function, and off you go.
chai.add(chaiscript::map_conversion<std::map<std::string, std::string>>());
auto map = chai.boxed_cast<std::map<std::string, std::string>>(chai.eval("data"));
Case 2: You only need to supply a map to chaiscript from c++
This is basically the same as Case 1, but you have to supply the conversion function yourself.
auto convert = [](const std::map<std::string, std::string>& std_map) {
auto chai_map = std::map<std::string, chaiscript::Boxed_Value>{};
for (auto&& entry : std_map)
chai_map.emplace(entry.first, chaiscript::var(entry.second));
return chai_map;
};
chai.add(chaiscript::var(convert(data)),"data");
Case 3: You want to share a global value between chaiscript and c++
This case is rather tricky. You either have to supply chaiscript with a get_map() and send_map() function, which handle the data synchronization:
chai.eval(R"(
data = get_map();
data["key1"] = "val1";
send_map(data);
)");
Or you have to add a custom data type, which handles the synchronization in the background.
My Solution:
Fortunately for my case, I don't really need a shared state between chaiscript and c++, and therefore can rely on the solution for Case 2.

C++ call function with string as parameter

Lets say I have several functions like function1(), function2(), ....., function1000()
and I am getting a string in a function lets say call_function(string function_name).
Now I need to execute function based on function_name.
I searched for solutions and found I can use maps.
Is there any easy way to create a map for lets say 1000 keys(string type) and respective functions ?
eg: call_function(function541) then it should execute function541();
You can use map to function pointers for this stuff
void func1(const char *args)
{
//....
}
void func2(const char *args)
{
//....
}
typedef void (*function) (const char *args);
//......
std::map<std::string, function> func_map;
func_map.insert(std::pair<std::string, function>("func1", func1));
func_map.insert(std::pair<std::string, function>("func2", func2));
func_map["func1"]("arg1 arg2 arg3"); // Here is the func1 call
Is there any easy way to create a map for lets say 1000 keys(string type) and respective functions ?
eg: call_function(function541)
then it should execute function541();
No, there is no easy way, because C++ does not have reflection. Function names only exist for the compiler. At run-time, there is no relationship between a function called function541 in your source code and the string "function541" existing in memory while the program is being executed.
Each and any of such links must be established manually:
std::map<std::string, std::function<void()>> map;
// ...
map["function541"] = function541;
Of course, you can still automate such a task with code generation. Functions with mechanical names like this don't look like manually written C++ code anyway. That is, you can write a script in some other language that creates the C++ code to add the thousand functions to the map, perhaps as some kind of pre-build step.
Still, from a run-time point of view, there's no automation whatsoever.

How to make a function that returns the name of the argument passed

I am looking for a way to create a naming service. Basically I need a function that accepts anything as an argument and returns me the name of the given argument. This can be anything, class, function, variable etc.
std::string name(T t)
{
if t is a function
return __func__ of t
if t is a variable
return name of variable.
}
Any suggestions?
C++ is not the right language to do this, it has no reflection capabilities at all, and you can't treat "anything, class, function, variable etc." uniformly. You can't pass a class to a function, or pass a function to a function, they are not objects.
With MACRO, you may do
#define name(n) #n
which stringify given argument.
In C++ the name of a function or of a variable is just non sense. The name is only known at build time (compile & link) and later translated to an address. At run time all names have just vanished and cannot be knows - except when using special build mode to allow debuggers to keep track of original names.
What would be closer than that would be a function accepting a pointer to void:
std::string address(const void *t) {
std::ostringstream os;
os << "Address is " << t;
return os.str();
}
You can then use it this way:
int i;
std::string s;
s = address(static_cast<const void *>(&i));
...
double d;
s = address(static_cast<const void *>(&d));
...
// if f is declared as int f(double d, std::string s):
s = address(static_cast<const void *>(&f));
As answered already, C++ doesn't have reflection. But if you have debug symbols available at runtime different OS/compiler combinations make that information available - if you put enough effort into it.
Search for mechanisms to get the C++ stack trace or back trace.
E.g., this question has multiple answers that point to libraries that are useful for Linux, and separately for Windows: C++ display stack trace on exception (There are also other answers on SO and on the web in general.)

Using functions from classes

I am learning C++ and very new at using classes, and I am getting very confused in trying to use them. I am trying to convert my existing code (which used structs) so that it uses classes - so while I know what I am trying to do I don't know if I'm doing it correctly.
I was told that when using functions from the class, I first need to instantiate an object of the class. So what I have tried (a snippet) in my main function is:
int main()// line 1
{
string message_fr_client = "test"; //line2
msgInfo message_processed; //line 3
message_processed.incMsgClass(message_fr_client); //line 4
if (!message_processed.priority_check(qos_levels, message_processed)) //line 5
cout << "failure: priority level out of bounds\n"; //line 6
return 0; //line 7
}
Could you help me clarify if my following assumptions are correct? The compiler is not showing any error and so I don't know if it is error-free, or if there are ones lurking beneath.
At line 4, is the function incMsgClass being performed on the string message_fr_client and returning the resultant (and modified) message_processed?
At line 5, the function priority_check is being performed on the message_processed and returning a boolean?
In my class definition, I have a function getPath that is meant to modify the value of nodePath - is it just a matter of using message_processed.getPath(/*arguments*/)?
I haven't included the body of the functions because I know they work - I would just like to find out how the class functions interact. Please let me know if I can be clearer - just trying to clear up some confusion here.
Here is my class:
#ifndef clientMsgHandling_H
#define clientMsgHandling_H
#include <list>
#include <map>
#include <queue>
class msgInfo
{
public:
msgInfo();
msgInfo(int, int, int, std::string, std::list<int>);
/*classifying message*/
msgInfo incMsgClass(std::string original_msg);
/*message error checks*/
bool priority_check(int syst_priority, msgInfo msg); //check that message is within qos levels
bool route_check(std::map<std::pair<int, int>, int> route_table, msgInfo msg); //check that route exists
void getPath(msgInfo msg, std::map<std::pair<int, int>, int> route_info, int max_hop);
private:
int source_id;
int dest_id;
int priority;
std::string payload;
std::list<int> nodePath;
};
#endif
While it may compile (and even run), there are a few oddities with the code as shown:-
First off, class methods know which object they are operating on - so your priority_check and route_check methods probably don't need msgInfo as a parameter.,
for example, your old non-class function might be like this
bool priority_check(int p, msgInfo msg)
{
return msg.priority < p;
}
But the new one should look like this:
bool msgInfo::priority_check(int p)
{
return priority < p;
}
Also, incMsgClass is a bit odd, as it's a non-static class method that returns a msgInfo object. It's difficult to tell without understanding what it's supposed to do, but it seems possible that this function should actually be a constructor, rather than a regular method.
One other thing is that you're currently passing a msgInfo by value to those methods. So if the method needed to modify the passed msgInfo, it would not have any effect. It's generally better to pass objects by reference or const reference to other methods. So, back to the previous non-method example, it should really be this.
bool priority_check(int p, const msgInfo &msg)
...
But, as I said, you probably don't need the msgInfo parameters anyway.
At line 4, is the function incMsgClass being performed on the string message_fr_client
Yes
and returning the resultant (and modified) message_processed?
Whatever it's returning, you're ignoring the return value. It can modify the object itself, yes, because the function is not const.
At line 5, the function priority_check is being performed on the message_processed and returning a boolean?
Yes
In my class definition, I have a function getPath that is meant to modify the value of nodePath - is it just a matter of using message_processed.getPath(/arguments/)?
If a member function is intended to modify one of the class members, it's just a matter of not marking that function const
Hard to tell without implementation-details, but here we go:
I. You are passing a std::string as value (C++ is call-by-value by default), so you get a copy of the std::string in your method. If you want to work on the object you passed and manipulate it, use a reference on the object, like
msgInfo incMsgClass(std::string& original_msg); // notice the ampersand
then you can change your signature to
void incMsgClass(std::string& original_msg);
as you don't need to return the std::string you passed.
II. Yes, at least according to your signature
III. Can see a node_path only as a member.
For all your questions, see C++-FAQ.
Your basic assumptions are correct.
message_processed.incMsgClass(message_fr_client); //line 4
This line is not correct. The function you call returns msgInfo which is simply dropped. You should assign it to something. But it is not as it is usually done. You should make it a constructor of msgInfo, like
class msgInfo
{
public:
msgInfo(std::string original_msg);
...
}
Then you could call it like this
msgInfo message_processed(message_fr_client);
That line would create a msgInfo that is already properly initialized.
There is another pattern for creating class instances - static creating function. In your case you could mark incMsgClass static and then call it like
msgInfo message_processed = msgInfo.incMsgClass(message_fr_client);
I seriously doubt you need this pattern here, so I'd advise to move to constructor.
As of other functions, I see no problems there. Just note that all member functions not marked as const can modify the object they are called on. So, you don't need to pass this object explicitly. For functions a pointer to the object they are called on is available by name this. Also the functions can access all class variables as if these variables are global for normal (non-member) functions.

c++ std::map of heterogeneous function pointers

Is it possible to store pointers to various heterogenous functions like:
In the header:
int functionA (int param1);
void functionB (void);
Basically this would the part I don't know how to write:
typedef ??boost::function<void(void)>?? functionPointer;
And afterwards:
map<char*,functionPointer> _myMap;
In the .cpp
void CreateFunctionMap()
{
_myMap["functionA"] = &functionA;
_myMap["functionB"] = &functionB;
...
}
And then reuse it like:
void execute(int argc, char* argv[])
{
if(argc>1){
int param = atoi(argv[1]);
int answer;
functionPointer mfp;
mfp = map[argv[0]];
answer = *mfp(param);
}
else{
*map[argv[0]];
}
}
etc.
Thanks
--EDIT--
Just to give more info:
The reason for this question is that I am implementing a drop-down "quake-style" console for an already existing application. This way I can provide runtime command line user input to access various already coded functions of various types i.e.:
/exec <functionName> <param1> <param2> ...
If you want to have "pointer to something, but I'm not going to define what, and it could be a variety of things anyway" you can use void *.
But you really shouldn't.
void * is purely a pointer. In order to do anything with it, you have to cast it to a more meaningful pointer, but at that point, you've lost all type safety. What's to stop someone from using the wrong function signature? Or using a pointer to a struct?
EDIT
To give you a more useful answer, there's no need to put this all into a single map. It's ok to use multiple maps. I.e.
typedef boost::function<void(void)> voidFunctionPointer;
typedef boost::function<int(int)> intFunctionPointer;
map<std::string, voidFunctionPointer> _myVoidMap;
map<std::string, intFunctionPointer > _myIntMap;
void CreateFunctionMap()
{
_myVoidMap["functionA"] = &functionA;
_myIntMap["functionB"] = &functionB;
...
}
void execute(int argc, char* argv[])
{
if(argc>1){
int param = atoi(argv[1]);
int answer;
// todo: check that argv[0] is actually in the map
intFunctionPointer mfp = _myIntMap[argv[0]];
answer = mfp(param);
}
else{
// todo: check that argv[0] is actually in the map
voidFunctionPointer mfp = _myVoidMap[argv[0]];
mfp();
}
}
You can use
boost::variant<
boost::function<void(void)>,
boost::function<void(int)> >
Why not just add functions of type int (*func)(int argc, char* argv[])? You could easily remove first arg from execute's params and call the relevant one.
Can you not use the command pattern to encapsulate the function calls. So you can store the functions in functors and call them after wards. For functor implementation you can have a look at Modern C++ Design by Andrei Alexandrescu.
Each of your functions has a different type, so you need some kind of type erasure. You could use the most generic of them: Boost.Any. You can have a map of boost::any, but you need to know the type of the function in order to get it back and call it.
Alternatively, if you know your arguments ahead of time you can bind them with the function call and have all functions in the map be nullary functions: function< void() >. Even if you don't, you may be able to get away with it by binding the argument to references, and then at call time fill the referred variables with the appropiate arguments.