I'm designing a mechanism that will execute a set of unary function objects in sequence. These function objects are assigned during runtime, and the problem is: the parameter type of these function objects are different.
What I want to do is something like this:
class command_sequence {
private:
/* some kind of container */
public:
void add( FUNC_OBJ &func, PARAM val );
void run(void);
};
class check_temperature {
public:
void operator() (int celsius) {
if(celsius > 26) {
cooler.switch_on();
}
}
};
class log_usage {
public:
void operator() (std::string username) {
username.append(" logged in");
syslog(LOG_NOTICE,username.c_str());
}
};
command_sequence sequence;
log_usage logger;
check_temperature checker;
sequence.add(logger, std::string("administrator"));
sequence.add(checker, lobbyMeter.read_temperature());
sequence.add(logger, std::string("lecture"));
sequence.add(checker, classroomMeter.read_temperature());
sequence.run();
If I'm writing C code, I have no choice but callback function pointer that takes void* as parameter. But I'm now working with C++, there should be an elegant way to deal with it.
The best way I can think now is declaring a template class that virtually inherit from a abstract wrapper class :
class command_sequence {
private:
class runner {
public:
virtual void execute(void) = 0;
};
template <class FUNC, typename T> class func_pair : public runner {
private:
FUNC &func;
T param;
public:
func_pair(FUNC &f, const T &t) : func(f),param(t) { }
void execute(void) {
func(param);
}
};
std::vector<runner*> funcQueue;
public:
template <class FUNC, typename T> void add(FUNC &obj, const T &t) {
funcQueue.push_back( new func_pair<FUNC,T>(obj,t) );
}
void run(void) {
std::vector<runner*>::iterator itr=funcQueue.begin();
for(;itr!=funcQueue.end();++itr) {
(*itr)->execute();
delete (*itr);
}
}
};
This approach can fit my needs, but it would allocate and release template_pair for each entry. I've no idea whether this would cause memory fragment, since this procedure will be called quite frequently during the process.
Is there any better way to do this ?