/*
Copyright 2004-2006 Chris Kaiser
This software is free to use under the condition that this
notice remains intact. All liability rests with the entity
using this code.
*/
#pragma once
#include <iostream>
using namespace std;
#pragma warning(disable: 4786) //debug info more than 255 chars
#pragma warning(disable: 4355) //using this in a base intitializer
/////////////////////////HANDLER///////////////////////////////////
//a couple of placeholder types we're hoping to be unique
namespace def
{
class Default { public: Default() {} };
class emptyVoidReturnSigAmibiguityFix { };
};
//Our default data type, small and flexible
typedef def::Default& TDEF_DATA;
//our hidden parameter types defined to fix the abiguity call
//of a signature differing only by return type, this is for the call operators
typedef def::emptyVoidReturnSigAmibiguityFix* HiddenParam;
#define HiddenParamVal (def::emptyVoidReturnSigAmibiguityFix*)0
//some enumerations used in TMappedHandler but publicly available
typedef enum { e0Params = 0, e1Params, e2Params, e3Params,
e4Params, e5Params, e6Params, e7Params } eNumberOfParams;
typedef enum { NO=0, YES=1 } eReturn;
#define SIGNATURE_ALGO(P, R) ((P == e0Params && R == NO) ? 0 : (1+((1+R)*P)))
template<typename tMapParent = def::Default,
eNumberOfParams ePARAMS = e0Params, eReturn eRET = NO,
typename tResult = TDEF_DATA, typename tP1 = TDEF_DATA,
typename tP2 = TDEF_DATA, typename tP3 = TDEF_DATA,
typename tP4 = TDEF_DATA, typename tP5 = TDEF_DATA,
typename tP6 = TDEF_DATA, typename tP7 = TDEF_DATA>
class TMappedHandler
{
tMapParent *m_pThis;
TMappedHandler() : m_pThis(0) { }
protected:
typedef TMappedHandler<tMapParent, ePARAMS, eRET, tResult, tP1,
tP2, tP3, tP4, tP5, tP6, tP7> HandlerBase;
public:
TMappedHandler(const HandlerBase &rhs) { *this=rhs; }
TMappedHandler(tMapParent *pThis) : m_pThis(pThis) { }
typedef void(tMapParent::*FX_pDef)();
typedef tResult(tMapParent::*FX_p0PWRet)();
typedef void(tMapParent::*FX_p1PWORet)(tP1);
typedef tResult(tMapParent::*FX_p1PWRet)(tP1);
typedef void(tMapParent::*FX_p2PWORet)(tP1, tP2);
typedef tResult(tMapParent::*FX_p2PWRet)(tP1, tP2);
typedef void(tMapParent::*FX_p3PWORet)(tP1, tP2, tP3);
typedef tResult(tMapParent::*FX_p3PWRet)(tP1, tP2, tP3);
typedef void(tMapParent::*FX_p4PWORet)(tP1, tP2, tP3, tP4);
typedef tResult(tMapParent::*FX_p4PWRet)(tP1, tP2, tP3, tP4);
typedef void(tMapParent::*FX_p5PWORet)(tP1, tP2, tP3, tP4, tP5);
typedef tResult(tMapParent::*FX_p5PWRet)(tP1, tP2, tP3, tP4, tP5);
typedef void(tMapParent::*FX_p6PWORet)(tP1, tP2, tP3, tP4, tP5, tP6);
typedef tResult(tMapParent::*FX_p6PWRet)(tP1, tP2, tP3, tP4, tP5, tP6);
typedef void(tMapParent::*FX_p7PWORet)(tP1, tP2, tP3, tP4, tP5, tP6, tP7);
typedef tResult(tMapParent::*FX_p7PWRet)(tP1, tP2, tP3, tP4, tP5, tP6, tP7);
protected:
union MMF
{
FX_pDef pfn;
FX_p0PWRet pfn0;
FX_p1PWORet pfnV1;
FX_p1PWRet pfn1;
FX_p2PWORet pfnV2;
FX_p2PWRet pfn2;
FX_p3PWORet pfnV3;
FX_p3PWRet pfn3;
FX_p4PWORet pfnV4;
FX_p4PWRet pfn4;
FX_p5PWORet pfnV5;
FX_p5PWRet pfn5;
FX_p6PWORet pfnV6;
FX_p6PWRet pfn6;
FX_p7PWORet pfnV7;
FX_p7PWRet pfn7;
};
FX_pDef m_pfn;
public:
HandlerBase& operator=(const HandlerBase &rhs)
{
if(&rhs == this)
return *this;
m_pThis = rhs.m_pThis;
m_pfn = rhs.m_pfn;
return *this;
}
FX_pDef operator=(FX_pDef pfn) { m_pfn = pfn; return pfn; }
FX_p0PWRet operator=(FX_p0PWRet pfn) { m_pfn = (FX_pDef)pfn; return pfn; }
FX_p1PWORet operator=(FX_p1PWORet pfn) { m_pfn = (FX_pDef)pfn; return pfn; }
FX_p1PWRet operator=(FX_p1PWRet pfn) { m_pfn = (FX_pDef)pfn; return pfn; }
FX_p2PWORet operator=(FX_p2PWORet pfn) { m_pfn = (FX_pDef)pfn; return pfn; }
FX_p2PWRet operator=(FX_p2PWRet pfn) { m_pfn = (FX_pDef)pfn; return pfn; }
FX_p3PWORet operator=(FX_p3PWORet pfn) { m_pfn = (FX_pDef)pfn; return pfn; }
FX_p3PWRet operator=(FX_p3PWRet pfn) { m_pfn = (FX_pDef)pfn; return pfn; }
FX_p4PWORet operator=(FX_p4PWORet pfn) { m_pfn = (FX_pDef)pfn; return pfn; }
FX_p4PWRet operator=(FX_p4PWRet pfn) { m_pfn = (FX_pDef)pfn; return pfn; }
FX_p5PWORet operator=(FX_p5PWORet pfn) { m_pfn = (FX_pDef)pfn; return pfn; }
FX_p5PWRet operator=(FX_p5PWRet pfn) { m_pfn = (FX_pDef)pfn; return pfn; }
FX_p6PWORet operator=(FX_p6PWORet pfn) { m_pfn = (FX_pDef)pfn; return pfn; }
FX_p6PWRet operator=(FX_p6PWRet pfn) { m_pfn = (FX_pDef)pfn; return pfn; }
FX_p7PWORet operator=(FX_p7PWORet pfn) { m_pfn = (FX_pDef)pfn; return pfn; }
FX_p7PWRet operator=(FX_p7PWRet pfn) { m_pfn = (FX_pDef)pfn; return pfn; }
//HiddenParam is a placeholder allowing the mapping of methods
//differing only by return type, meant to be wrapped by a deriving
//handler to obscure its details
typedef HiddenParam HP;
#define MMF_CALL(N) MMF mmf;mmf.pfn=m_pfn;(m_pThis->*mmf.pfnV##N)
#define return_MMF_CALL(N) MMF mmf;mmf.pfn=m_pfn;return(m_pThis->*mmf.pfn##N)
//Call operators
void operator()(HiddenParam){(m_pThis->*m_pfn)();}
tResult operator()(){return_MMF_CALL(0)();}
void operator()(tP1 p1,HP){MMF_CALL(1)(p1);}
tResult operator()(tP1 p1){return_MMF_CALL(1)(p1);}
void operator()(tP1 p1,tP2 p2,HP){MMF_CALL(2)(p1,p2);}
tResult operator()(tP1 p1,tP2 p2){return_MMF_CALL(2)(p1,p2);}
void operator()(tP1 p1,tP2 p2,tP3 p3,HP){MMF_CALL(3)(p1,p2,p3);}
tResult operator()(tP1 p1,tP2 p2,tP3 p3){return_MMF_CALL(3)(p1,p2,p3);}
void operator()(tP1 p1,tP2 p2,tP3 p3,tP4 p4,HP){MMF_CALL(4)(p1,p2,p3,p4);}
tResult operator()(tP1 p1,tP2 p2,tP3 p3,tP4 p4)
{return_MMF_CALL(4)(p1,p2,p3,p4);}
void operator()(tP1 p1,tP2 p2,tP3 p3,tP4 p4,tP5 p5,HP)
{MMF_CALL(5)(p1,p2,p3,p4,p5);}
tResult operator()(tP1 p1,tP2 p2,tP3 p3,tP4 p4,tP5 p5)
{return_MMF_CALL(5)(p1,p2,p3,p4,p5);}
void operator()(tP1 p1,tP2 p2,tP3 p3,tP4 p4,tP5 p5,tP6 p6,HP)
{MMF_CALL(6)(p1,p2,p3,p4,p5,p6);}
tResult operator()(tP1 p1,tP2 p2,tP3 p3,tP4 p4,tP5 p5,tP6 p6)
{return_MMF_CALL(6)(p1,p2,p3,p4,p5,p6);}
void operator()(tP1 p1,tP2 p2,tP3 p3,tP4 p4,tP5 p5,tP6 p6,tP7 p7,HP)
{MMF_CALL(7)(p1,p2,p3,p4,p5,p6,p7);}
tResult operator()(tP1 p1,tP2 p2,tP3 p3,tP4 p4,tP5 p5,tP6 p6,tP7 p7)
{return_MMF_CALL(7)(p1,p2,p3,p4,p5,p6,p7);}
};
////////////////////////////////////////////////////////////////////
class MHTester;
typedef TMappedHandler<MHTester, e1Params, YES, bool, int> TestHandler;
class MHTester
{
TestHandler m_handler;
public:
MHTester() : m_handler(this)
{
m_handler = &MHTester::TestMethod;
}
TestHandler &GetHandler()
{
return m_handler;
}
bool TestMethod(int testValue)
{
cout << "\t" << testValue << "\tis the number being tested!\n\n";
return true;
}
};