Click here to Skip to main content
15,894,720 members
Articles / Programming Languages / C++

MappedHandler - That Horrible Hack! or A Functor for Member Functions

Rate me:
Please Sign up or sign in to vote.
4.75/5 (10 votes)
15 Aug 20066 min read 20.9K   498   20  
An article on yet another Standard C++ delegate-like implementation for a handler to map to non-static methods of classes.
/*
	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;
   }
};

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here


Written By
Web Developer
United States United States
This statement is false.

Semantic sense in a stream of syntax
twiddles my bits from degree in form
to dissipate into meaning

This statement is false.

Comments and Discussions