I'd like to have a dynamic messaging system in my C++ project, one where there is a fixed list of existing events, events can be triggered anywhere during runtime, and where you can subscribe callback functions to certain events.
There should be an option for arguments passed around in those events. For example, one event might not need any arguments (EVENT_EXIT), and some may need multiple ones (EVENT_PLAYER_CHAT: Player object pointer, String with message)
The first option for making this possible is allowing to pass a void pointer as argument to the event manager when triggering an event, and receiving it in the callback function.
Although: I was told that void pointers are unsafe and I shouldn't use them.
How can I keep (semi) dynamic argument types and counts for my events whilst not using void pointers?
Since others have mentioned the visitor pattern, here is a slight twist using Boost.Variant. This library is often a good choice (or at least it has been for me) when you need a set of different behaviors based on a value. Compared to a void*, it has the benefit of static type checking: if you write a visitor class the misses one of the cases, your code will not compile rather than failing at run time.
Step 1: Define message types:
struct EVENT_EXIT { }; // just a tag, really
struct EVENT_PLAYER_CHAT { Player * p; std::string msg; };
typedef boost::variant<EVENT_EXIT,
EVENT_PLAYER_CHAT> event;
Step 2: Define a visitor:
struct event_handler : public boost::static_visitor<void> {
void operator()(EVENT_EXIT const& e) {
// handle exit event here
}
void operator()(EVENT_PLAYER_CHAT const& e) {
// handle chat event here
std::cout << e.msg << std::endl;
}
};
This defines an event handler that nicely separates out the code for each kind of event. The existence of all operator() overloads is checked at compile time (on template instantiation), so if you add an event type later, the compiler will force you to add corresponding handler code.
Note that event_handler subclasses boost::static_visitor<void>. This determines the return type for each of the operator() overloads.
Step 3: Use your event handler:
event_handler handler;
// ...
event const& e = get_event(); //variant type
boost::apply_visitor(handler, e); // will not compile unless handler
// implements operator() for each
// kind of event
Here, apply_visitor will call the appropriate overload for the 'actual' value of e. For example, if we define get_event as follows:
event get_event() {
return EXIT_EVENT();
}
Then the return value will be converted implicitly to event(EXIT_EVENT()). Then apply_visitor will call the corresponding operator()(EXIT_EVENT const&) overload.
Templates would allow you to write a type-safe event manager without it knowing the message types a-priori.
If the event types change at runtime, or you need to mix multiple types into a single container, you can use pointers to a common base class of all the message/event types.
Something I've done in the past is set up a delegate-based system not unlike what is in C#, using the (excellent) FastDelegate library: http://www.codeproject.com/Articles/7150/Member-Function-Pointers-and-the-Fastest-Possible
So with that in hand, I created some general-purpose Event classes to contain the lists of delegates, like so:
template <class T1>
class Event1 {
public:
typedef FastDelegate1<T1> Delegate;
private:
std::vector<Delegate> m_delegates;
public:
// ...operator() to invoke, operators += and -= to add/remove subscriptions
};
// ...more explicit specializations for diff arg counts (Event2, etc.), unfortunately
Then you can have the various sub-components expose their specific event objects (I used an interface-style but that's not necessary):
typedef Event2<Player*, std::string> PlayerChatEvent;
class IPlayerEvents {
public:
virtual PlayerChatEvent& OnPlayerChat() = 0;
virtual PlayerLogoutEvent& OnPlayerLogout() = 0; // etc...
};
Consumers of this interface can register like so:
void OtherClass::Subscribe(IPlayerEvent& evts) {
evts.OnPlayerChat() += MakeDelegate(this, &OtherClass::OnPlayerChat);
}
void OtherClass::OnPlayerChat(Player* player, std::string message) {
// handle it...
}
The result is is all individually static-typed per event type--no dynamic_casting. However it does decentralize the event system, which may or may not be an issue for your architecture.
You could use a base class, optionally abstract, and use dynamic_cast. The argument will be checked at run-time. A compile-time would probably be better, though.
class EventArgs
{
public:
virtual ~EventArgs();
};
class PlayerChatEventArgs : public EventArgs
{
public:
PlayerChatEventArgs(Player* player, const std::string& message);
virtual ~PlayerChatEventArgs();
Player* GetPlayer() const;
const std::string& GetMessage() const;
private:
Player* player;
std::string message;
};
class Event
{
public:
virtual ~Event() = 0;
virtual void Handle(const EventArgs& args) = 0;
};
class ExitEvent : public Event
{
public:
virtual ~ExitEvent();
virtual void Handle(const EventArgs& /*args*/)
{
// Perform exit stuff.
}
};
class PlayerChatEvent : public Event
{
public:
virtual ~PlayerChatEvent();
virtual void Handle(const EventArgs& args)
{
// this will throw a bad_cast exception if cast fails.
const PlayerChatEventArgs& playerchatargs =
dynamic_cast<const PlayerChatEventArgs&>(args);
// Perform player chat stuff.
}
};
I would think about having a base class for the messages, and then derive all the messages from that base class. You will then be passing pointers to the base class around the events.
You will, presumably, have some basic funcitonaliy in the base class, which may include a member saying what type of message it is. This will allow you to check the message type before casting to the version you need.
It is tempting to have the base class as the most basic type of message, but I would advise making it a virtual class so that every message has to be cast to be used. This symmetry makes it much less prone to bugs later when the complexity (inevitably) increases
Related
I have my fancyFunction which takes a set of elements implementing interface A. The function does a complicated analysis of those elements, based on properties read through interface A. During this analysis, it will call methods of a Consumer c which will take the elements as arguments.
The Consumer is designed to take arguments of a specific type which has absolutely nothing to do with A.
You could imagine that A is an abstraction for edges in a graph. The graph is analyzed in fancyFunction and - for example - every time the function "crosses" an edge, it will send that edge to a Consumer which prints additional information stored in the edge that has nothing to do with it being an edge.
The code given below would of course not compile in a typed language (particularly C++), but leaving out the types (Matlab, Python), the code would work.
To make it work in a typed language (particularly C++), I see two options:
Declare the function as
template <class CONSUMER>
void fancyFunction(A[] setOfAs, CONSUMER c){ ... }
Declare operation1 and operation2 to take the most general object and then do a downcast in the implementation.
What do you recommend to do in that situation? (As far as I see, the visitor pattern is NOT an option.)
Full code outline (I did not use C++ in a while, so please excuse if there are minor syntactical mistakes.):
void fancyFunction(A[] setOfAs, Consumer* c){
// do fancy analysis of setOfAs by properties
// read through interface A
double x = setOfAs[i]->getX();
// call functions in c with arguments of setOfAs[j]
...
c->operationX(setOfAs[i]);
...
c->operationY(setOfAs[j]);
...
}
class A{
virtual double getX();
}
class Consumer{
virtual void operationX(??? x); // whoops, what type do we expect?
virtual void operationY(??? y); // whoops, what type do we expect?
}
class Consumer1{
void operationX(Obj1 x){ ... } // whoops, override with different type
void operationY(Obj1 y){ ... } // whoops, override with different type
}
class Consumer2{
void operationX(Obj2 x){ ... } // whoops, override with different type
void operationY(Obj2 y){ ... } // whoops, override with different type
}
class Obj1 : public A {};
class Obj2 : public A {};
void test(){
Obj1 o1[];
Obj2 o2[];
Callback1 c1;
Callback2 c2;
fancyFunction(o1, &c1);
fancyFunction(o2, &c2);
}
I believe the solution you're looking for is called the Visitor Pattern.
You don't want to manually cast each instance of object A in your fancy function, because that is a maintenance nightmare and a clear code smell.
On the other hand, what if each object automatically handled its own casting? That's the Visitor Pattern.
You begin by defining a new "Visit" function in your base class (A), taking your Consumer as its only argument:
class A
{
public:
virtual void Visit(Consumer& consumer) = 0;
}
You then implement this function for every inherited class, thusly:
class B : public A
{
public:
void Visit(Consumer& consumer)
{
consumer.DoOperation(this); // 'this' utomatically resolves to type B*
}
}
Each derived type now handles calling the appropriate operation overload, by passing the 'this' pointer to the provided Consumer instance. The 'this' pointer is automatically interpreted as the most specific type possible.
Looking back through your original example code, it appears you have each Consumer providing multiple operations, and only handling a single type. This pattern would likely require that you change this paradigm slightly: create a single Consumer for each operation, where each consumer provides overloads for every possible inherited type.
class ConsumerX
{
public:
void DoOperation(A* a) { /* ERROR! This is a base type. If this function is called, you probably need to implement another overload. */ }
void DoOperation(B* b) { /* Much better */ }
}
class ConsumerY
{
public:
void DoOperation(A* a) { /* ERROR! This is a base type. If this function is called, you probably need to implement another overload. */ }
void DoOperation(B* b) { /* Much better */ }
}
Then your implementation loop looks something like this:
ConsumerX consumerX; // Does Operation X for every type
ConsumerY consumerY; // Does Operation Y for every type
for(int x = 0; x < numElements, x++)
{
auto element = setOfAs[x];
element.Visit(consumerX); //Do operation X
element.Visit(consumerY); //Do operation Y
}
Clearly a case where templates are appropriate. I'd even question why your fancyFunction is insisting on base class A. It should just take a begin and end iterator. I wouldn't bother with a consumer either. Make that flexible too, just take any function.
In fact, I wouldn't even write a fancyFunction. It already exists:
std::for_each(o1.begin(), o1.end(),
[c1](Obj1 o) { double x = o.getX(); c1.operationX(o); c1.operationY(o); }
);
My Event Manager
For a event manager I need to store many pointers to functions in a vector to call them when the event is triggered. (I will provide the source code of the EventFunction helper class at the end of this question.)
// an event is defined by a string name and a number
typedef pair<string, int> EventKey;
// EventFunction holds a pointer to a listener function with or without data parameter
typedef unordered_map<EventKey, vector<EventFunction>> ListEvent;
// stores all events and their listeners
ListEvent List;
Registering an listener could be done by calling the first or the second function, depending on if you want receive additional data or not. (This code is from my event manager class.)
public:
typedef void (*EventFunctionPointer)();
typedef void (*EventFunctionPointerData)(void* Data);
// let components register for events by functions with or without data parameter,
// internally simple create a EventFunction object and call the private function
void ManagerEvent::Listen(EventFunctionPointer Function, string Name, int State);
void ManagerEvent::Listen(EventFunctionPointerData Function, string Name, int State);
private:
void ManagerEvent::Listen(EventFunction Function, string Name, int State)
{
EventKey Key(Name, State);
List[Key].push_back(Function);
}
Member Function Pointers
That code doesn't work because I store function pointers but not member function pointers in my List. All these pointers should be member function pointers because a component like ComponentSound will listen to the event "PlayerLevelup" with on of its member functions ComponentSound::PlayerLevelup to play a nice sound if the event is triggered.
A member function pointer in C++ looks like this.
// ReturnType (Class::*MemberFunction)(Parameters);
void (ComponentSound::*PlayerLevelup)();
The problem is, any component class should be able to listen for events, but storing the member function pointers in the event manager requires me to specify the listening class. As you can see in the example, I need to specify ComponentSound but the event manager should simply have a vector of member function pointers to any class.
Question
An Answer to one of these question would help me a lot.
How can I store function pointers to any member function in a vector in my event manager? (Maybe it helps that all the listening functions are inherited from one abstract class Component.)
How can I design my event manager in another way to reach the aimed functionality? (I want to use string and int keys for messages.)
I tried to keep my question general but if you need more informations or code please comment.
Assignments
In my vector of member function pointers I use EventFunction instead of only a pointer to provide two message types. One with, and one without a data parameter.
class EventFunction
{
private: EventFunctionPointer Pointer; EventFunctionPointerData PointerData; bool Data;
public:
EventFunction(EventFunctionPointer Pointer) : Pointer(Pointer), PointerData(NULL), Data(false) { }
EventFunction(EventFunctionPointerData PointerData) : PointerData(PointerData), Pointer(NULL), Data(true) { }
EventFunctionPointer GetFunction() { return Pointer; }
EventFunctionPointerData GetFunctionData() { return PointerData; } bool IsData() { return Data; }
void Call(void* Data = NULL){ if(this->Data) PointerData(Data); else Pointer(); }
};
You will have to use std::function. This is the only way to achieve a generic callback. As soon as you involve function pointers instead of function objects, it is not generic, will never be generic, and can never be made to be generic.
unordered_map<string, vector<std::function<void()>>>
Function pointers are bad and should never be explicitly used in C++, only passed to templates like std::bind and std::function's constructor, and member function pointers are even worse.
You can use functors to achieve this. If you wrap a functor around your member functions you can make a vector out of functors. A functor looks like this:
template <class T> class MyFunctor
{
private:
T* ObjectPtr;
void (T::*MemberFunction) ();
public:
void operator () ()
{
return (*this->ObjectPtr.*this->MemberFunction)();
}
};
So basically a functor overrides the () operator and returns the member function stored in the functor class. Functors can be quite complex if you want them to work with different signatures but in this article you can get further information.
http://www.codeproject.com/Articles/7112/Pointers-to-Member-Functions-and-Functors
Not a direct response, so bear with me.
Before we start: This is generally referred to as the Observer pattern, you might find lots of confused information on the web about it, and many failed implementations, but who knows you might also strike gold.
Okay, so first the question has a fundamental flaw: it fails to consider that capturing object references is tricky, because object lifetimes are bounded.
Therefore, even before we delve into the specifics of an implementation we need to ask ourselves how to handle stale references. There are two basic strategies:
Not having stale references, this implies that registered objects unregister themselves automatically upon destruction. The mechanism can be factored out in a base class.
Having a way to tell good and stale references apart when inspecting them, and lazily collecting the stale ones. The mechanism can be enforced using a shared_ptr/weak_ptr pair and realizing that weak_ptr are observers of the shared_ptr.
Both solutions are viable and neither implementation is perfect. The base class mechanism assumes you can actually modify your class hierarchy while the weak_ptr trick assumes that all observes will be heap-allocated and their lifetime controlled by a weak_ptr.
I will make an example using shared_ptr (and make use of a number of C++11 facilities, though none is mandatory here):
class EventManager {
typedef std::unique_ptr<Observer> OPtr;
typedef std::vector<OPtr> Observers;
public:
// Callback observers of "name"
// Returns the number of observers so invoked
size_t signal(std::string const& name) const {
auto const it = _observers.find(name);
if (it == _observers.end()) { return 0; }
Observers& obs = it->second;
size_t count = 0;
auto invoker = [&count](OPtr const& p) -> bool {
bool const invoked = p->invoke();
count += invoked;
return not invoked; // if not invoked, remove it!
};
obs.erase(std::remove_if(obs.begin(), obs.end(), invoker), obs.end());
if (obs.empty()) { _observers.erase(it); }
return count;
}
// Registers a function callback on event "name"
void register(std::string const& name, void (*f)()) {
_observers[name].push_back(OPtr(new ObserverFunc(f)));
}
// Registers an object callback on event "name"
template <typename T>
void register(std::string const& name, std::shared_ptr<T> const& p, void (T::*f)()) {
_observers[name].push_back(OPtr(new ObserverMember<T>(p, f)));
}
private:
struct Observer { virtual ~Observer() {} virtual bool invoke() = 0; };
struct ObserverFunc: Observer {
ObserverFunc(void (*f)()): _f(f) {}
virtual bool invoke() override { _f(); return true; }
void (*_f)();
};
template <typename T>
struct ObserverMember: Observer {
ObserverT(std::weak_ptr<T> p, void (T::*f)()): _p(p), _f(f) {}
virtual bool invoke() override {
std::shared_ptr<T> p = _p.lock();
if (not p) { return false; }
p->*_f();
return true;
}
std::weak_ptr<T> _p;
void (T::*_f)();
};
// mutable because we remove observers lazily
mutable std::unordered_map<std::string, Observers> _observers;
}; // class EventManager
This is the typical case where you should use polymorphism instead of function (or member function) pointers.
As you noted, your component classes should inherit from a common class Component, which contains virtual method(s) representing the event(s):
class Component
{
public:
virtual void OnPlayerLevelUp()
{
}
};
class ComponentSound : public Component
{
public:
// override it
void OnPlayerLevelUp()
{
// do the actual work
}
};
Your ListEvent type will now look like this:
typedef unordered_map<EventKey, vector<Component*>> ListEvent;
As for the optional void* paramenter in event methods, you can specify it as an optional parameter, but the fact that it's a void* is a bad sign (use of void* can lead to loss of type safety), so I would suggest that you look for a different way to achieve what you want.
I have a class, Mouse, than handles mouse events. It consists of a number of static functions for simple "where is it, etc" calls, but it also has a few non-static members, namely some event-handling stuff when it's used as an object. I'm having trouble, however with how I can allow any object to subscribe to the events. In my Mouse.h file I have the follwing declarations: (excuse the syntax errors, this is from memory)
typedef void (*MouseEvent)(Point pos,MouseButton button)
class Mouse {
MouseEvent m_downEvent;
//...
void HookMouseDown(MouseEvent handler);
void OnMouseDown();
}
...and in the implemenation...
void Mouse::HookMouseDown(MouseEvent handler) {
if (handler != NULL) m_downEvent = handler;
}
void Mouse::OnMouseDown() {
if (m_downEvent != NULL) m_downEvent(m_pos,m_button);
}
Now in my subscriber's code, It seemed logical to hook up the event this way:
m_mouse.HookMouseDown(&MyClass::MouseDown);
But my compiler (MVC2008) doesn't like the fact that I'm passing it a pointer-to-member-function rather a pointer-to-free-function. After some research on here, I discovered that changing my typedef to
typedef void (MyClass::*MouseEvent)(Point pos,MouseButton button)
it won't complain and will work fine, but the problem is that this restricts subscribers to the event to only MyClass objects.
Will I have to get templates involved to allow any object to subscribe to these events? Or would it be bad design to allow anything to consume mouse events in the first place?
it won't complain and will work fine, but the problem is that this restricts subscribers to the event to only MyClass objects.
Nope, you will be able to 'invoke' that member through derived class instances as well.
Regardless, the problem has been solved many times over using std::mem_fun_ptr (c++03) std::function<> (c++0x), std::bind (c++0x) and boost::bind.
Here is a full sample, see it live on https://ideone.com/mut9V:
#include <iostream>
struct MyBase
{
virtual void DoStuff(int, float) { std::cout << "Base" << std::endl; }
};
struct MyDerived : MyBase
{
virtual void DoStuff(int, float) { std::cout << "Derived" << std::endl; }
};
int main()
{
typedef void (MyBase::*memfun)(int, float);
memfun event(&MyBase::DoStuff);
MyBase base;
MyDerived derived;
(base.*event)(42, 3.14);
(derived.*event)(42, 3.14);
}
To make the class Mouse handle pointers to member-functions of arbitrary classes, you could make it a template:
template<class T>
class Mouse {
typedef void (T::*MouseEvent)(Point pos,MouseButton button);
MouseEvent m_downEvent;
//...
void HookMouseDown(MouseEvent handler);
void OnMouseDown();
}
Or would it be bad design to allow anything to consume mouse events in the first place?
I think it is quite nice to use an event based design. On the other hand it is a pain in the ass to support both free functions and member functions. Especially if you have also to supply the instance which calls this function.
Coincidentally I stumbled upon a Delegate implementation which exactly deals with this matter. Have a look at this interesting article.
The HookMouseDown could now return a reference to an internal delegate, which then can be bound to either a free function or a member function:
mouse.HookMouseDown().Bind<MyClass, &MyClass::MyMember>(myinstance);
You really want std::function and std::bind/lambdas (function/bind also available in Boost). This more than adequately solves the problem.
I want to implement a class in c++ that has a callback.
So I think I need a method that has 2 arguments:
the target object. (let's say
*myObj)
the pointer to a member function of
the target object. (so i can do
*myObj->memberFunc(); )
The conditions are:
myObj can be from any class.
the member function that is gonna be the callback function is non-static.
I've been reading about this but it seems like I need to know the class of myObj before hand. But I am not sure how to do it. How can I handle this? Is this possible in C++?
This is something I have in mind but is surely incorrect.
class MyClassWithCallback{
public
void *targetObj;
void (*callback)(int number);
void setCallback(void *myObj, void(*callbackPtr)(int number)){
targetObj = myObj;
callback = callbackPtr;
};
void callCallback(int a){
(myObj)->ptr(a);
};
};
class Target{
public
int res;
void doSomething(int a){//so something here. This is gonna be the callback function};
};
int main(){
Target myTarget;
MyClassWithCallback myCaller;
myCaller.setCallback((void *)&myTarget, &doSomething);
}
I appreciate any help.
Thank you.
UPDATE
Most of you said Observing and Delegation, well that's i exactly what i am looking for, I am kind of a Objective-C/Cocoa minded guy.
My current implementation is using interfaces with virtual functions. Is just I thought it would be "smarter" to just pass the object and a member function pointer (like boost!) instead of defining an Interface. But It seems that everybody agrees that Interfaces are the easiest way right? Boost seems to be a good idea, (assuming is installed)
The best solution, use boost::function with boost::bind, or if your compiler supports tr1/c++0x use std::tr1::function and std::tr1::bind.
So it becomes as simple as:
boost::function<void()> callback;
Target myTarget;
callback=boost::bind(&Target::doSomething,&myTarget);
callback(); // calls the function
And your set callback becomes:
class MyClassWithCallback{
public:
void setCallback(boost::function<void()> const &cb)
{
callback_ = cb;
}
void call_it() { callback_(); }
private:
boost::function<void()> callback_;
};
Otherwise you need to implement some abstract class
struct callback {
virtual void call() = 0;
virtual ~callback() {}
};
struct TargetCallback {
virtual void call() { ((*self).*member)()); }
void (Target::*member)();
Target *self;
TargetCallback(void (Target::*m)(),Target *p) :
member(m),
self(p)
{}
};
And then use:
myCaller.setCallback(new TargetCallback(&Target::doSomething,&myTarget));
When your class get modified into:
class MyClassWithCallback{
public:
void setCallback(callback *cb)
{
callback_.reset(cb);
}
void call_it() { callback_->call(); }
private:
std::auto_ptr<callback> callback_;
};
And of course if the function you want to call does not change you may just implement some interface, i.e. derive Target from some abstract class with this call.
One trick is to use interfaces instead, that way you don't need specifically to know the class in your 'MyClassWithCallback', if the object passed in implements the interface.
e.g. (pseudo code)
struct myinterface
{
void doSomething()=0;
};
class Target : public myinterface { ..implement doSomething... };
and
myinterface *targetObj;
void setCallback(myinterface *myObj){
targetObj = myObj;
};
doing the callback
targetObj->doSomething();
setting it up:
Target myTarget;
MyClassWithCallback myCaller;
myCaller.setCallback(myTarget);
The Observer design pattern seems to be what you're looking for.
You have a few basic options:
1) Specify what class the callback is going to use, so that the object pointer and member function pointer types are known, and can be used in the caller. The class might have several member functions with the same signature, which you can choose between, but your options are quite limited.
One thing that you've done wrong in your code is that member function pointers and free function pointers in C++ are not the same, and are not compatible types. Your callback registration function takes a function pointer, but you're trying to pass it a member function pointer. Not allowed. Furthermore, the type of the "this" object is part of the type of a member function pointer, so there's no such thing in C++ as "a pointer to any member function which takes an integer and returns void". It has to be, "a pointer to any member function of Target which takes an integer and returns void". Hence the limited options.
2) Define a pure virtual function in an interface class. Any class which wants to receive the callback therefore can inherit from the interface class. Thanks to multiple inheritance, this doesn't interfere with the rest of your class hierarchy. This is almost exactly the same as defining an Interface in Java.
3) Use a non-member function for the callback. The for each class which wants to use it, you write a little stub free function which takes the object pointer and calls the right member function on it. So in your case you'd have:
dosomething_stub(void *obj, int a) {
((Target *)obj)->doSomething(a);
}
4) Use templates:
template<typename CB> class MyClassWithCallback {
CB *callback;
public:
void setCallback(CB &cb) { callback = &cb; }
void callCallback(int a) {
callback(a);
}
};
class Target {
void operator()(int a) { /* do something; */ }
};
int main() {
Target t;
MyClassWithCallback<T> caller;
caller.setCallback(t);
}
Whether you can use templates depends whether your ClassWithCallback is part of some big old framework - if so then it might not be possible (to be precise: might require some more tricks, such as a template class which inherits from a non-template class having a virtual member function), because you can't necessarily instantiate the entire framework once for each callback recipient.
Also, look at the Observer Pattern and signals and slots . This extends to multiple subscribers.
In C++, pointers to class methods are hardly used. The fact that you called in - it is delegates and their use is not recommended. Instead of them, you must use virtual functions and abstract classes.
However, C++ would not have been so fond of me, if it not supported completely different concepts of programming. If you still want delegates, you should look towards "boost functional" (part of C + +0 x), it allows pointers to methods of classes regardless of the class name. Besides, in C++ Builder has type __closure - implementation of a delegate at the level of the compiler.
P.S. Sorry for bad English...
I'm trying to implement the command design pattern, but I'm stumbling accross a conceptual problem. Let's say you have a base class and a few subclasses like in the example below:
class Command : public boost::noncopyable {
virtual ResultType operator()()=0;
//Restores the model state as it was before command's execution.
virtual void undo()=0;
//Registers this command on the command stack.
void register();
};
class SomeCommand : public Command {
virtual ResultType operator()(); // Implementation doesn't really matter here
virtual void undo(); // Same
};
The thing is, everytime operator () is called on a SomeCommand instance, I'd like to add *this to a stack (mostly for undo purposes) by calling the Command's register method. I'd like to avoid calling "register" from SomeCommand::operator()(), but to have it called automaticaly (someway ;-) )
I know that when you construct a sub class such as SomeCommand, the base class constructor is called automaticaly, so I could add a call to "register" there. The thing I don't want to call register until operator()() is called.
How can I do this? I guess my design is somewhat flawed, but I don't really know how to make this work.
It looks as if you can benefit from the NVI (Non-Virtual Interface) idiom. There the interface of the command object would have no virtual methods, but would call into private extension points:
class command {
public:
void operator()() {
do_command();
add_to_undo_stack(this);
}
void undo();
private:
virtual void do_command();
virtual void do_undo();
};
There are different advantages to this approach, first of which is that you can add common functionality in the base class. Other advantages are that the interface of your class and the interface of the extension points is not bound to each other, so you could offer different signatures in your public interface and the virtual extension interface. Search for NVI and you will get much more and better explanations.
Addendum: The original article by Herb Sutter where he introduces the concept (yet unnamed)
Split the operator in two different methods, e.g. execute and executeImpl (to be honest, I don't really like the () operator). Make Command::execute non-virtual, and Command::executeImpl pure virtual, then let Command::execute perform the registration, then call it executeImpl, like this:
class Command
{
public:
ResultType execute()
{
... // do registration
return executeImpl();
}
protected:
virtual ResultType executeImpl() = 0;
};
class SomeCommand
{
protected:
virtual ResultType executeImpl();
};
Assuming it's a 'normal' application with undo and redo, I wouldn't try and mix managing the stack with the actions performed by the elements on the stack. It will get very complicated if you either have multiple undo chains (e.g. more than one tab open), or when you do-undo-redo, where the command has to know whether to add itself to undo or move itself from redo to undo, or move itself from undo to redo. It also means you need to mock the undo/redo stack to test the commands.
If you do want to mix them, then you will have three template methods, each taking the two stacks (or the command object needs to have references to the stacks it operates on when created), and each performing the move or add, then calling the function. But if you do have those three methods, you will see that they don't actually do anything other than call public functions on the command and are not used by any other part of the command, so become candidates the next time you refactor your code for cohesion.
Instead, I'd create an UndoRedoStack class which has an execute_command(Command*command) function, and leave the command as simple as possible.
Basically Patrick's suggestion is the same as David's which is also the same as mine. Use NVI (non-virtual interface idiom) for this purpose. Pure virtual interfaces lack any kind of centralized control. You could alternatively create a separate abstract base class that all commands inherit, but why bother?
For detailed discussion about why NVIs are desirable, see C++ Coding Standards by Herb Sutter. There he goes so far as to suggest making all public functions non-virtual to achieve a strict separation of overridable code from public interface code (which should not be overridable so that you can always have some centralized control and add instrumentation, pre/post-condition checking, and whatever else you need).
class Command
{
public:
void operator()()
{
do_command();
add_to_undo_stack(this);
}
void undo()
{
// This might seem pointless now to just call do_undo but
// it could become beneficial later if you want to do some
// error-checking, for instance, without having to do it
// in every single command subclass's undo implementation.
do_undo();
}
private:
virtual void do_command() = 0;
virtual void do_undo() = 0;
};
If we take a step back and look at the general problem instead of the immediate question being asked, I think Pete offers some very good advice. Making Command responsible for adding itself to the undo stack is not particularly flexible. It can be independent of the container in which it resides. Those higher-level responsibilities should probably be a part of the actual container which you can also make responsible for executing and undoing the command.
Nevertheless, it should be very helpful to study NVI. I've seen too many developers write pure virtual interfaces like this out of the historical benefits they had only to add the same code to every subclass that defines it when it need only be implemented in one central place. It is a very handy tool to add to your programming toolbox.
I once had a project to create a 3D modelling application and for that I used to have the same requirement. As far as I understood when working on it was that no matter what and operation should always know what it did and therefore should know how to undo it. So I had a base class created for each operation and it's operation state as shown below.
class OperationState
{
protected:
Operation& mParent;
OperationState(Operation& parent);
public:
virtual ~OperationState();
Operation& getParent();
};
class Operation
{
private:
const std::string mName;
public:
Operation(const std::string& name);
virtual ~Operation();
const std::string& getName() const{return mName;}
virtual OperationState* operator ()() = 0;
virtual bool undo(OperationState* state) = 0;
virtual bool redo(OperationState* state) = 0;
};
Creating a function and it's state would be like:
class MoveState : public OperationState
{
public:
struct ObjectPos
{
Object* object;
Vector3 prevPosition;
};
MoveState(MoveOperation& parent):OperationState(parent){}
typedef std::list<ObjectPos> PrevPositions;
PrevPositions prevPositions;
};
class MoveOperation : public Operation
{
public:
MoveOperation():Operation("Move"){}
~MoveOperation();
// Implement the function and return the previous
// previous states of the objects this function
// changed.
virtual OperationState* operator ()();
// Implement the undo function
virtual bool undo(OperationState* state);
// Implement the redo function
virtual bool redo(OperationState* state);
};
There used to be a class called OperationManager. This registered different functions and created instances of them within it like:
OperationManager& opMgr = OperationManager::GetInstance();
opMgr.register<MoveOperation>();
The register function was like:
template <typename T>
void OperationManager::register()
{
T* op = new T();
const std::string& op_name = op->getName();
if(mOperations.count(op_name))
{
delete op;
}else{
mOperations[op_name] = op;
}
}
Whenever a function was to be executed, it would be based on the currently selected objects or the whatever it needs to work on. NOTE: In my case, I didn't need to send the details of how much each object should move because that was being calculated by MoveOperation from the input device once it was set as the active function.
In the OperationManager, executing a function would be like:
void OperationManager::execute(const std::string& operation_name)
{
if(mOperations.count(operation_name))
{
Operation& op = *mOperations[operation_name];
OperationState* opState = op();
if(opState)
{
mUndoStack.push(opState);
}
}
}
When there's a necessity to undo, you do that from the OperationManager like:
OperationManager::GetInstance().undo();
And the undo function of the OperationManager looks like this:
void OperationManager::undo()
{
if(!mUndoStack.empty())
{
OperationState* state = mUndoStack.pop();
if(state->getParent().undo(state))
{
mRedoStack.push(state);
}else{
// Throw an exception or warn the user.
}
}
}
This made the OperationManager not be aware of what arguments each function needs and so was easy to manage different functions.