如何在c ++中创建map <string,class :: method =“”>并能够搜索函数并调用它?</string,>

时间:2010-06-24 19:11:50

标签: c++ mapping function-pointers

我正在尝试在C ++中创建字符串和方法的映射,但我不知道该怎么做。我想做那样的事情(伪代码):

map<string, method> mapping =
{
  "sin", Math::sinFunc,
  "cos", Math::cosFunc,
  ...
};

...

string &function;
handler = mapping.find(function);
int result;

if (handler != NULL)
  result = (int) handler(20);

老实说我不知道​​C ++是否可行。我想有一个字符串,方法的地图,并能够在我的映射中搜索功能。如果给定的函数字符串名称存在,那么我想用给定的参数调用它。

7 个答案:

答案 0 :(得分:17)

好吧,我不是Boost Lovers Club中流行的成员,所以在这里 - 用原始C ++。

#include <map>
#include <string>

struct Math
{
    double sinFunc(double x) { return 0.33; };
    double cosFunc(double x) { return 0.66; };
};

typedef double (Math::*math_method_t)(double);
typedef std::map<std::string, math_method_t> math_func_map_t;

int main()
{

    math_func_map_t mapping;
    mapping["sin"] = &Math::sinFunc;
    mapping["cos"] = &Math::cosFunc;

    std::string function = std::string("sin");
    math_func_map_t::iterator x = mapping.find(function);
    int result = 0;

    if (x != mapping.end()) {
        Math m;
        result = (m.*(x->second))(20);
    }
}

很明显,如果我已经正确理解你想要一个方法指针,而不是一个函数/静态方法指针。

答案 1 :(得分:6)

由于函数指针,这确实可以在C ++中实现。这是一个简单的例子:

  std::string foo() { return "Foo"; }
  std::string bar() { return "Bar"; }

  int main()
  {
      std::map<std::string, std::string (*)()> m;

      // Map the functions to the names
      m["foo"] = &foo;
      m["bar"] = &bar;

      // Display all of the mapped functions
      std::map<std::string, std::string (*)()>::const_iterator it = m.begin();
      std::map<std::string, std::string (*)()>::const_iterator end = m.end();

      while ( it != end ) {
          std::cout<< it->first <<"\t\""
              << (it->second)() <<"\"\n";
          ++it;
      }
  }

在处理具有不同返回类型和参数的函数时,这会变得更加棘手。此外,如果要包含非静态成员函数,则应使用Boost.Function

答案 2 :(得分:1)

最简单的方法是使用boost::function

#include <map>
#include <string>
#include <boost/function.hpp>

using namespace std;

// later...

map<string, boost::function<double(double)> > funcs;
funcs["sin"] = &Math::sinFunc;

如果您使用成员函数,它会稍微复杂一点 - boost::lambda可以提供帮助:

#include <map>
#include <string>
#include <boost/function.hpp>
#include <boost/lambda/bind.hpp>

using namespace std;
namespace l = boost::lambda;

// later...

Math *m = new Math();
map<string, boost::function<double(double)> > funcs;
funcs["sin"] = l::bind(&Math::sinFunc, m, l::_1);

答案 3 :(得分:0)

你当然可以哄骗地图&lt;&gt;容器将字符串映射到函数指针。但这是一种非常难以做到的事情。

创建所有函数名称的枚举。将字符串名称映射到枚举值。然后使用switch语句根据枚举值调用函数。你会因为变灰而节省很多头发。

答案 4 :(得分:0)

this questionmethod最方便的表示法是function<signature>,其中function包含在 boost 中或{C} 0x下的<utility>中。

在您的情况下,签名就是这样。

map<string, function<double (double)> map; ...

map["sin"](1.0); 

答案 5 :(得分:0)

我认为这可行,假设您的函数返回int并且只需要一个int参数:

map<string, int(*func)(int)>

如果函数参数类型或返回值不同,我认为你不能这样做。

答案 6 :(得分:0)

//pick one
typedef float (*func_type_1)(float);
typedef boost::function<float(float)> func_type_2;

std::map<std::string,func_type> fm;
fm["sin"] = &Math::sin;
fm["cos"] = &Math::cos;

auto f = fm[str];
result = f(42);