# Command Pattern (with func pointers) (C++)

## Recommended Posts

I posted about this in the Game Programming forum, but maybe it's more appropriate here.. and I will elaborate on the question: Using the command pattern with function pointers (instea dof writing new Execute method for command classes, use single class per reciever and point the execute method to desired function), i get decent usable functionality. However, I can only make calls to functions with no arguments (Because of "typedef void (Game::* Action)();", which is set for no arguments!!) My solution was to make another subclass of Command class, with Action typedefed with an argument.. So I had to prototype new Execute method in Command, and make it do nothing in other subclass, of course. Anyway, it seemed like this should work for me, but when I tried to run it it gives message "illegal call of non-static member function" because of this line: boost::shared_ptr<Command> cmd(new StringCommand(&game, &Game::OpenMenu(file))); StringCommand is the subclass of Command that should accept 1 std string as argument. Am I just trying to send address of function+argument to the StringCommand object wrong, or is this just impossible to work anyway? If any other code is needed, id be happy to post some.

##### Share on other sites
Quote:
 Original post by AAAPAm I just trying to send address of function+argument
Yeah, looks like it. Except that there's no such thing, so you get an error. You need to use an object which holds the argument's value and has a () operator which will call Game::OpenMenu with the argument.

But an easier way is to use a generic facility which does the same thing and you won't need to manually define a new class for each function. Since you're already using boost, may I suggest you look up boost.function and boost.bind. Together they provide exactly what you need.

##### Share on other sites
&Game::OpenMenu(file) is trying to call the supposed-static OpenMenu member function of the Game class with file as a parameter and then take the address of the result. Since the member function is non-static, the code is illegal.

It is definitely not giving you a pointer to a curried member function. C++ has no automated currying mechanism.

Since you're already using Boost, consider using boost::function and boost::bind instead of naked function pointers. You'll likely find they already do everything you want.

##### Share on other sites
I'd second what Frunny said about boost::bind. We use it along with boost signals and slots for our command pattern architecture.

Cheers
Chris

##### Share on other sites
Hey, I took your advice and started switch to just using the boost function ptrs and bind system.

I used http://www.codeproject.com/library/BoostBindFunction.asp website as a base.

Now, i see that you need to make different function templates for different varieties of variables...

so this puts me in the same situation that i was in before, essentially. theres only room for one "kind of function" in the command container. Any tips?

##### Share on other sites
Quote:
 Original post by AAAPso this puts me in the same situation that i was in before, essentially. theres only room for one "kind of function" in the command container. Any tips?

I may be missing something, but I would prefer functors instead of function pointers. One of the main reasons is that you can de-couple the initialization from the calling. The upshot of this is that you can make all of the functor calls the same. For example they could take no arguments and return a bool indicating success...or whatever. However, since each command is now a class you can initialize it however you like. So, lets say some command needs to know where you clicked. You could pass the point into the constructor and store it off. However, the call would still be "bool Execute();".

I think this approach is simpler than trying to support an arbitrary calling mechanism. Plus, it means you can do nifty things like derive commands and such :)

-John

##### Share on other sites
I thought boost::function was a implementation of functor?

##### Share on other sites
typedef void (*void_func)(void*);typedef std::pair<void_func, void*> callback;template<typename T>struct round_trip {  typedef void(*T_func)(T*);  typedef std::pair<T_func, T*> Tcallback;  static void wrapper_func(void* v) {    Tcallback* t = reinterpret_cast<Tcallback*>(v);    t->first(t->second);    delete t;      }  static callback make_callback(T_func f, T* t) {    Tcallback* cb = new Tcallback( f, t );    callback retval = callback( wrapper_func, reinterpret_cast<void*>(cb);    return retval;  }};template<typename T>callback make_callback(void (*f)(T*), T* t) {  return round_trip<T>::make_callback(f, t);}

Voila. "Typesafe" callbacks that take arbitrary T*s. =)

The above is designed for "do the callback once".

If you want "do the callback more than once", you need both "do callback" and "clean up callback" callback functions.

##### Share on other sites
can T be in the form of a whole function prototype such as the return type and parameters? sorry for the newb questions, but this whole topic seems a little over my head at the moment.

##### Share on other sites
Quote:
 Original post by AAAPNow, i see that you need to make different function templates for different varieties of variables... so this puts me in the same situation that i was in before, essentially. theres only room for one "kind of function" in the command container. Any tips?

I have a very simple question for you, but I want you to really think before answering:

If you somehow managed to lump together functions which expect varied number and types of arguments, how would you go about actually calling them? You would be constrained to a single interface regardless of the number and type of parameters in the function call!

The only sound mechanism I can think of is to pass around a std::vector<boost::any> or std::vector<boost::variant<stuff> > and have the client function extract the actual parameters.

I wrote a bit of a class to do that, but it's incomplete and rather messy. If you want it, you're welcome to it.

An alternative is to have a battery of operator()(T0, T1...) templates that cast the pointer to the appropriate function pointer type but *ugh* that involves some serious tightrope-walking there. Without a net.

Or you can have them all accept a void* and pray.

##### Share on other sites
Quote:
 Original post by AAAPcan T be in the form of a whole function prototype such as the return type and parameters? sorry for the newb questions, but this whole topic seems a little over my head at the moment.

With VC6, no, with better compiler, yes:

boost::function<int (double, std::string)> func;

or (VC6)

boost::function2<int, double, std::string> func;

##### Share on other sites
Quote:
 Original post by AAAPI thought boost::function was a implementation of functor?

To be honest, I've never used boost::function so I can't say for sure. However, I thought it was a way to wrap function pointers, pointers to member functions, or functors in such a manner that you could use them interchangeably.

Either way, if you want to use different inputs to different functions, using functors seems the sanest and simplest way to me. Just initialize or update each command object any way you want. Then, when you iterate through and call them just call Execute() or whatever.

FWIW, I've used this approach before in situations like this and it's worked great for me!

-John

##### Share on other sites
Well, I'm just settling for making everything use the same parameters (for commands at least), I guess it's not a big deal.

##### Share on other sites
Quote:
 Original post by AAAPcan T be in the form of a whole function prototype such as the return type and parameters? sorry for the newb questions, but this whole topic seems a little over my head at the moment.

In my case, no.

When you are dealing with "callbacks", it is often the case that you have the callback pull it's own data from where it needs it, instead of being provided with the data.

If you think about it, if you had a list of functions with two different signatures, how would you know how to call the functions?

Instead, you provide the callback with "too much information", and the callback filters out what it cares about.

## Create an account

Register a new account

• ### Forum Statistics

• Total Topics
628320
• Total Posts
2982072

• 21
• 9
• 9
• 13
• 11