Как последовательно выполнять объекты унарных функций с разными типами параметров?

Я разрабатываю механизм, который будет последовательно выполнять набор унарных функциональных объектов. Эти функциональные объекты назначаются во время выполнения, и проблема заключается в следующем: типы параметров этих функциональных объектов различны.

Я хочу сделать что-то вроде этого:

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, у меня нет choice, но указатель на функцию обратного вызова, который принимает в качестве параметра 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 для каждой записи. Я понятия не имею, приведет ли это к фрагментации памяти, поскольку эта процедура будет вызываться довольно часто во время процесса.

Есть ли лучший способ сделать это?

5
задан RichardLiu 8 July 2011 в 15:33
поделиться