web-dev-qa-db-ja.com

boost :: functionとboost :: bindの仕組み

私はコード全体に魔法の箱が散らばっているのが嫌いです...関数<>に渡されるものとまったく異なるパラメータが設定されている場合でも、これらの2つのクラスがどのように機能して基本的にすべての関数を関数オブジェクトにマッピングできるかboost::bind

異なる呼び出し規約でも動作します(つまり、メンバーメソッドは__thiscall VCの下で、しかし「通常の」関数は一般に__cdeclまたは__stdcall Cとの互換性が必要な場合.

81
Fire Lancer

boost::functionは、正しい署名を持つoperator()を持つすべてのものをパラメーターとしてバインドすることを許可し、バインドの結果はパラメーターintを使用して呼び出すことができるため、バインドできますfunction<void(int)>に。

これがどのように機能するかです(この説明はstd::functionにも当てはまります):

boost::bind(&klass::member, instance, 0, _1)は次のようなオブジェクトを返します

struct unspecified_type
{
  ... some members ...
  return_type operator()(int i) const { return instance->*&klass::member(0, i);
}

return_typeintklass::memberの署名から推測され、関数ポインターとバインドされたパラメーターは実際にはオブジェクトに格納されますが、それは重要ではありません

これで、boost::functionは型チェックを行いません。テンプレートパラメータで指定したオブジェクトと署名を受け取り、署名に従って呼び出し可能なオブジェクトを作成し、オブジェクトを呼び出します。それが不可能な場合は、コンパイルエラーです。

boost::functionは、実際には次のようなオブジェクトです。

template <class Sig>
class function
{
  function_impl<Sig>* f;
public:
  return_type operator()(argument_type arg0) const { return (*f)(arg0); }
};

return_typeargument_typeSigから抽出され、fはヒープに動的に割り当てられます。異なるサイズの完全に無関係なオブジェクトをboost::functionにバインドできるようにするために必要です。

function_implは単なる抽象クラスです

template <class Sig>
class function_impl
{
public:
  virtual return_type operator()(argument_type arg0) const=0;
};

すべての作業を行うクラスは、boost::functionから派生した具象クラスです。 boost::functionに割り当てるオブジェクトのタイプごとに1つあります

template <class Sig, class Object>
class function_impl_concrete : public function_impl<Sig>
{
  Object o
public:
  virtual return_type operator()(argument_type arg0) const=0 { return o(arg0); }
};

それはあなたの場合、ブースト機能への割り当てを意味します:

  1. タイプfunction_impl_concrete<void(int), unspecified_type>をインスタンス化します(もちろんコンパイル時間です)
  2. ヒープ上にそのタイプの新しいオブジェクトを作成します
  3. このオブジェクトをboost :: functionのfメンバーに割り当てます

関数オブジェクトを呼び出すと、実装オブジェクトの仮想関数が呼び出され、元の関数への呼び出しが指示されます。

免責事項:この説明の名前は意図的に構成されていることに注意してください。実在の人物やキャラクターとの類似点は...知っています。目的は、原理を説明することでした。

94
jpalecek