2

私はすべて非常によく似た一連の関数を持っています。それらは同じ引数タイプを取り、文字列を返します。

std::string f1(T arg);
std::string f2(T arg);
std::string f3(T arg);
std::string f4(T arg);
.
.
.

ループでは、構造体T内の変数の1つに従って使用されます。現在、これを行うためswitch/caseに、コードに大きなブロックがあります。

これを行うためのより良いコーディングスタイルはありますか?コードの大きなブロックは非常に奇妙に見えます。

私はc++がPythonのようになりたいと思いますeval("f" + str(i) + "(arg))"

ブロックは次のようなものです。

std::string out = "";

switch (arg.tag){
    case 1:
        out += f1(arg);
        break;
    case 2:
        out += f2(arg);
        break;
    .
    .
    .
}

約2ダースの場合

4

2 に答える 2

4

std::functionC ++ 11を使用すると、マップを使用してこれをかなり簡単に行うことができます。

#include <map>
#include <functional>
#include <string>
#include <iostream>

std::string f1(int) { return "f1"; }
std::string f2(int) { return "f2"; }

std::map<int, std::function<std::string(int)> > funcs = {
  {1,f1},
  {2,f2}
};

int main() {
  std::cout << funcs[1](100) << "\n";    
}

C ++ 11がない場合は、代わりにBoostを使用するか、代わりにstd::function独自のタイプをロールする必要があります。昔ながらの関数ポインタを使用することもできますが、便利なもの(std::bind/ boost::bind、ファンクターオブジェクト、ラムダ関数など)が除外されます。関数が実装するインターフェイスを使用して型階層を定義することもできます。たとえば、C++03では次のように機能します。マップが初期化される方法について:

#include <map>
#include <functional>
#include <string>
#include <iostream>

std::string f1(int) { return "f1"; }
std::string f2(int) { return "f2"; }

std::map<int, std::string(*)(int)> funcs = {
  std::make_pair(1,f1),
  std::make_pair(2,f2)
};

int main() {
  std::cout << funcs[1](100) << "\n";    
}

または、これにより、好きな種類のファンクターオブジェクトを作成できます。

#include <map>
#include <string>
#include <iostream>

struct thing {
  virtual std::string operator()(int) const = 0;
};

struct f1 : thing {
  std::string operator()(int) const { return "f1"; }
};

struct f2 : thing {
  std::string operator()(int) const { return "f2"; }
};

// Note the leak - these never get deleted:
std::map<int, thing*> funcs = {
  std::make_pair(1,new f1),
  std::make_pair(2,new f2)
};

int main() {
  std::cout << (*funcs[1])(100) << "\n";
}
于 2012-07-16T17:04:22.950 に答える
1

をエミュレートする1​​つの方法Eval()は、マップを作成することです。マップのキーは関数の名前になり、値は対応する関数へのポインターになります。

この場合、マップで必要な関数を名前で呼び出すことができますoperator[]。これはどういうわけか動作をエミュレートしeval("f" + str(i) + "(arg))"ますが、それでもあなたにとって最良の解決策ではないかもしれません。

于 2012-07-16T17:04:01.337 に答える