1. ホーム
  2. c++

[解決済み] boost::functionとboost::bindのしくみ

2023-05-25 11:30:54

質問

私は自分のコードにマジックボックスが散らばっているのが嫌いです。この2つのクラスは、基本的にどんな関数でも関数オブジェクトにマッピングすることができ、たとえ関数が私が渡すものと全く異なるパラメータセットを持っていても、正確にどのように機能するのでしょうか。 boost::bind

さらに、異なる呼び出し規則でも動作します (例えば、メンバーメソッドが __thiscall であるのに対し、通常の関数は一般に __cdecl または __stdcall で、Cとの互換性が必要なものには

どのように解決するのですか?

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

つまり、あなたの場合、boost関数への代入です。

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

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

免責事項: この説明の中の名前は意図的に作られたものであることに注意してください。実在の人物やキャラクターに類似している場合は......おわかりですね。目的は原理を説明することでした。