我试图找到一种方法来根据一个字符串参数调用函数。
对于Parametertype,枚举或 Int 也可以。也许还有更多的东西? 有没有办法这样做:
myFunction(string functionParameter, int value){
this->functionParameter(value);}
最好的方法是什么?我知道有一些类似的问题,但我没有找到一个真正适合我的问题的答案。
答案 0 :(得分:3)
只需使用地图从字符串映射到函数:
void f1()
{
std::cout << "f1!" << std::endl;
}
void f2()
{
std::cout << "f2!" << std::endl;
}
void f3()
{
std::cout << "f3!" << std::endl;
}
int main()
{
std::unordered_map<std::string,std::function<void()>> map;
map["f1"] = f1;
map["f2"] = f2;
map["f3"] = f3;
map["f1"]();
map["f2"]();
map["f3"]();
}
输出:
F1!
F2!
F3!
答案 1 :(得分:2)
C ++并没有直接支持使用该名称调用函数。您需要以某种方式创建映射。最简单的方法可能是创建一个合适的std::function<...>
类型的地图:
void f(int);
void g(int);
typedef std::function<void(int)> Function;
std:: map<std::string, Function> functions;
// ...
functions["f"] = f;
functions["g"] = g;
void call(std::string const& name, int x) {
auto it = functions.find(name);
if (it->second != functions.end()) {
it->second(x);
}
else {
// deal with unknown functions
}
}
答案 2 :(得分:0)
您可以将字符串映射到函数指针。尝试这样的事情:
#include <iostream>
#include <string>
#include <functional>
#include <map>
class X;
template<class X>
class handler_factory;
template<>
class handler_factory<X>
{
private:
using HandlerType = void (X::*)(int);
public:
handler_factory();
HandlerType get(const std::string& name) const
{
if (handlers.find(name) == handlers.end())
return nullptr;
else
return (*handlers.find(name)).second;
}
private:
std::map<std::string, HandlerType> handlers;
};
class X
{
public:
friend class handler_factory<X>;
private:
void f(int);
void h(int);
};
handler_factory<X>::handler_factory()
{
handlers["f"] = &X::f;
handlers["h"] = &X::h;
}
void X::f(int) { std::cout << "X::f();"; }
void X::h(int) { std::cout << "X::h();"; }
您的课程(在此示例中为X
)可以具有如下所示的函数dispatch_method
:
template<typename... Args>
void dispatch_method(const std::string& name, Args&&... args)
{
if (find_handler(name))
(this->*find_handler(name))(std::forward<Args>(args...));
}
find_handler
是辅助方法的地方:
private:
auto find_handler(const std::string& name)
-> decltype(handler_factory<X>().get(name))
{
return handler_factory<X>().get(name);
}
然后你可以这样称呼它:
int main()
{
X{}.dispatch_method("f", 5);
}
答案 3 :(得分:0)
您可以使用以下内容:
#include <map>
#include <functional>
#include <stdexcept>
#include <string>
template<typename T> class Caller;
template<typename Ret, typename... Args>
class Caller<std::function<Ret(Args...)>>
{
public:
typedef std::function<Ret(Args...)> FuncType;
void add(const std::string& name, FuncType f)
{
functions[name] = f;
}
Ret call(const std::string& name, Args... args)
{
auto it = functions.find(name);
if (it == functions.end()) {
// Or any other error
throw std::runtime_error("unknown " + name + "function");
}
return (it->second)(args...);
}
private:
std::map<std::string, FuncType> functions;
};
让我们测试一下:
int minus(int a) { return -a; }
int main(int argc, char** argv)
{
Caller<std::function<int (int)>> caller;
caller.add("+1", [](int a) { return a + 1; } );
caller.add("minus", minus);
caller.call("minus", -42); // calls minus(-42), returns 42
caller.call("+1", 41); // calls the lambda, returns 42
return 0;
}
答案 4 :(得分:0)
这类似于问题here。您需要创建一个类似 map<string, class::method>
的地图,然后您可以使用其签名来搜索功能并调用它。
有两种方法可供选择:
<强> 1。不使用任何第三方库(在行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);
}
}
<强> 2。使用Boost库: method
最方便的表示法是function<signature>
,其中function
包含在 boost 或<utility>
中
签名就像这样。
map<string, function<double (double)> map; ...
map["sin"](1.0);