调用函数取决于字符串参数

时间:2013-12-27 16:29:19

标签: c++ parameter-passing

我试图找到一种方法来根据一个字符串参数调用函数

对于Parametertype,

枚举 Int 也可以。也许还有更多的东西? 有没有办法这样做:

myFunction(string functionParameter, int value){
this->functionParameter(value);}

最好的方法是什么?我知道有一些类似的问题,但我没有找到一个真正适合我的问题的答案。

5 个答案:

答案 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);