Skip to content

Versatile, easy-to-use and header-only implementation for delegates.

License

Notifications You must be signed in to change notification settings

Darky-Lucera/delegate

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

5 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Delegate Class

The Delegate class in C++ is a versatile, easy-to-use, type-safe and header-only implementation for delegates. It empowers you to craft delegate / callback / listener / event-handler objects capable of holding multiple references to a variety of entities:

  • Free functions
  • Static member functions
  • Functors
  • Non-static member functions (const or non-const)
  • Lambda functions (with and without captures)
  • std::function
  • std::bind

This utility is derived from an earlier version employed in the MindShake video game engine from Lucera Project. While I can't recall the precise inception date of the initial class, I developed it prior to the establishment of Lucera in 2009, utilizing C++98. Subsequently, I enhanced it to leverage the features introduced in C++11, a transformation that took place several years ago.

Note: In all my tests, the Delegate has demonstrated comparable speed to std::function and, in some cases, even faster performance (depending on the specific scenario and compiler flags). Additionally, it is capable of holding multiple functions at the same time.

Usage

Just drop the class into your code folder and include it.

Note: We now capture exceptions on every call and show information using fprintf. Change it by your own logger.

Interface

Note: The interface has been changed and the flag lazy for removing a function it is not needed anymore.

  • id Add(function): Adds a function.
  • bool Remove(function): If the delegate is not being executed the function is removed. If it is being executed the function will be disabled and removed when the execution will finish.
  • bool RemoveById(id): Removes a funtion given its id.
  • void Clear(): Removes all functions.
  • void operator(...) const: Runs all the functions added.
  • size_t GetNumDelegates() const: Get the number of delegates added.

Examples

The main.cpp contains an exhaustive example of how to use this class.

Snippets

Here are some basic examples of how to use the Delegate class:

#include "Delegate.h"

void mousePosition(int x, int y) {
    // ...
}

class MyClass {
public:
    void mousePosition(int x, int y) {
        // ...
    }
};

int main() {
    MindShake::Delegate<void(int x, int y)> delegate;

    delegate.Add(mousePosition);

    MyClass myObject;
    delegate.Add(&myObject, &MyClass::mousePosition);

    delegate.Add([](int x, int y) {
        // ...
    });

    delegate(2, 3);

    // ...
}

If you find yourself needing to distinguish between calling a const or a non-const function, you can employ the helper functions: getNonConstMethod and getConstMethod:

class MyClass {
public:
    void memberFunction() {
        // ...
    }

    void memberFunction() const {
        // ...
    }
};

int kk() {
    MindShake::Delegate<void()> delegate;

    MyClass myObject;
    delegate.Add(&myObject, MindShake::getNonConstMethod(&MyClass::memberFunction));

    delegate.Add(&myObject, MindShake::getConstMethod(&MyClass::memberFunction));

    // ...
}

If you no longer wish to receive additional events, or if you are in the process of destroying the class that holds the delegate, it is advisable to remove it:

struct Holder {
    static MindShake::Delegate<void(int)> delegate;
};

class MyClass {
public:
    MyClass() {
        Holder::delegate.Add(this, &MyClass::memberFunction);
    }

    virtual ~MyClass() {
        Holder::delegate.Remove(this, &MyClass::memberFunction);
    }

    void memberFunction(int value) {
        // ...
    }
};

int main() {
    MyClass myObject;
    // ...
    Holder::delegate(123);
    // ...
}

If you wish to cease receiving further events for a lambda function, take note that the Add function returns an ID, facilitating the straightforward identification of the delegate to be removed:

Delegate<void()> delegate;

auto lambdaId = delegate.Add([]() {
    // ...
});

// ...
delegate.RemoveById(lambdaId);

About

Versatile, easy-to-use and header-only implementation for delegates.

Topics

Resources

License

Stars

Watchers

Forks