Last active
May 5, 2023 16:26
-
-
Save xenobrain/ed90e8a54ad948cebf480fbbc3d0772b to your computer and use it in GitHub Desktop.
delegate
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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; | |
}; | |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// 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