pass-callback-data-as-void*-structアンチパターンにうんざりしています。ブーストバインドはそれをうまく解決しますが、許容できない依存関係です。軽量の代替品は何ですか?できるだけ簡単に自分で書くにはどうすればよいですか?
7 に答える
まず、重すぎて使えないというあなたの主張に疑問を感じます。
次に、動作を制御する必要がある場合は、独自のテンプレートをロールします。
第 3 に、独自のテンプレートを展開することを恐れている場合は、それboost::bind
が重すぎて使用できないと判断する能力に疑問があります。
Don Clugstonによるfast delegateをチェックしてください。これはおそらく、現在のほとんどのプラットフォームで見つけることができる最速のデリゲートです (2 つのアセンブリ命令にコンパイルされます)。バージョン 1.4+ は、Boost.Bind の互換性を獲得します。
boost:bind に詳しくないのですが、こういうことですか?
#include <iostream>
void foo (int const& x) {
std::cout << "x = " << x << std::endl;
}
void bar (std::string const& s) {
std::cout << "s = " << s << std::endl;
}
template<class T>
void relay (void (*f)(T const&), T const& a) {
f(a);
}
int main (int argc, char *argv[])
{
std::string msg("Hello World!");
relay (foo, 1138);
relay (bar, msg);
}
出力 --
x = 1138
s = Hello World!
一般的な C++ のイディオムは、ファンクター (つまり、operator() をオーバーライドするオブジェクト) を使用することです。ポイントは、単一のオブジェクトを使用して、コールバックされるコードとそのコードが作用するデータの両方をカプセル化することです。ファンクターが手作業で作成されたものであるか、boost::bind や <functional> を使用して生成されたものであるかは、おそらく実行時のオーバーヘッドに大きな違いをもたらすことはありません。
したがって、代わりに:
typedef void (*cb)(void*);
void funcThatNeedsCallback(cb thecallback, void *thedata) {
// blah blah
thecallback(thedata);
}
行う:
template<typename T>
void funcThatNeedsCallback(T &thefunctor) {
// blah blah
thefunctor();
}
次に、呼び出し元は次のことを行います。
struct MyFunctor {
int mydata1;
char *mydata2;
void operator()(void) {
// do something with mydata1 and mydata2
}
};
MyFunctor mf = { value1, value2 };
funcThatNeedsCallback(mf);
明らかに、必要に応じて、初期化リストを使用するのではなく、メンバーをプライベートにしてコンストラクターに渡すことができます。
テンプレートが心配な場合 (たとえば、 funcThatNeedsCallback が重複する大量のコードである場合)、抽象クラスを使用して、パラメーターに必要な仮想メソッドを定義し、そのメソッドをコールバックとして使用します。
class CallbackInterface {
virtual void theCallback(void) = 0;
virtual ~CallbackInterface() {} // just in case
};
void funcThatNeedsCallback(CallbackInterface &cb) {
// blah blah
cb.theCallback();
}
Boost.Function は、boost::bind と一緒に使用すると、約 1.34 の時点でパフォーマンスが劇的に向上しました。古いブースト バージョンでプロファイリングした場合は、より新しいバージョンでもう一度実行してください。boost::function
小さな関数オブジェクトを、ヒープではなくスタックに割り当てられた小さなバッファーに保存する機能を取得しました (placement new を使用)。
このメーリング リスト メッセージを参照してください: http://lists.boost.org/Archives/boost/2006/01/98993.php。
boost :: bindsスピードを擁護する人々は、おそらく低レイテンシのトレーディングシステムや高速グラフィックライブラリを書いたことがないでしょう。
Boostは、速度が最適化されたライブラリではなく、優れた汎用ライブラリです。一部のBoostライブラリ(調整された実装と比較して)は、比較すると非常に遅くなる可能性があります。
関数/委任については、有用な比較についてhttp://www.codeproject.com/KB/cpp/fastdelegate2.aspxを参照してください。
チャオ。
libsigc++があります。ライセンスは LGPL ですが、実装は Boost.Signal の機能に関するものです (「Boost.Signal が遅すぎる」ではなく、「Boost をすべてインストールすると重すぎる」という意味で「重すぎる」と読んでいます)。