Простите мое незнание в задавании этого основного вопроса, но я стал настолько привыкшим к использованию Python, где этот вид вещи тривиален, который я полностью забыл, как я делал бы попытку этого в C++.
Я хочу смочь передать обратный вызов функции, которая выполняет медленный процесс в фоновом режиме, и имейте его, звонил позже, когда процесс завершен. Этот обратный вызов мог быть бесплатной функцией, статической функцией или функцией членства. Я также хотел бы смочь ввести некоторые произвольные аргументы там в пользу контекста. (т.е. Реализация сопрограммы очень бедного человека, в некотором роде.) Вдобавок ко всему, эта функция будет всегда брать станд.:: строка, которая является выводом процесса. Я не возражаю, если положение этого аргумента в заключительном списке параметров обратного вызова фиксируется.
Я получаю чувство, что ответ включит повышение:: свяжите и повысьте:: функционируйте, но я не могу разработать точные вызовы, которые были бы необходимы для создания произвольного callables (при приправлении их карри, чтобы просто взять единственную строку) сохраните их, в фоновом режиме обрабатывают и вызывают вызываемое правильно со строковым параметром.
Обратный вызов должен храниться как boost :: function
. Затем вы можете использовать boost :: bind
для «преобразования» любой другой сигнатуры функции в такой объект путем привязки других параметров.
Я не пытался скомпилировать это, но он все равно должен показать общую идею
void DoLongOperation(boost::function<void, const std::string&> callback)
{
std::string result = DoSomeLengthyStuff();
callback(result);
}
void CompleteRoutine1(const std::string&);
void CompleteRoutine2(int param, const std::string&);
// Calling examples
DoLongOperation(&CompleteRoutine1); // Matches directly
DoLongOperation(boost::bind(&CompleteRoutine2, 7, _1)); // int parameter is bound to constant.
// This one is thanks to David Rodríguez comment below, but reformatted here:
struct S
{
void f( std::string const & );
};
int main()
{
S s;
DoLongOperation( boost::bind( &S::f, &s, _1 ) );
}
Самый простой способ:
class Callback
{
public:
virtual ~Callback() {}
virtual Callback* clone() const = 0;
// Better to wrap the call (logging, try/catch, etc)
void execute(const std::string& result) { this->executeImpl(result); }
protected:
// Don't make sense to have them public
Callback() {}
Callback(const Callback&) {}
Callback& operator=(const Callback&) { return *this; }
private:
virtual void executeImpl(const std::string& result) = 0;
};
// Example
class Example: public Callback
{
public:
Example(int a, int b): Callback(), mA(a), mB(b) {}
virtual Example* clone() const { return new Example(*this); }
private:
virtual void executeImpl(const std::string& result) {}
int mA;
int mB;
};
И затем вы можете передать класс обратного вызова (по указателю / ссылке) процессу. У класса есть состояние, которое требуется, и при необходимости его можно скопировать (если нет, отбросьте клон).