21

この基本的な質問をすることについての私の無知を許してください、しかし私はこの種のことは些細なことであるPythonを使うことにとても慣れてきたので、C++でこれをどのように試みるかを完全に忘れました。

バックグラウンドで低速のプロセスを実行する関数にコールバックを渡して、後でプロセスが完了したときにコールバックを呼び出せるようにしたい。このコールバックは、フリー関数、静的関数、またはメンバー関数である可能性があります。また、コンテキストのためにそこに任意の引数を挿入できるようにしたいと思います。(つまり、ある意味で非常に貧しい人のコルーチンを実装します。)その上、この関数は常にプロセスの出力であるstd::stringを取ります。最終的なコールバックパラメータリストでのこの引数の位置が固定されていてもかまいません。

答えにはboost::bindとboost::functionが含まれているように感じますが、任意の呼び出し可能オブジェクトを作成するために必要な正確な呼び出しを実行できません(1つの文字列を取得するようにカリー化しています)。それらをバックグラウンドプロセスに保存し、stringパラメーターを使用してcallableを正しく呼び出します。

4

3 に答える 3

18

コールバックはとして保存する必要がありますboost::function<void, std::string>。次に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 ) ); 
}
于 2010-03-18T16:28:01.117 に答える
1

オブザーバーパターンを使用したいようです。

于 2010-03-18T16:27:55.923 に答える
0

最も簡単な方法:

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;
};

次に、コールバッククラスを(ポインタ/参照によって)プロセスに渡すことができます。クラスには必要に応じて状態があり、必要に応じてコピーできます(そうでない場合は、クローンを削除します)。

于 2010-03-18T16:43:19.633 に答える