#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);
}
