#include <iostream>
#include <cstring>
template<typename ReturnType, typename... ParameterTypes>
class FDelegate
{
class FDelegateDummyClass;
using MethodType = ReturnType (FDelegateDummyClass::*)(ParameterTypes...);
MethodType BoundMethod;
public:
FDelegate()
: BoundMethod(nullptr)
{
}
template<typename ClassName>
void Bind(ReturnType (ClassName::*Method)(ParameterTypes...))
{
BoundMethod = (MethodType&)(Method);
}
void Unbind()
{
BoundMethod = nullptr;
}
bool IsBound() const
{
return BoundMethod != nullptr;
}
template<typename ObjectType>
ReturnType Execute(ObjectType* Object, ParameterTypes... Parameters)
{
return ((FDelegateDummyClass*)Object->*BoundMethod)(Parameters...);
}
template<typename ObjectType>
ReturnType ExecuteIfBound(ObjectType* Object, ParameterTypes... Parameters)
{
if (IsBound())
{
return Execute<ObjectType>(Object, Parameters...);
}
}
};
class FSampleBase
{
protected:
FDelegate<void, int> NotifyFooInvoked;
public:
void Foo(int Value)
{
NotifyFooInvoked.ExecuteIfBound(this, Value);
}
};
class FSampleDerived : public FSampleBase
{
int SampleData;
public:
FSampleDerived(int Data)
: SampleData(Data)
{
NotifyFooInvoked.Bind(&FSampleDerived::OnFooInvoked);
}
void OnFooInvoked(int Value)
{
std::cout << "Foo Invoked: " << Value << " [Sample Data: " << SampleData << "]" << std::endl;
}
};
int main()
{
FSampleDerived FirstSample(11);
FSampleDerived* SecondSample = (FSampleDerived*)std::malloc(sizeof(FSampleDerived));
std::memcpy(SecondSample, &FirstSample, sizeof(FSampleDerived));
FirstSample.Foo(1);
SecondSample->Foo(2);
std::free(SecondSample);
return 0;
}
I2luY2x1ZGUgPGlvc3RyZWFtPgojaW5jbHVkZSA8Y3N0cmluZz4KCnRlbXBsYXRlPHR5cGVuYW1lIFJldHVyblR5cGUsIHR5cGVuYW1lLi4uIFBhcmFtZXRlclR5cGVzPgpjbGFzcyBGRGVsZWdhdGUKewoJY2xhc3MgRkRlbGVnYXRlRHVtbXlDbGFzczsKCQoJdXNpbmcgTWV0aG9kVHlwZSA9IFJldHVyblR5cGUgKEZEZWxlZ2F0ZUR1bW15Q2xhc3M6OiopKFBhcmFtZXRlclR5cGVzLi4uKTsKCQoJTWV0aG9kVHlwZSBCb3VuZE1ldGhvZDsKCQpwdWJsaWM6CgoJRkRlbGVnYXRlKCkKCQk6IEJvdW5kTWV0aG9kKG51bGxwdHIpCgl7Cgl9CgkKCXRlbXBsYXRlPHR5cGVuYW1lIENsYXNzTmFtZT4KCXZvaWQgQmluZChSZXR1cm5UeXBlIChDbGFzc05hbWU6OipNZXRob2QpKFBhcmFtZXRlclR5cGVzLi4uKSkKCXsKCQlCb3VuZE1ldGhvZCA9IChNZXRob2RUeXBlJikoTWV0aG9kKTsKCX0KCQoJdm9pZCBVbmJpbmQoKQoJewoJCUJvdW5kTWV0aG9kID0gbnVsbHB0cjsKCX0KCQoJYm9vbCBJc0JvdW5kKCkgY29uc3QKCXsKCQlyZXR1cm4gQm91bmRNZXRob2QgIT0gbnVsbHB0cjsKCX0KCQoJdGVtcGxhdGU8dHlwZW5hbWUgT2JqZWN0VHlwZT4KCVJldHVyblR5cGUgRXhlY3V0ZShPYmplY3RUeXBlKiBPYmplY3QsIFBhcmFtZXRlclR5cGVzLi4uIFBhcmFtZXRlcnMpCgl7CgkJcmV0dXJuICgoRkRlbGVnYXRlRHVtbXlDbGFzcyopT2JqZWN0LT4qQm91bmRNZXRob2QpKFBhcmFtZXRlcnMuLi4pOwoJfQoJCgl0ZW1wbGF0ZTx0eXBlbmFtZSBPYmplY3RUeXBlPgoJUmV0dXJuVHlwZSBFeGVjdXRlSWZCb3VuZChPYmplY3RUeXBlKiBPYmplY3QsIFBhcmFtZXRlclR5cGVzLi4uIFBhcmFtZXRlcnMpCgl7CgkJaWYgKElzQm91bmQoKSkKCQl7CgkJCXJldHVybiBFeGVjdXRlPE9iamVjdFR5cGU+KE9iamVjdCwgUGFyYW1ldGVycy4uLik7CgkJfQoJfQp9OwoKY2xhc3MgRlNhbXBsZUJhc2UKewpwcm90ZWN0ZWQ6CgoJRkRlbGVnYXRlPHZvaWQsIGludD4gTm90aWZ5Rm9vSW52b2tlZDsKCQpwdWJsaWM6CgkKCXZvaWQgRm9vKGludCBWYWx1ZSkKCXsKCQlOb3RpZnlGb29JbnZva2VkLkV4ZWN1dGVJZkJvdW5kKHRoaXMsIFZhbHVlKTsKCX0KfTsKCmNsYXNzIEZTYW1wbGVEZXJpdmVkIDogcHVibGljIEZTYW1wbGVCYXNlCnsKCWludCBTYW1wbGVEYXRhOwoJCnB1YmxpYzoKCQoJRlNhbXBsZURlcml2ZWQoaW50IERhdGEpCgkJOiBTYW1wbGVEYXRhKERhdGEpCgl7CgkJTm90aWZ5Rm9vSW52b2tlZC5CaW5kKCZGU2FtcGxlRGVyaXZlZDo6T25Gb29JbnZva2VkKTsKCX0KCQoJdm9pZCBPbkZvb0ludm9rZWQoaW50IFZhbHVlKQoJewoJCXN0ZDo6Y291dCA8PCAiRm9vIEludm9rZWQ6ICIgPDwgVmFsdWUgPDwgIiBbU2FtcGxlIERhdGE6ICIgPDwgU2FtcGxlRGF0YSA8PCAiXSIgPDwgc3RkOjplbmRsOwoJfQp9OwoKaW50IG1haW4oKQp7CglGU2FtcGxlRGVyaXZlZCBGaXJzdFNhbXBsZSgxMSk7CglGU2FtcGxlRGVyaXZlZCogU2Vjb25kU2FtcGxlID0gKEZTYW1wbGVEZXJpdmVkKilzdGQ6Om1hbGxvYyhzaXplb2YoRlNhbXBsZURlcml2ZWQpKTsKCQoJc3RkOjptZW1jcHkoU2Vjb25kU2FtcGxlLCAmRmlyc3RTYW1wbGUsIHNpemVvZihGU2FtcGxlRGVyaXZlZCkpOwoJCglGaXJzdFNhbXBsZS5Gb28oMSk7CglTZWNvbmRTYW1wbGUtPkZvbygyKTsKCQoJc3RkOjpmcmVlKFNlY29uZFNhbXBsZSk7CgkKCXJldHVybiAwOwp9