2

我有一大堆看起来非常相似的函数:它们采用相同的争论类型并返回字符串。

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

在一个循环中,它们是根据结构 T 中的一个变量来使用的。目前要做到这一点,我的代码中只有一个大块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

使用 C++11,您可以使用地图相当轻松地做到这一点std::function

#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,仿函数对象,lambda 函数。您还可以使用您的函数实现的接口定义类型层次结构,例如以下在 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

模仿的一种方法Eval()是拥有一张地图。映射的键是函数的名称,值是指向相应函数的指针。

在这种情况下,您将能够通过地图operator[]名称调用所需的函数。这将以某种方式模拟该eval("f" + str(i) + "(arg))"行为,尽管它可能仍然不是您的最佳解决方案。

于 2012-07-16T17:04:01.337 回答