Skip to content

Instantly share code, notes, and snippets.

@xenobrain
Last active May 5, 2023 16:26
Show Gist options
  • Save xenobrain/ed90e8a54ad948cebf480fbbc3d0772b to your computer and use it in GitHub Desktop.
Save xenobrain/ed90e8a54ad948cebf480fbbc3d0772b to your computer and use it in GitHub Desktop.
delegate
template <typename T> class delegate;
template <typename R, typename... Args> class delegate<R(Args...)> {
public:
template <R(*function)(Args...)> auto bind(void) -> void {
_instance = nullptr;
_proxy = &function_proxy<function>;
}
template <class C, R(C::* function)(Args...)> auto bind(C* instance) -> void {
_instance = instance;
_proxy = &method_proxy<C, function>;
}
template <class C, R(C::* function)(Args...) const> auto bind(const C* instance) -> void {
_instance = const_cast<C*>(instance);
_proxy = &const_method_proxy<C, function>;
}
auto invoke(Args... args) -> R const { return _proxy(_instance, static_cast<Args&&>(args)...); }
private:
typedef R(*proxy_function)(void*, Args...);
template <R(*function)(Args...)> auto static function_proxy(void*, Args... args) -> R {
return function(static_cast<Args&&>(args)...);
}
template <class C, R(C::* function)(Args...)> auto static method_proxy(void* instance, Args... args) -> R {
return (static_cast<C*>(instance)->*function)(static_cast<Args&&>(args)...);
}
template <class C, R(C::* function)(Args...) const> auto static const_method_proxy(void* instance, Args... args) -> R {
return (static_cast<const C*>(instance)->*function)(static_cast<Args&&>(args)...);
}
void* _instance = nullptr;
proxy_function _proxy = nullptr;
};
// pre-C++11 version
//#include "Delegate.h"
// C++11 version
#include "delegate.h"
#include <windows.h>
void Func0(void)
{
}
int Func1(int a)
{
return a + 10;
}
float Func2(float a, float b)
{
return a + b;
}
struct Test
{
void Func0(void)
{
}
void Func0(void) const
{
}
int Func1(int a)
{
return a + 20;
}
int Func1(int a) const
{
return a + 20;
}
float Func2(float a, float b)
{
return a + b;
}
float Func2(float a, float b) const
{
return a + b;
}
};
int main(void)
{
// delegate with zero arguments
{
typedef delegate<void(void)> TestDelegate;
TestDelegate d;
d.bind<&Func0>();
d.invoke();
}
// delegate with one argument
{
typedef delegate<int(int)> TestDelegate;
TestDelegate d;
d.bind<&Func1>();
d.invoke(10);
Test t;
d.bind<Test, &Test::Func1>(&t);
d.invoke(10);
const Test ct;
d.bind<Test, &Test::Func1>(&ct);
d.invoke(10);
}
// delegate with two arguments
{
typedef delegate<float(float, float)> TestDelegate;
TestDelegate d;
d.bind<&Func2>();
d.invoke(10.0f, 20.0f);
Test t;
d.bind<Test, &Test::Func2>(&t);
d.invoke(10.0f, 20.0f);
const Test ct;
d.bind<Test, &Test::Func2>(&ct);
d.invoke(10.0f, 20.0f);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment