一般的に、ブースト バインドはバックグラウンドでどのように機能しますか?
-
02-07-2019 - |
質問
ブースト ソース コードのレビューに長い時間を費やすことなく、誰かがブースト バインドがどのように実装されているかについて簡単に説明してもらえませんか?
解決
私はこの作品が好きです bind
ソース:
template<class R, class F, class L> class bind_t
{
public:
typedef bind_t this_type;
bind_t(F f, L const & l): f_(f), l_(l) {}
#define BOOST_BIND_RETURN return
#include <boost/bind/bind_template.hpp>
#undef BOOST_BIND_RETURN
};
本当に、知っておくべきことをほぼすべて教えてくれます。
の bind_template
ヘッダーはインラインのリストに展開されます operator()
定義。たとえば、最も単純なものは次のとおりです。
result_type operator()()
{
list0 a;
BOOST_BIND_RETURN l_(type<result_type>(), f_, a, 0);
}
私たちが見ることができるのは、 BOOST_BIND_RETURN
マクロは次のように展開されます return
この時点では、ラインは次のようになります return l_(type...)
.
1 パラメーターのバージョンは次のとおりです。
template<class A1> result_type operator()(A1 & a1)
{
list1<A1 &> a(a1);
BOOST_BIND_RETURN l_(type<result_type>(), f_, a, 0);
}
かなり似ていますね。
の listN
クラスはパラメータ リストのラッパーです。ここではたくさんの奥深い魔法が起こっていますが、私はあまり理解していません。彼らはまた過負荷になっています operator()
それは神秘を呼ぶ unwrap
関数。いくつかのコンパイラ固有のオーバーロードを無視すると、あまり多くのことは行われません。
// unwrap
template<class F> inline F & unwrap(F * f, long)
{
return *f;
}
template<class F> inline F & unwrap(reference_wrapper<F> * f, int)
{
return f->get();
}
template<class F> inline F & unwrap(reference_wrapper<F> const * f, int)
{
return f->get();
}
命名規則は次のようです。 F
関数パラメータの型です。 bind
. R
戻り値の型です。 L
パラメータのタイプのリストになる傾向があります。また、さまざまな数のパラメーターに対して 9 つ以上のオーバーロードがあるため、多くの複雑さが発生します。あまりそこにこだわらないのが一番です。
他のヒント
ちなみに、もし、 bind_t
を含めることで折りたたまれて簡略化されます boost/bind/bind_template.hpp
とすると、以下のようにわかりやすくなります。
template<class R, class F, class L>
class bind_t
{
public:
typedef bind_t this_type;
bind_t(F f, L const & l): f_(f), l_(l) {}
typedef typename result_traits<R, F>::type result_type;
...
template<class A1>
result_type operator()(A1 & a1)
{
list1<A1 &> a(a1);
return l_(type<result_type>(), f_, a, 0);
}
private:
F f_;
L l_;
};
バインドしたい引数のメンバ変数を宣言し、残りの引数をオーバーロード()するテンプレートクラスだと思います。