#include <iostream>
class Null { };
#define DELEGATE(returnType, ...) Delegate<returnType (*)(__VA_ARGS__), returnType (Null::*)(__VA_ARGS__)>
#define ARGS(...) __VA_ARGS__
template<class _FunctionType, class _MemberType>
struct Delegate {
typedef _FunctionType FunctionType;
typedef _MemberType MemberType;
Null* mpThis;
union DelPtr {
_FunctionType asStatic;
_MemberType asMember;
DelPtr(_FunctionType p) : asStatic(p) { }
DelPtr(_MemberType p) : asMember(p) { }
};
DelPtr mpfn;
Delegate(_FunctionType pfn) : mpThis(NULL), mpfn(pfn) { }
Delegate(_MemberType pfn, void* pThis) : mpThis((Null*)pThis), mpfn(pfn) { }
};
#define INVOKE(_delegate, ...) ( \
(_delegate).mpThis ? \
(((_delegate).mpThis)->*((_delegate).mpfn.asMember))(__VA_ARGS__) \
: \
((_delegate).mpfn.asStatic)(__VA_ARGS__) \
)
float test1(int a, int b) {
std::cout << "a:" << a << std::endl;
std::cout << "b:" << b << std::endl;
return 7.0f;
}
class TestClass {
public:
double x;
float test2(int a, int b) {
std::cout << "TestClass a:" << a << std::endl;
std::cout << "TestClass b:" << b << std::endl;
std::cout << "TestClass x:" << x << std::endl;
return 5.0f;
}
};
class TestClass2 {
public:
char c;
float test3(int a, int b) {
std::cout << "TestClass2 a:" << a << std::endl;
std::cout << "TestClass2 b:" << b << std::endl;
std::cout << "TestClass2 c:" << c << std::endl;
return 3.0f;
}
};
// Declare MANUALLY
// typedef float (*FnStatic)(int, int) ;
// typedef float (NullClass::*FnMember)(int, int);
// typedef Delegate<FnStatic, FnMember> Delegate1;
// Declare using DELEGATE macro
typedef DELEGATE(float, ARGS(int, int)) Delegate1;
int main() {
TestClass obj;
obj.x = 23.3;
TestClass2 obj2;
obj2.c = 'h';
std::cout << "test\n";
Delegate1 d = Delegate1(test1);
Delegate1 e = Delegate1((Delegate1::MemberType)&TestClass::test2, &obj);
Delegate1 f = Delegate1((Delegate1::MemberType)&TestClass2::test3, &obj2);
std::cout << "d return value: " << (INVOKE(d, ARGS(5, 6))) << std::endl;
std::cout << "e return value: " << (INVOKE(e, ARGS(8, 9))) << std::endl;
std::cout << "f return value: " << (INVOKE(f, ARGS(1, 2))) << std::endl;
int x;
std::cin >> x;
return 0;
}
I2luY2x1ZGUgPGlvc3RyZWFtPgoKY2xhc3MgTnVsbCB7IH07CgojZGVmaW5lIERFTEVHQVRFKHJldHVyblR5cGUsIC4uLikgRGVsZWdhdGU8cmV0dXJuVHlwZSAoKikoX19WQV9BUkdTX18pLCByZXR1cm5UeXBlIChOdWxsOjoqKShfX1ZBX0FSR1NfXyk+CiNkZWZpbmUgQVJHUyguLi4pIF9fVkFfQVJHU19fCgp0ZW1wbGF0ZTxjbGFzcyBfRnVuY3Rpb25UeXBlLCBjbGFzcyBfTWVtYmVyVHlwZT4Kc3RydWN0IERlbGVnYXRlIHsKCXR5cGVkZWYgX0Z1bmN0aW9uVHlwZSBGdW5jdGlvblR5cGU7Cgl0eXBlZGVmIF9NZW1iZXJUeXBlIE1lbWJlclR5cGU7CgoJTnVsbCogbXBUaGlzOwoJdW5pb24gRGVsUHRyIHsKCQlfRnVuY3Rpb25UeXBlIGFzU3RhdGljOwoJCV9NZW1iZXJUeXBlIGFzTWVtYmVyOwoJCURlbFB0cihfRnVuY3Rpb25UeXBlIHApIDogYXNTdGF0aWMocCkgeyB9CgkJRGVsUHRyKF9NZW1iZXJUeXBlIHApIDogYXNNZW1iZXIocCkgeyB9Cgl9OwoJRGVsUHRyIG1wZm47CgkKCURlbGVnYXRlKF9GdW5jdGlvblR5cGUgcGZuKSA6IG1wVGhpcyhOVUxMKSwgbXBmbihwZm4pIHsgfQoJRGVsZWdhdGUoX01lbWJlclR5cGUgcGZuLCB2b2lkKiBwVGhpcykgOiBtcFRoaXMoKE51bGwqKXBUaGlzKSwgbXBmbihwZm4pIHsgfQp9OwoKI2RlZmluZSBJTlZPS0UoX2RlbGVnYXRlLCAuLi4pICggXAoJKF9kZWxlZ2F0ZSkubXBUaGlzID8gXAoJCSgoKF9kZWxlZ2F0ZSkubXBUaGlzKS0+KigoX2RlbGVnYXRlKS5tcGZuLmFzTWVtYmVyKSkoX19WQV9BUkdTX18pIFwKCTogXAoJCSgoX2RlbGVnYXRlKS5tcGZuLmFzU3RhdGljKShfX1ZBX0FSR1NfXykgXAoJKQoKCmZsb2F0IHRlc3QxKGludCBhLCBpbnQgYikgewoJc3RkOjpjb3V0IDw8ICJhOiIgPDwgYSA8PCBzdGQ6OmVuZGw7CglzdGQ6OmNvdXQgPDwgImI6IiA8PCBiIDw8IHN0ZDo6ZW5kbDsKCXJldHVybiA3LjBmOwp9CgpjbGFzcyBUZXN0Q2xhc3MgewpwdWJsaWM6Cglkb3VibGUgeDsKCWZsb2F0IHRlc3QyKGludCBhLCBpbnQgYikgewoJCXN0ZDo6Y291dCA8PCAiVGVzdENsYXNzIGE6IiA8PCBhIDw8IHN0ZDo6ZW5kbDsKCQlzdGQ6OmNvdXQgPDwgIlRlc3RDbGFzcyBiOiIgPDwgYiA8PCBzdGQ6OmVuZGw7CgkJc3RkOjpjb3V0IDw8ICJUZXN0Q2xhc3MgeDoiIDw8IHggPDwgc3RkOjplbmRsOwoJCXJldHVybiA1LjBmOwoJfQp9OwoKY2xhc3MgVGVzdENsYXNzMiB7CnB1YmxpYzoKCWNoYXIgYzsKCWZsb2F0ICB0ZXN0MyhpbnQgYSwgaW50IGIpIHsKCQlzdGQ6OmNvdXQgPDwgIlRlc3RDbGFzczIgYToiIDw8IGEgPDwgc3RkOjplbmRsOwoJCXN0ZDo6Y291dCA8PCAiVGVzdENsYXNzMiBiOiIgPDwgYiA8PCBzdGQ6OmVuZGw7CgkJc3RkOjpjb3V0IDw8ICJUZXN0Q2xhc3MyIGM6IiA8PCBjIDw8IHN0ZDo6ZW5kbDsKCQlyZXR1cm4gMy4wZjsKCX0KfTsKCi8vIERlY2xhcmUgTUFOVUFMTFkKLy8gdHlwZWRlZiBmbG9hdCAoKkZuU3RhdGljKShpbnQsIGludCkgOwovLyB0eXBlZGVmIGZsb2F0IChOdWxsQ2xhc3M6OipGbk1lbWJlcikoaW50LCBpbnQpOwovLyB0eXBlZGVmIERlbGVnYXRlPEZuU3RhdGljLCBGbk1lbWJlcj4gRGVsZWdhdGUxOwoKLy8gRGVjbGFyZSB1c2luZyBERUxFR0FURSBtYWNybwp0eXBlZGVmIERFTEVHQVRFKGZsb2F0LCBBUkdTKGludCwgaW50KSkgRGVsZWdhdGUxOwoKaW50IG1haW4oKSB7CglUZXN0Q2xhc3Mgb2JqOwoJb2JqLnggPSAyMy4zOwoJVGVzdENsYXNzMiBvYmoyOwoJb2JqMi5jID0gJ2gnOwoKCXN0ZDo6Y291dCA8PCAidGVzdFxuIjsKCglEZWxlZ2F0ZTEgZCA9IERlbGVnYXRlMSh0ZXN0MSk7CglEZWxlZ2F0ZTEgZSA9IERlbGVnYXRlMSgoRGVsZWdhdGUxOjpNZW1iZXJUeXBlKSZUZXN0Q2xhc3M6OnRlc3QyLCAmb2JqKTsKCURlbGVnYXRlMSBmID0gRGVsZWdhdGUxKChEZWxlZ2F0ZTE6Ok1lbWJlclR5cGUpJlRlc3RDbGFzczI6OnRlc3QzLCAmb2JqMik7CgoJc3RkOjpjb3V0IDw8ICJkIHJldHVybiB2YWx1ZTogIiA8PCAoSU5WT0tFKGQsIEFSR1MoNSwgNikpKSA8PCBzdGQ6OmVuZGw7CglzdGQ6OmNvdXQgPDwgImUgcmV0dXJuIHZhbHVlOiAiIDw8IChJTlZPS0UoZSwgQVJHUyg4LCA5KSkpIDw8IHN0ZDo6ZW5kbDsKCXN0ZDo6Y291dCA8PCAiZiByZXR1cm4gdmFsdWU6ICIgPDwgKElOVk9LRShmLCBBUkdTKDEsIDIpKSkgPDwgc3RkOjplbmRsOwoKCWludCB4OwoJc3RkOjpjaW4gPj4geDsKCXJldHVybiAwOwp9