一連の単項関数オブジェクトを順番に実行するメカニズムを設計しています。これらの関数オブジェクトは実行時に割り当てられますが、問題は、これらの関数オブジェクトのパラメーターの型が異なることです。
私がやりたいことは次のようなものです:
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();
C コードを書いている場合、void* をパラメーターとして取るコールバック関数ポインターを使用するしかありません。しかし、私は現在 C++ を使用しています。それを処理するエレガントな方法があるはずです。
私が今考えることができる最善の方法は、抽象ラッパー クラスから仮想的に継承するテンプレート クラスを宣言することです。
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);
}
}
};
このアプローチは私のニーズに合う可能性がありますが、エントリごとに template_pair を割り当てて解放します。この手順はプロセス中に頻繁に呼び出されるため、これがメモリフラグメントを引き起こすかどうかはわかりません。
これを行うより良い方法はありますか?