3

I already know the basics about functors, how they are created and so on. I now have a specific code that would probably benefit from being converted to functors:

It's about a console input. If the user enters text and presses enter than it tries to execute the entered text as a command. Currently the available commands are stored in a std::map<std::string, (void*)(std::string)> where map.first is the name of the command and map.second is the pointer to a function containing the code for this command.

If I now convert this to functors, what would be the best way to do so? Would I simply replace the function pointer by the actual functor objects? Or would remove the map and simply call the functor with the command string (commandFunctor("command"))? If the second: What would the best way such a functor should look like? Should I then only create ONE functor class and in it's operator() place a if-else-if-else... checking for the commands and store the code into it?

Or should I create a new functor class for each command and call the functor that corresponds to this command?

So, in short: User enters command. Command is looked up. If comnmand exists then execute its code. How to do this in the most efficietly way with functors?

blubberbernd
  • 3,641
  • 8
  • 35
  • 46
  • http://stackoverflow.com/questions/356950/c-functors-and-their-uses/357223#357223 – sehe Jul 07 '11 at 08:36
  • why do you store commands? why in `map` instead of e.g. `vector`? what benefit do you expect to receive using functors instead of function pointers? – Andriy Tylychko Jul 07 '11 at 08:37
  • "map.first" is commonly called the "key", and "map.second" the "mapped type", or also "value". (Though the *value type* of a map is actually "key-value pair".) Just for information... – Kerrek SB Jul 07 '11 at 09:58
  • @Andy T How would you solve this? If I only store the functors in a vector, how would the console determine what functor to execute? If the user enters "command1", from what would the programm know which functor in the vector to use for "command1"? It would not know which functor is for "command1". – blubberbernd Jul 07 '11 at 17:42
  • @blubberbernd: accidentally you answered all my questions. I just didn't get that it's lookup table for functors. – Andriy Tylychko Jul 08 '11 at 08:43

3 Answers3

3

I would stick with the general form of what you have, but use a std::map<std::string, std::tr1::function> to store the commands (i'm using std::tr1::function, but you can use whatever functor class fits)

Jim Deville
  • 10,632
  • 1
  • 37
  • 47
3

I would suggest using a std::map<std::string, boost::function<void(std::string)> >. Or, if you have access to a C++0x standard library, you can use std::function instead of boost::function.

A boost/std::function is a callable object that can store anything that is callable with the function type you specify. So the user can give you a function pointer, a functor of a type that they create, or even a boost/std::bind object that does function composition.

Nicol Bolas
  • 449,505
  • 63
  • 781
  • 982
  • I'd like to use my own functors (don't want a new dependency like boost) and C++0x still isn't "officially". So, where should I define all my functors? Basically this would mean, if I have 10 commands I would have 10 new functor classes, or am I wrong here? And the argument of the operator() would be the arguments from the commands, do I get this right? – blubberbernd Jul 07 '11 at 09:54
  • @blubberbernd: boost or tr1 functors allows you to bind arguments. you can have one general simple function bound to different commands with different arguments. it's quite difficult to implement yourself. – Andriy Tylychko Jul 08 '11 at 08:54
0

Currently, you use the map to determine which function pointer to be called, based on the discriminator (or string id, or whatever you want to call it). Replacing it with a functor that just gets passed a string (say, commandFunctor("command")), you'll just have to move the mapping logic to that function.

You'll still need the map, but as you noticed, you can definitely replace the function pointer with a functor, and depending on your compiler/version/etc, you can use the std::tr1::function or boost, or whatever else you might have.

Vlad Ciobanu
  • 1,473
  • 1
  • 11
  • 11