Как создать карту <строка, класс:: метод> в C++ и смочь искать функцию и назвать его?

Я пытаюсь создать карту строки и метод в 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++. Я хотел бы иметь карту строки, метод и смочь искать функцию в моем отображении. Если бы данный имя строки функции существует затем, я хотел бы назвать его с данным параметрическим усилителем.

15
задан user360872 24 June 2010 в 19:11
поделиться

7 ответов

Ну, я не член популярного здесь клуба любителей Boost, так что вот оно - в сыром 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);
    }
}

Это очевидно, если я правильно понял, что вам нужен указатель на метод, а не на функцию/статический указатель на метод.

19
ответ дан 1 December 2019 в 02:28
поделиться

Самый простой способ - использовать 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);
2
ответ дан 1 December 2019 в 02:28
поделиться

Это действительно возможно в 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.

6
ответ дан 1 December 2019 в 02:28
поделиться

Думаю, это будет работать, если предположить, что ваша функция возвращает int и принимает единственный int параметр:

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

Если типы параметров функции или возвращаемые значения отличаются, не думаю, что вы сможете это сделать.

0
ответ дан 1 December 2019 в 02:28
поделиться

Конечно, вы можете уговорить контейнер map <> отображать строки в указатели на функции. Но это действительно сложный способ сделать что-то довольно простое.

Создайте список всех имён функций. Сопоставьте имена строк со значениями перечисления. Затем используйте оператор switch для вызова функций на основе значения перечисления. Вы убережете много волос от седины.

0
ответ дан 1 December 2019 в 02:28
поделиться

См. этот вопрос . Наиболее удобное обозначение для метода - function , где функция либо включена в boost , либо в под C ++ 0x.

В вашем случае подпись будет такой.

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

map["sin"](1.0); 
1
ответ дан 1 December 2019 в 02:28
поделиться
//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);
0
ответ дан 1 December 2019 в 02:28
поделиться
Другие вопросы по тегам:

Похожие вопросы: