I went for a slightly different approach. Something similar to boost::function but allowing me to bake the parameters in during call preparation. Here is a small test app I wrote :
#include <iostream>
#include <vector>
typedef void (*VoidFunc)();
int callMe() { std::cout << "callMe()\n"; return 1; }
void callMeWithInt(int a) { std::cout << "callMeWithInt(" << a << ")\n"; }
void callMeWithFloat(float a) { std::cout << "callMeWithFloat(" << a << ")\n"; }
class FunctionCaller { public : virtual void call() = 0; };
template <typename RetValT> class NoParamCaller : public FunctionCaller
{
typedef RetValT (*NoParamFunc)();
NoParamFunc theFunc;
public:
NoParamCaller(NoParamFunc func) : theFunc(func) {};
void call() { theFunc(); }
};
template <typename RetValT, typename Param1T> class OneParamCaller : public FunctionCaller
{
public:
typedef RetValT (*OneParamFunc)(Param1T);
OneParamFunc theFunc;
Param1T param1;
OneParamCaller(OneParamFunc _func, Param1T _param1) : theFunc(_func), param1(_param1) {};
void call() { theFunc(param1); }
};
int main(int argc, char* argv[])
{
std::vector<FunctionCaller*> calls;
calls.push_back(new NoParamCaller<int>(callMe));
calls.push_back(new OneParamCaller<void, int>(callMeWithInt, 1));
calls.push_back(new OneParamCaller<void, float>(callMeWithFloat, 5.5));
for (size_t i=0; i<calls.size(); i++)
{
calls[i]->call();
}
for (size_t i=0; i<calls.size(); i++)
{
delete calls[i];
}
calls.clear();
std::cout << "Finished" << std::endl;
return 0;
}
This code compiles and runs correctly. I have the FunctionCaller interface, which then gets implemented by the template classes. In this case, I only handle 0 or 1 parameters, but adding the same templates for the 2,3,4 cases (should be enough) and maybe the member function permutation as well will not be that hard.
Then, instead of having the generated function, i will have an array of FunctionCallers that i will need to call. The overhead is probably 2-3 times bigger than the assembly writing route (have to access the array and another virtual function call), but I can manage that cost.
Does this seem OK for what I'm trying to do? Anybody see something inherently wrong with it?