This section of the archives stores flipcode's complete Developer Toolbox collection, featuring a variety of mini-articles and source code contributions from our readers.

| Method Call Closure Submitted by

If you've ever played with stl and come across "functors" maybe you thought that was a cool idea. But for me it fell short of what I needed to do, just storing the function pointer wasn't enough. I needed full method call closures so that I could call a specific method of a given instance with all the arguments as given at the time of the call, but do the actual call much later. I use this so that I can queue up a list of method calls and have a set of service threads call those methods at their convenience. Using it is as simple as:

    #include <iostream
    #include "method_call.h"

    using namespace std;
    using namespace rsi;

    class ClassA
    {
        public:

        virtual void aa(string text)
        {
            cout << text << endl;
        }
    };

    int main()
    {
        ClassA* instanceA = new ClassA;
        method_call_interface* AA =
            new method_call<ClassA,string(
                instanceA,&ClassA::aa,string("In the method."));
        method_call_interface* BB =
            new method_call<ClassA,string(
                instanceA,&ClassA::aa,string("And again."));

        cout << "Hello World!" << endl;

        (*AA)();
        (*BB)();
        (*AA)();
        (*BB)();

        cout << "Goodbye World!" << endl;

        delete BB;
        delete AA;
        delete instanceA;

        return 0;
    }

I'm not sure how many compilers this works on as is, but at least it works on CodeWarrior7, and will most likely work on GCC-2.95 (it uses class method pointers). I'm giving this code up for public domain use so have fun with it. But if you use it I'd appreciate an email - just for my curiosity, and especially if you improve it!
Enjoy, Grafik. NOTE: A VC6-compatible version of this code, submitted by Steve Anichini, can be downloaded here.

Download Associated File: method_call.h (10,377 bytes)

    #ifndef method_call_h#define method_call_hnamespace rsi {struct method_call_interface { virtual void operator()() = 0; };#define ARG_TYPE(n) typename tArg ## n = method_arg_unused#define ARG_TYPES \	ARG_TYPE(1),ARG_TYPE(2),ARG_TYPE(3),ARG_TYPE(4),ARG_TYPE(5),\	ARG_TYPE(6),ARG_TYPE(7),ARG_TYPE(8),ARG_TYPE(9)struct method_arg_unused { };template<typename tArg> struct method_arg_count { enum { value = 1 }; };template<> struct method_arg_count<method_arg_unused> { enum { value = 0 }; };template<ARG_TYPES> struct method_count_args { enum { value = (	method_arg_count<tArg1>::value+	method_arg_count<tArg2>::value+	method_arg_count<tArg3>::value+	method_arg_count<tArg4>::value+	method_arg_count<tArg5>::value+	method_arg_count<tArg6>::value+	method_arg_count<tArg7>::value+	method_arg_count<tArg8>::value+	method_arg_count<tArg9>::value) }; };template<int Args> struct method_closure { };template<> struct method_closure<0> {	template<typename tClass,ARG_TYPES> struct implementation	{		typedef void (tClass::* tMethod)();		tClass* mInstance;		tMethod mMethod;		void operator()()		{			(mInstance->*mMethod)();		}		implementation(			tClass* instance, tMethod method,			tArg1 /*a1*/, tArg2 /*a2*/, tArg3 /*a3*/, tArg4 /*a4*/,			tArg5 /*a5*/, tArg6 /*a6*/, tArg7 /*a7*/, tArg8 /*a8*/, tArg9 /*a9*/)			: mInstance(instance), mMethod(method)		{		}	};};template<> struct method_closure<1> {	template<typename tClass,ARG_TYPES> struct implementation	{		typedef void (tClass::* tMethod)(tArg1 a1);		tClass* mInstance;		tMethod mMethod;		tArg1 Arg1;		void operator()()		{			(mInstance->*mMethod)(Arg1);		}		implementation(			tClass* instance, tMethod method,			tArg1 a1, tArg2 /*a2*/, tArg3 /*a3*/, tArg4 /*a4*/,			tArg5 /*a5*/, tArg6 /*a6*/, tArg7 /*a7*/, tArg8 /*a8*/, tArg9 /*a9*/)			: mInstance(instance), mMethod(method)			, Arg1(a1)		{		}	};};template<> struct method_closure<2> {	template<typename tClass,ARG_TYPES> struct implementation	{		typedef void (tClass::* tMethod)(tArg1 a1, tArg2 a2);		tClass* mInstance;		tMethod mMethod;		tArg1 Arg1;		tArg2 Arg2;		void operator()()		{			(mInstance->*mMethod)(Arg1,Arg2);		}		implementation(			tClass* instance, tMethod method,			tArg1 a1, tArg2 a2, tArg3 /*a3*/, tArg4 /*a4*/,			tArg5 /*a5*/, tArg6 /*a6*/, tArg7 /*a7*/, tArg8 /*a8*/, tArg9 /*a9*/)			: mInstance(instance), mMethod(method)			, Arg1(a1), Arg2(a2)		{		}	};};template<> struct method_closure<3> {	template<typename tClass,ARG_TYPES> struct implementation	{		typedef void (tClass::* tMethod)(tArg1 a1, tArg2 a2, tArg3 a3);		tClass* mInstance;		tMethod mMethod;		tArg1 Arg1;		tArg2 Arg2;		tArg3 Arg3;		void operator()()		{			(mInstance->*mMethod)(Arg1,Arg2,Arg3);		}		implementation(			tClass* instance, tMethod method,			tArg1 a1, tArg2 a2, tArg3 a3, tArg4 /*a4*/,			tArg5 /*a5*/, tArg6 /*a6*/, tArg7 /*a7*/, tArg8 /*a8*/, tArg9 /*a9*/)			: mInstance(instance), mMethod(method)			, Arg1(a1), Arg2(a2), Arg3(a3)		{		}	};};template<> struct method_closure<4> {	template<typename tClass,ARG_TYPES> struct implementation	{		typedef void (tClass::* tMethod)(			tArg1 a1, tArg2 a2, tArg3 a3, tArg4 a4);		tClass* mInstance;		tMethod mMethod;		tArg1 Arg1;		tArg2 Arg2;		tArg3 Arg3;		tArg4 Arg4;		void operator()()		{			(mInstance->*mMethod)(Arg1,Arg2,Arg3,Arg4);		}		implementation(			tClass* instance, tMethod method,			tArg1 a1, tArg2 a2, tArg3 a3, tArg4 a4,			tArg5 /*a5*/, tArg6 /*a6*/, tArg7 /*a7*/, tArg8 /*a8*/, tArg9 /*a9*/)			: mInstance(instance), mMethod(method)			, Arg1(a1), Arg2(a2), Arg3(a3), Arg4(a4)		{		}	};};template<> struct method_closure<5> {	template<typename tClass,ARG_TYPES> struct implementation	{		typedef void (tClass::* tMethod)(			tArg1 a1, tArg2 a2, tArg3 a3, tArg4 a4,			tArg5 a5);		tClass* mInstance;		tMethod mMethod;		tArg1 Arg1;		tArg2 Arg2;		tArg3 Arg3;		tArg4 Arg4;		tArg5 Arg5;		void operator()()		{			(mInstance->*mMethod)(Arg1,Arg2,Arg3,Arg4,				Arg5);		}		implementation(			tClass* instance, tMethod method,			tArg1 a1, tArg2 a2, tArg3 a3, tArg4 a4,			tArg5 a5, tArg6 /*a6*/, tArg7 /*a7*/, tArg8 /*a8*/, tArg9 /*a9*/)			: mInstance(instance), mMethod(method)			, Arg1(a1), Arg2(a2), Arg3(a3), Arg4(a4)			, Arg5(a5)		{		}	};};template<> struct method_closure<6> {	template<typename tClass,ARG_TYPES> struct implementation	{		typedef void (tClass::* tMethod)(			tArg1 a1, tArg2 a2, tArg3 a3, tArg4 a4,			tArg5 a5, tArg6 a6);		tClass* mInstance;		tMethod mMethod;		tArg1 Arg1;		tArg2 Arg2;		tArg3 Arg3;		tArg4 Arg4;		tArg5 Arg5;		tArg6 Arg6;		void operator()()		{			(mInstance->*mMethod)(Arg1,Arg2,Arg3,Arg4,				Arg5,Arg6);		}		implementation(			tClass* instance, tMethod method,			tArg1 a1, tArg2 a2, tArg3 a3, tArg4 a4,			tArg5 a5, tArg6 a6, tArg7 /*a7*/, tArg8 /*a8*/, tArg9 /*a9*/)			: mInstance(instance), mMethod(method)			, Arg1(a1), Arg2(a2), Arg3(a3), Arg4(a4)			, Arg5(a5), Arg6(a6)		{		}	};};template<> struct method_closure<7> {	template<typename tClass,ARG_TYPES> struct implementation	{		typedef void (tClass::* tMethod)(			tArg1 a1, tArg2 a2, tArg3 a3, tArg4 a4,			tArg5 a5, tArg6 a6, tArg7 a7);		tClass* mInstance;		tMethod mMethod;		tArg1 Arg1;		tArg2 Arg2;		tArg3 Arg3;		tArg4 Arg4;		tArg5 Arg5;		tArg6 Arg6;		tArg7 Arg7;		void operator()()		{			(mInstance->*mMethod)(Arg1,Arg2,Arg3,Arg4,				Arg5,Arg6,Arg7);		}		implementation(			tClass* instance, tMethod method,			tArg1 a1, tArg2 a2, tArg3 a3, tArg4 a4, tArg5 a5,			tArg6 a6, tArg7 a7, tArg8 /*a8*/, tArg9 /*a9*/)			: mInstance(instance), mMethod(method)			, Arg1(a1), Arg2(a2), Arg3(a3), Arg4(a4)			, Arg5(a5), Arg6(a6), Arg7(a7)		{		}	};};template<> struct method_closure<8> {	template<typename tClass,ARG_TYPES> struct implementation	{		typedef void (tClass::* tMethod)(			tArg1 a1, tArg2 a2, tArg3 a3, tArg4 a4,			tArg5 a5, tArg6 a6, tArg7 a7, tArg8 a8);		tClass* mInstance;		tMethod mMethod;		tArg1 Arg1;		tArg2 Arg2;		tArg3 Arg3;		tArg4 Arg4;		tArg5 Arg5;		tArg6 Arg6;		tArg7 Arg7;		tArg8 Arg8;		void operator()()		{			(mInstance->*mMethod)(Arg1,Arg2,Arg3,Arg4,				Arg5,Arg6,Arg7,Arg8);		}		implementation(			tClass* instance, tMethod method,			tArg1 a1, tArg2 a2, tArg3 a3, tArg4 a4,			tArg5 a5, tArg6 a6, tArg7 a7, tArg8 a8, tArg9 /*a9*/)			: mInstance(instance), mMethod(method)			, Arg1(a1), Arg2(a2), Arg3(a3), Arg4(a4)			, Arg5(a5), Arg6(a6), Arg7(a7), Arg8(a8)		{		}	};};template<> struct method_closure<9> {	template<typename tClass,ARG_TYPES> struct implementation	{		typedef void (tClass::* tMethod)(			tArg1 a1, tArg2 a2, tArg3 a3, tArg4 a4,			tArg5 a5, tArg6 a6, tArg7 a7, tArg8 a8, tArg9 a9);		tClass* mInstance;		tMethod mMethod;		tArg1 Arg1;		tArg2 Arg2;		tArg3 Arg3;		tArg4 Arg4;		tArg5 Arg5;		tArg6 Arg6;		tArg7 Arg7;		tArg8 Arg8;		tArg9 Arg9;		void operator()()		{			(mInstance->*mMethod)(Arg1,Arg2,Arg3,Arg4,				Arg5,Arg6,Arg7,Arg8,Arg9);		}		implementation(			tClass* instance, tMethod method,			tArg1 a1, tArg2 a2, tArg3 a3, tArg4 a4,			tArg5 a5, tArg6 a6, tArg7 a7, tArg8 a8, tArg9 a9)			: mInstance(instance), mMethod(method)			, Arg1(a1), Arg2(a2), Arg3(a3), Arg4(a4)			, Arg5(a5), Arg6(a6), Arg7(a7), Arg8(a8), Arg9(a9)		{		}	};};template<typename tClass,ARG_TYPES> struct method_call	: public method_call_interface{	typedef method_closure<method_count_args<tArg1,tArg2,tArg3,tArg4,		tArg5,tArg6,tArg7,tArg8,tArg9>::value>		::template implementation<tClass,tArg1,tArg2,tArg3,tArg4,			tArg5,tArg6,tArg7,tArg8,tArg9> delegate;		method_call(		tClass * aInstance, delegate::tMethod aMethod)		: mDelegate(aInstance,aMethod,			method_arg_unused(),method_arg_unused(),method_arg_unused(),			method_arg_unused(),method_arg_unused(),method_arg_unused(),			method_arg_unused(),method_arg_unused(),method_arg_unused())	{}	method_call(		tClass * aInstance, delegate::tMethod aMethod,		tArg1 a1)		: mDelegate(aInstance,aMethod,a1,			method_arg_unused(),method_arg_unused(),method_arg_unused(),			method_arg_unused(),method_arg_unused(),method_arg_unused(),			method_arg_unused(),method_arg_unused())	{}	method_call(		tClass * aInstance, delegate::tMethod aMethod,		tArg1 a1, tArg2 a2)		: mDelegate(aInstance,aMethod,a1,a2,			method_arg_unused(),method_arg_unused(),method_arg_unused(),			method_arg_unused(),method_arg_unused(),method_arg_unused(),			method_arg_unused())	{}	method_call(		tClass * aInstance, delegate::tMethod aMethod,		tArg1 a1, tArg2 a2, tArg3 a3)		: mDelegate(aInstance,aMethod,a1,a2,a3,			method_arg_unused(),method_arg_unused(),method_arg_unused(),			method_arg_unused(),method_arg_unused(),method_arg_unused())	{}	method_call(		tClass * aInstance, delegate::tMethod aMethod,		tArg1 a1, tArg2 a2, tArg3 a3, tArg4 a4)		: mDelegate(aInstance,aMethod,a1,a2,a3,a4,			method_arg_unused(),method_arg_unused(),method_arg_unused(),			method_arg_unused(),method_arg_unused())	{}	method_call(		tClass * aInstance, delegate::tMethod aMethod,		tArg1 a1, tArg2 a2, tArg3 a3, tArg4 a4,		tArg5 a5)		: mDelegate(aInstance,aMethod,a1,a2,a3,a4,a5			method_arg_unused(),method_arg_unused(),method_arg_unused(),			method_arg_unused())	{}	method_call(		tClass * aInstance, delegate::tMethod aMethod,		tArg1 a1, tArg2 a2, tArg3 a3, tArg4 a4,		tArg5 a5, tArg6 a6)		: mDelegate(aInstance,aMethod,a1,a2,a3,a4,a5,a6			method_arg_unused(),method_arg_unused(),method_arg_unused())	{}	method_call(		tClass * aInstance, delegate::tMethod aMethod,		tArg1 a1, tArg2 a2, tArg3 a3, tArg4 a4,		tArg5 a5, tArg6 a6, tArg7 a7)		: mDelegate(aInstance,aMethod,a1,a2,a3,a4,a5,a6,a7,			method_arg_unused(),method_arg_unused())	{}	method_call(		tClass * aInstance, delegate::tMethod aMethod,		tArg1 a1, tArg2 a2, tArg3 a3, tArg4 a4,		tArg5 a5, tArg6 a6, tArg7 a7, tArg8 a8)		: mDelegate(aInstance,aMethod,a1,a2,a3,a4,a5,a6,a7,a8,			method_arg_unused())	{}	method_call(		tClass * aInstance, delegate::tMethod aMethod,		tArg1 a1, tArg2 a2, tArg3 a3, tArg4 a4,		tArg5 a5, tArg6 a6, tArg7 a7, tArg8 a8, tArg9 a9)		: mDelegate(aInstance,aMethod,a1,a2,a3,a4,a5,a6,a7,a8,a9)	{}		virtual void operator()() { mDelegate(); }		delegate mDelegate;};#undef ARG_TYPE#undef ARG_TYPES}#endif

The zip file viewer built into the Developer Toolbox made use of the zlib library, as well as the zlibdll source additions.

Copyright 1999-2008 (C) FLIPCODE.COM and/or the original content author(s). All rights reserved.
Please read our Terms, Conditions, and Privacy information.