boost :: functionとboost :: bindのしくみ


83

コード全体にマジックボックスが散在しているのは嫌いです... function <>のパラメータが完全に異なるパラメータが渡された場合でも、基本的にすべての関数を関数オブジェクトにマップできるようにするには、これら2つのクラスがどのように機能するのでしょうか。 boost::bind

さまざまな呼び出し規約でも機能します(つまり、メンバーメソッドは__thiscallVCの下にありますが、「通常の」関数は通常、__cdeclまたは__stdcallCとの互換性が必要な関数用です。



1
本当に-この質問はバインドと機能についてです
1800 INFORMATION

はい、したがって、バインド(&MyClass :: DoSomething、instance、 "Hello World "、_1)
Fire Lancer

2
20,000回の聖牛訪問これはブーストフロントページにある必要があります!
unixman83 2011

回答:


96

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_typeintはの署名から推測され、klass::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_typeとは、argument_typeから抽出されSig、そしてf動的ヒープ上に割り当てられています。これは、サイズの異なる完全に無関係なオブジェクトをにバインドできるようにするために必要ですboost::function

function_impl 単なる抽象クラスです

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

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

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メンバーに割り当てます

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

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


struct unspecified_typeの内容(つまり、operator()関数のコード)は、基本的に過去の引数から生成され、ケースバイケースでブースト::バインドして、任意の組み合わせと数の引数を許可しますか?
火災ランサー

1
いいえ、すべてのアリティを処理するoperator()のテンプレートがあります(そして異なるテンプレート引数が組み合わせを処理します)
jpalecek 2009

最後のコードブロックでは、次のようになっています。 arg0) const=0 { return...。...これまで見たことがありません。フォーラムで、純粋仮想関数に本体を含めることができることを説明するC ++のFAQにリンクされたフォローアップメッセージが機能しない例を見つけましたが、そのような構文(clang&gcc)を使用してコンパイルするコードを取得できません。
ブライアンヴァンデンバーグ

私の質問を少し明確にする必要があります:純粋な仮想は=0;、後で与えられる本体で宣言されたときに本体を与えることができます(例えばvoid Base::Blah() { /* ... */ })...私は上記で使用されている表記法について具体的に尋ねています。単なるタイプミスだと思います。
ブライアンヴァンデンバーグ

@BrianVandenberg:まったく無意味ですが、標準準拠だと思います。
Mooing Duck
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.