Hi,
I took a look look at the fast FastDelegate, and I must say I’m a little bit sceptical. It may work, it may be efficient. But it uses so many compiler-specific implementation details, it looks to me like a ticking timebomb.
And for my use the delegates of the boost library are an overkill. I also don’t like that the so called “preferred syntax” which is used througout the documentation, is not portable:
http://www.boost.org/doc/libs/1_35_0/doc/html/function/tutorial.html
So I made my own delegate template :D, which is simple and fully standard compatible (at least so I think):
http://www.noloops.ch/source/delegate.h
There are different template classes dependent on the number of parameters and if there is a return type( the code was created using a generator). The usage is quite simple:
class MyClass
{
public:
void myMethod() { }
virtual void myVirtualMethod() { }
static void myStaticMethod() { }
};
void mySub() { }
MyClass gMyClass;
void example()
{
DelegateV0 f; // V0 means void, zero parameters
f.bind<&mySub>();
f();
f.bind<&MyClass::myStaticMethod>();
f();
f.bind<MyClass, &MyClass::myMethod>(&gMyClass);
f();
f.bind<MyClass, &MyClass::myVirtualMethod>(&gMyClass);
f();
}
I wrote a first testcase with projects for Visual C++, Borland C++ Builder and Xcode (the code works also fine with GCC, tested under linux). You can download it here:
http://www.noloops.ch/source/Delegate.zip
The Implementation of the most simple case (no return value, no parameters, therefore a class instead of a template class) looks like this (here only the important methods are shown, but it is still functional):
class DelegateV0
{
typedef void (*Caller)(void *obj);
public:
DelegateV0() : caller(0), obj(0) { }
template< void (*M)() >
inline void bind()
{
obj = 0;
caller = staticCaller<M>;
}
template<class ObjectType, void (ObjectType::*M)() >
inline void bind(ObjectType *inObj)
{
bindMethod(inObj, methodCaller<ObjectType, M>);
}
inline void operator () ()
{
caller(obj);
}
inline bool isNull() { return caller == 0; }
private:
template< void (*M)() >
static void staticCaller(void *obj)
{
(*M) ();
}
template<class ObjectType, void (ObjectType::*M)() >
static void methodCaller(void *obj)
{
(static_cast<ObjectType*>(obj)->*M) ();
}
void bindMethod(void *inObj, Caller inCaller)
{
obj = inObj;
caller = (obj) ? inCaller : 0;
}
Caller caller;
void *obj;
};
In my oppinion, such a signal/slot mechanism is a great thing to implement a loose coupling between components. What do you think?
I would be very pleased about any feedback.
Greetings
Jan