
I would like to determine interest in a possible library submission. I have written some code which converts a member function and object pointer combination to a free function for use in C style callbacks. It has some limitations which I will describe shortly. The basic idea is to be able to convert: R (B::*)(T0,T1,…) and B* to R (*)(T0,T1,…) Here's an example usage: class foo { int x; int test(int v) {return x + v;} }; foo* a = new foo; a->x = 3; int (*f)(int) = delegate(a, &foo::inc); cout << f(4) << endl; // outputs "7" When I first attempted this I used a technique where I allocated some executable memory in the heap and dynamically created a free function to call the member function for the instance. It was fun attempting that but, as you can imagine, as soon as I used the optimizer flags on my compiler I would get segment faults :) My second approach was to use templates and the Boost Preprocessor library to create appropriate static arrays of pointers to free functions matching the required signatures and then hand those pointers out each time the delegate() function is called. The two downsides to this are: you can only call delegate() for a certain function signature a limited number of times, and it adds a lot of potentially unused code to your executable. Here's the code (I've stripped out error checking for the sake of illustration): #include <boost/preprocessor.hpp> #ifndef _delegate_h_ #define _delegate_h_ #define MAX_DELEGATES 256 #define DELEGATE_PARAMS 0 #include "delegate_template.hpp" #undef DELEGATE_PARAMS #define DELEGATE_PARAMS 1 #include "delegate_template.hpp" #undef DELEGATE_PARAMS // … #endif // delegate_template.hpp #define DELEGATE_STORE BOOST_PP_CAT(DELEGATE_STORE,**DELEGATE_PARAMS) template <class B, class R BOOST_PP_ENUM_TRAILING_PARAMS(**DELEGATE_PARAMS, class T) > struct DELEGATE_STORE { typedef B* objectPointer; typedef R (B::*memberFunction)( BOOST_PP_ENUM_PARAMS(DELEGATE_**PARAMS, T) ); typedef R (*freeFunction)( BOOST_PP_ENUM_PARAMS(DELEGATE_**PARAMS, T) ); static int delegateCount; static int delegateMax; static objectPointer delegateObjectPointer[MAX_**DELEGATES]; static memberFunction delegateMemberFunction[MAX_**DELEGATES]; template <int i> static R func( BOOST_PP_ENUM_BINARY_PARAMS(**DELEGATE_PARAMS, T, v) ) { return (delegateObjectPointer[i]->***delegateMemberFunction[i])( BOOST_PP_ENUM_PARAMS(DELEGATE_**PARAMS, v) ); } static const freeFunction delegateFreeFunction[MAX_**DELEGATES]; static freeFunction getDelegate(objectPointer o, memberFunction m) { int delegateIndex = delegateCount++; delegateObjectPointer[**delegateIndex] = o; delegateMemberFunction[**delegateIndex] = m; return delegateFreeFunction[**delegateIndex]; } }; template <class B, class R BOOST_PP_ENUM_TRAILING_PARAMS(**DELEGATE_PARAMS, class T) > int DELEGATE_STORE<B,R BOOST_PP_ENUM_TRAILING_PARAMS(**DELEGATE_PARAMS, T)
::delegateCount = 0;
template <class B, class R BOOST_PP_ENUM_TRAILING_PARAMS(**DELEGATE_PARAMS, class T) > int DELEGATE_STORE<B,R BOOST_PP_ENUM_TRAILING_PARAMS(**DELEGATE_PARAMS, T)
::delegateMax = MAX_DELEGATES;
template <class B, class R BOOST_PP_ENUM_TRAILING_PARAMS(**DELEGATE_PARAMS, class T) > typename DELEGATE_STORE<B,R BOOST_PP_ENUM_TRAILING_PARAMS(**DELEGATE_PARAMS, T) >::memberFunction DELEGATE_STORE<B,R BOOST_PP_ENUM_TRAILING_PARAMS(**DELEGATE_PARAMS, T)
::delegateMemberFunction[MAX_**DELEGATES] = {0};
template <class B, class R BOOST_PP_ENUM_TRAILING_PARAMS(**DELEGATE_PARAMS, class T) > typename DELEGATE_STORE<B,R BOOST_PP_ENUM_TRAILING_PARAMS(**DELEGATE_PARAMS, T) >::objectPointer DELEGATE_STORE<B,R BOOST_PP_ENUM_TRAILING_PARAMS(**DELEGATE_PARAMS, T)
::delegateObjectPointer[MAX_**DELEGATES] = {0};
#define FUNC_POINTER(z, n, params) &DELEGATE_STORE<B,R BOOST_PP_ENUM_TRAILING_PARAMS(**DELEGATE_PARAMS, T) >::template func< n >, template <class B, class R BOOST_PP_ENUM_TRAILING_PARAMS(**DELEGATE_PARAMS, class T) > const typename DELEGATE_STORE<B,R BOOST_PP_ENUM_TRAILING_PARAMS(**DELEGATE_PARAMS, T) >::freeFunction DELEGATE_STORE<B,R BOOST_PP_ENUM_TRAILING_PARAMS(**DELEGATE_PARAMS, T)
::delegateFreeFunction[MAX_**DELEGATES] = {
BOOST_PP_REPEAT(MAX_DELEGATES, FUNC_POINTER,) }; template <class B, class R BOOST_PP_ENUM_TRAILING_PARAMS(**DELEGATE_PARAMS, class T) > R (*delegate( B* b, R (B::*f)( BOOST_PP_ENUM_PARAMS(DELEGATE_**PARAMS, T) ) ))( BOOST_PP_ENUM_PARAMS(DELEGATE_**PARAMS, T) ) { return DELEGATE_STORE<B,R BOOST_PP_ENUM_TRAILING_PARAMS(**DELEGATE_PARAMS, T) >::getDelegate(b, f); } // end Thankyou very much if you managed to read all the way to here! By the way, this is my first active participation in any open source project :) Jared