EasyDelegate  2.0
Delegate and deferred callers for C++11.
Welcome

EasyDelegate is, as the name implies, a delegate system. It is written for C++11 with the intention to allow C++ programmers to easily create references to static and member methods that may be passed around like any other variable and invoked at any point in the code. This is helpful for a variety of situations, such as an event/listener implementation.

Example

This quick example below demonstrates how simple it is to utilize the EasyDelegate library, though for a more complete example, please refer to example.cpp.

class MyCustomClass
{
public:
unsigned int myMemberMethod(char *str, float flt, double dbl)
{
std::cout << "MyCustomClass::myMemberMethod: " << str << "," << flt << "," << dbl << std::endl;
return 2;
}
};
int main(int argc, char *argv[])
{
// Typedef our event type for later shortcutting
// Instantiate our delegate set and the custom class type.
MyEventType myDelegateSet;
MyCustomClass *myCustomClassInstance = new MyCustomClass();
// Instantiate our member Delegate; we obviously want it to persist even when out of scope in a production environment so we use a pointer.
// Notice how the class type is only cared about here rather than in the DelegateSet typedef or in the push_back call below. This is because both
// StaticDelegate and MemberDelegate types may be stored in the same DelegateSet as they have the same signature, the only difference is that
// MemberDelegate types need a this pointer to call against.
MyEventType::MemberDelegateType<MyCustomClass> *myMemberDelegate = new MyEventType::MemberDelegateType<MyCustomClass>(myCustomClassInstance, &MyCustomClass::myMemberMethod);
// Register the the myMemberMethod of MyCustomClass
myDelegateSet.push_back(myMemberDelegate);
// You can invoke the DelegateSet in the same way you invoke the delegate directly
myDelegateSet.invoke("Foo", 3.14, 3.14159);
myMemberDelegate->invoke("Foo", 3.14, 3.14159);
delete myMemberDelegate;
delete myCustomClassInstance; // Note that this causes any related MemberDelegate instances to become 'bad'.
}

The above code sample will output:

"MyCustomClass::myMemberMethod: Foo,3.14,3.14159"

"MyCustomClass::myMemberMethod: Foo,3.14,3.14159"

Deferred Callers

EasyDelegate also supports deferred call objects in C++ using the same implementations that the regular EasyDelegate library uses. They provide you with the ability to cache a call and later dispatch it completely anonymously if so desired. Take the following code sample:

static void someMethod(const float& in)
{
std::cout << "Got float: " << in << std::endl;
}
int main(int argc, char *argv[])
{
EasyDelegate::MyDeferredCaller* caller = new MyDeferredCaller(someMethod, 3.14f);
EasyDelegate::IDeferredCaler* generic = reinterpret_cast<EasyDelegate::IDeferredCaller>(caller);
generic->genericDispatch();
delete generic;
}

The output of this code will be "Got float: 3.14".

Supported Compilers and Operating Systems

EasyDelegate has been compiled and known to run on the following systems:

It should compile and run underneath of any compiler that at least supports variadic templates, std::tuple (used by CachedDelegate types), std::set, std::unordered_set but preferably has full C++11 support, though. If the use of the STL is not an option, then it should be relatively easy to switch EasyDelegate to the preferred container types for your project.

Note for MinGW/GCC Users:
EasyDelegate has been known to fail compilation (and possibly crash the compiler) on MinGW 4.7, and the same bugs probably exist in *nix native GCC. Please ensure that you are running at least GCC 4.8 when building a project with EasyDelegate.

Limitations

Due to the nature of the library, there is one limitation which derives from the usage of templates which is the inability to work with variadic methods because the ellipses ('...') involved are interpreted as a variadic template argument expansion and thusly will fail to compile. A work around for this if such functionality is necessary to your project would be to use a void* declaration instead and use that to pass a struct in which is then casted to the proper struct type on the called method's end. There may be a way to properly implement variadic method support, but I have not come up with anything yet.

Links & Attributions

The vast majority of this library was written by Robert MacGregor, licensed under the MIT license for the open source community. There exists two small types that were pulled from StackOverflow which were quite imperative to the functioning of the deferred calling systems:

Other Links: