#include <cstdio>
struct GenericObject;
typedef void (GenericObject::*GenericMethod)(GenericObject const&);
template<class HandlerBase, class ArgBase>
struct CallTraits
{
typedef void(*CallFunc)(HandlerBase*, GenericMethod, ArgBase const&);
template<class TheHandler, class TheArg>
static void callfunc(HandlerBase* h, GenericMethod m, ArgBase const& a)
{
typedef void (TheHandler::*TheMethod)(TheArg const&);
TheHandler* th = (TheHandler*)h;
TheMethod tm = (TheMethod)m;
TheArg const& ta = (TheArg const&)a;
printf(" < %p->...(*%p)\n", h, &a);
printf(" > %p->...(*%p)\n", th, &ta);
(th->*tm)(ta);
}
struct Delegate
{
HandlerBase* h;
GenericMethod m;
CallFunc c;
};
template<class TheHandler, class TheArg>
static Delegate make_delegate(TheHandler* th, void (TheHandler::*tm)(TheArg const&))
{
Delegate d = { (HandlerBase*)th, (GenericMethod)tm, &callfunc<TheHandler,TheArg> };
return d;
}
static void call_delegate(Delegate const& d, ArgBase const& a)
{
d.c(d.h, d.m, a);
}
};
struct A0 { int x; virtual ~A0() {} };
struct A1 { int y; };
struct A : A0, A1 {};
struct H0 { int x; virtual ~H0() {} };
struct H1 { int y; virtual ~H1() {} };
struct H : H0, H1
{
virtual void foo(A const& a)
{
printf(" = %p->foo(*%p)\n", this, &a);
}
};
int main()
{
typedef CallTraits<H1, A1> CT;
A a; H h;
printf("directly:\n");
h.foo(a);
printf("delegated:\n");
CT::Delegate d = CT::make_delegate(&h, &H::foo);
printf("delegate: %p %p sizeof(fun)=%d sizeof(method)=%d\n", d.h, d.c, sizeof(d.c), sizeof(d.m));
CT::call_delegate(d, a);
}
I2luY2x1ZGUgPGNzdGRpbz4KCnN0cnVjdCBHZW5lcmljT2JqZWN0Owp0eXBlZGVmIHZvaWQgKEdlbmVyaWNPYmplY3Q6OipHZW5lcmljTWV0aG9kKShHZW5lcmljT2JqZWN0IGNvbnN0Jik7Cgp0ZW1wbGF0ZTxjbGFzcyBIYW5kbGVyQmFzZSwgY2xhc3MgQXJnQmFzZT4Kc3RydWN0IENhbGxUcmFpdHMKewoJdHlwZWRlZiB2b2lkKCpDYWxsRnVuYykoSGFuZGxlckJhc2UqLCBHZW5lcmljTWV0aG9kLCBBcmdCYXNlIGNvbnN0Jik7CgoJdGVtcGxhdGU8Y2xhc3MgVGhlSGFuZGxlciwgY2xhc3MgVGhlQXJnPgoJc3RhdGljIHZvaWQgY2FsbGZ1bmMoSGFuZGxlckJhc2UqIGgsIEdlbmVyaWNNZXRob2QgbSwgQXJnQmFzZSBjb25zdCYgYSkKCXsKCQl0eXBlZGVmIHZvaWQgKFRoZUhhbmRsZXI6OipUaGVNZXRob2QpKFRoZUFyZyBjb25zdCYpOwoKCQlUaGVIYW5kbGVyKiAgIHRoID0gKFRoZUhhbmRsZXIqKWg7CgkJVGhlTWV0aG9kICAgICB0bSA9IChUaGVNZXRob2QpbTsKCQlUaGVBcmcgY29uc3QmIHRhID0gKFRoZUFyZyBjb25zdCYpYTsKCgkJcHJpbnRmKCIgPCAlcC0+Li4uKColcClcbiIsIGgsICAmYSk7CgkJcHJpbnRmKCIgPiAlcC0+Li4uKColcClcbiIsIHRoLCAmdGEpOwoJCSh0aC0+KnRtKSh0YSk7Cgl9CgoJc3RydWN0IERlbGVnYXRlCgl7CgkJSGFuZGxlckJhc2UqICBoOwoJCUdlbmVyaWNNZXRob2QgbTsKCQlDYWxsRnVuYyAgICAgIGM7Cgl9OwoKCXRlbXBsYXRlPGNsYXNzIFRoZUhhbmRsZXIsIGNsYXNzIFRoZUFyZz4KCXN0YXRpYyBEZWxlZ2F0ZSBtYWtlX2RlbGVnYXRlKFRoZUhhbmRsZXIqIHRoLCB2b2lkIChUaGVIYW5kbGVyOjoqdG0pKFRoZUFyZyBjb25zdCYpKQoJewoJCURlbGVnYXRlIGQgPSB7IChIYW5kbGVyQmFzZSopdGgsIChHZW5lcmljTWV0aG9kKXRtLCAmY2FsbGZ1bmM8VGhlSGFuZGxlcixUaGVBcmc+IH07CgkJcmV0dXJuIGQ7Cgl9CgoJc3RhdGljIHZvaWQgY2FsbF9kZWxlZ2F0ZShEZWxlZ2F0ZSBjb25zdCYgZCwgQXJnQmFzZSBjb25zdCYgYSkKCXsKCQlkLmMoZC5oLCBkLm0sIGEpOwoJfQp9OwoKc3RydWN0IEEwIHsgaW50IHg7IHZpcnR1YWwgfkEwKCkge30gfTsKc3RydWN0IEExIHsgaW50IHk7IH07CnN0cnVjdCBBIDogQTAsIEExIHt9OwoKCnN0cnVjdCBIMCB7IGludCB4OyB2aXJ0dWFsIH5IMCgpIHt9IH07CnN0cnVjdCBIMSB7IGludCB5OyB2aXJ0dWFsIH5IMSgpIHt9IH07CnN0cnVjdCBIIDogSDAsIEgxCnsKCXZpcnR1YWwgdm9pZCBmb28oQSBjb25zdCYgYSkKCXsKCQlwcmludGYoIiA9ICVwLT5mb28oKiVwKVxuIiwgdGhpcywgJmEpOwoJfQp9OwoKCgoKCmludCBtYWluKCkKewoJdHlwZWRlZiBDYWxsVHJhaXRzPEgxLCBBMT4gQ1Q7CgoJQSBhOyBIIGg7CgoJcHJpbnRmKCJkaXJlY3RseTpcbiIpOwoJaC5mb28oYSk7CgoJcHJpbnRmKCJkZWxlZ2F0ZWQ6XG4iKTsKCUNUOjpEZWxlZ2F0ZSBkID0gQ1Q6Om1ha2VfZGVsZWdhdGUoJmgsICZIOjpmb28pOwoJcHJpbnRmKCJkZWxlZ2F0ZTogJXAgJXAgIHNpemVvZihmdW4pPSVkIHNpemVvZihtZXRob2QpPSVkXG4iLCBkLmgsIGQuYywgc2l6ZW9mKGQuYyksIHNpemVvZihkLm0pKTsKCUNUOjpjYWxsX2RlbGVnYXRlKGQsIGEpOwp9Cg==