3

ファンクターを使用してベクター テーブルのタイプを作成するという興味深いアイデアがありました。しかし、さらに分析すると、ファンクターを呼び出す関数から関数パラメーターの一部を渡すためにテーブル全体を生成する必要があるため、非常にコストがかかるため、これは夢物語であると思われます。この場合のファンクターは、ファンクターが呼び出している関数間のパラメーターの違いを管理するプロキシとして機能します。

まだ混乱していますか?:-) 例:

#include <functional>

class classA {};
void fn1(int a);
void fn2(classA& a);

void fn_x(int fn_to_call, int a1, classA& a2) {
  std::function<void()> vtable[] = {
    [&]{ fn1(a1); },
    [&]{ fn2(a2); }
  };
  vtable[fn_to_call]();
}

void fn_y(int fn_to_call, int a1, classA& a2) {
  switch(fn_to_call) {
    case 0:
      return fn1(a1);
    case 1:
      return fn2(a2);
  }
}

簡潔にするために、電話でこれを行っているため、チェックをスキップしました。

私が理解しているように、fn_x は関数に入るとファンクターの配列を作成し、必要なファンクターを呼び出す必要があります。fn_y は必要なものにジャンプするだけです。

ディスパッチする関数の数が少ない場合、これはあまり問題になりませんが、数が増えるにつれて、これはますます悪化します。

ファンクターオブジェクトが呼び出されるまで、何らかの形でその作成を遅らせることができれば、それが最適です。それは可能ですか?

また、編集、コンパイラはこれをどのように処理しますか? 複数の呼び出しスタック エントリ (ファンクターへの呼び出しとターゲット関数への呼び出し) が発生するのでしょうか、それともスイッチと同じくらい効率的でしょうか?

4

1 に答える 1

2

コメントの推奨事項のいくつかを取り上げて要約するには、引数を転送する方法を知っているファンクターのセットを 1 つだけ作成してみませんか?

#include <functional>

class classA {};
void fn1(int a) {}
void fn2(classA& a) {}

void fn_x(int fn_to_call, int a1, classA& a2) {
  using namespace std::placeholders;
  static std::function<void(int, classA&)> vtable[] = {
    std::bind(&fn1, _1),
    std::bind(&fn2, _2),
  };
  vtable[fn_to_call](a1, a2);
}

int main()
{
  classA a;
  fn_x(0, 3, a);
  fn_x(1, 3, a);
  return 0;
}
于 2013-10-09T15:43:06.760 に答える