Please consider this -probably poorly written- example :
class Command;
class Command : public boost::enable_shared_from_this<Command>
{
public :
void execute()
{
executeImpl();
// then do some stuff which is common to all commands ...
}
// Much more stuff ...
private:
virtual void executeImpl()=0;
// Much more stuff too ...
};
and :
class CmdAdd : public Command
{
public:
CmdAdd(int howMuchToAdd);
void executeImpl();
int _amountToAdd;
};
// implementation isn't really important here ....
With this, I can simply add a callback using this syntax :
boost::shared_ptr<Command> cmdAdd(CmdAdd(someValue));
cmdAdd->execute();
It works flawlessly. My “Command” class does much more things which are common to all commands, such as implementing undo, redo, progress report and so on, but I removed it from the code for the sake of readability.
Now my question is simple :
is there a way to rewrite the command class, so that I can replace this call :
boost::shared_ptr<Command> cmdAdd(CmdAdd(someValue));
cmdAdd->execute();
by something like :
CmdAdd(someValue); // preferably
or CmdAdd->execute(someValue)
I’ve been thinking about that a lot but I have a conceptual problem :
I wanted to template my Command class like
template <typename R,typename T1, typename T2, ..., typename Tn> class Command
{
R1 execute(T1 p1, ...,Tn pn)
{
return executeImpl(T1 p1, ...,Tn pn);
// then do some stuff which is common to all commands ...
}
}
but obviously, there’s a problem here :
the syntax template <typename R,typename T1, typename T2, ..., typename Tn> isn’t legal C++ , AFAIK.
Do I have to write n versions of Command, like :
template <typename R> class Command
template <typename R,typename T1> class Command
template <typename R,typename T1, typename T2> class Command
...
and so on ?
(not even sure this is gonna work indeed)
Or is there another, more elegant way to do this ?
Is the syntax, mentioned here of any use there ? (function f;)
I’ve been looking at Loki’s type lists and they seem to do the job. But I can’t find anything that in Boost. I read on the web that boost::mpl is what one wants to use to implement typelists, but I’m a bit confused by MPL docs ?
Any insights on this ?
Regads,
D.
Interesting question 🙂
First of all, there is an issue you overlooked: you need a common base class for all
Commandand this class cannot be templated if you are going to use a stack of them (for undo/redo).Therefore you are stuck with:
I can understand your desire an execute function with parameters, but don’t forget that anyway you would need to save those parameters for the undo/redo operation. It’s just simpler to get them through the constructor.
However, you could still use a templated method to actually invoke a command:
Which is close to the syntax you desired. Note that I have purposely forgotten about the stack here, in my mind you need to pass it to the
executemethod for registration (once completed).Not that I would also probably change the
Commanddesign to get closer to a Strategy pattern:It’s the typical combination of Non Virtual Interface and Pointer to Implementation idioms.