Я пытаюсь создать карту строки и метод в 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++. Я хотел бы иметь карту строки, метод и смочь искать функцию в моем отображении. Если бы данный имя строки функции существует затем, я хотел бы назвать его с данным параметрическим усилителем.
Ну, я не член популярного здесь клуба любителей 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);
}
}
Это очевидно, если я правильно понял, что вам нужен указатель на метод, а не на функцию/статический указатель на метод.
Самый простой способ - использовать 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);
Это действительно возможно в 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
.
Думаю, это будет работать, если предположить, что ваша функция возвращает int
и принимает единственный int
параметр:
map<string, int(*func)(int)>
Если типы параметров функции или возвращаемые значения отличаются, не думаю, что вы сможете это сделать.
Конечно, вы можете уговорить контейнер map <> отображать строки в указатели на функции. Но это действительно сложный способ сделать что-то довольно простое.
Создайте список всех имён функций. Сопоставьте имена строк со значениями перечисления. Затем используйте оператор switch для вызова функций на основе значения перечисления. Вы убережете много волос от седины.
См. этот вопрос . Наиболее удобное обозначение для метода
- function
, где функция
либо включена в boost , либо в
под C ++ 0x.
В вашем случае подпись будет такой.
map<string, function<double (double)> map; ...
map["sin"](1.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);