Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/130.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 在一个函数容器中存储和调用不同参数的函数_C++ - Fatal编程技术网

C++ 在一个函数容器中存储和调用不同参数的函数

C++ 在一个函数容器中存储和调用不同参数的函数,c++,C++,下面是我想要实现的示例设计代码。基本上,我想为不同的HandlerName存储处理函数,这些处理函数可以是可变参数 当使用Script::Handle(…)传递具有所需参数的事件时,应调用处理程序函数 我怎样才能做到这一点?可能是可变模板吗 class Script { public: Script() { /* ... */ } template<typename TFunction> void AddHandler(const char *handler

下面是我想要实现的示例设计代码。基本上,我想为不同的HandlerName存储处理函数,这些处理函数可以是可变参数

当使用Script::Handle(…)传递具有所需参数的事件时,应调用处理程序函数

我怎样才能做到这一点?可能是可变模板吗

class Script
{
public:
    Script() { /* ... */ }

    template<typename TFunction>
    void AddHandler(const char *handlerName, TFunction &&function)
    {
        _handlerMap[handlerName] = std::move(function);
    }

    void Handle(const char *handlerName, ...)
    {
        _handlerMap[handlerName](...);
    }

private:
    typedef std::map<std::string, std::function<void()>> HandlerMapType;
    HandlerMapType _handlerMap;
};

//Handler functions
handlerOne() { std::cerr << "One"; }
handlerTwo(std::string a1, int a2) { std::cerr << "Two"; }
handlerThree(bool a1) { std::cerr << "Three"; }

int main(int argc, char **argv)
{
    Script script;
    script.AddHandler("One", std::bind(&handlerOne));
    script.AddHandler("Two", std::bind(&handlerTwo));
    script.AddHandler("Three", std::bind(&handlerThree));

    script.Handle("One");
    script.Handle("Two, "string", 96);
    script.Handle("Three", true);

    script.Handle("Three", "what should happen here?"); //String passed instead of bool
}
类脚本
{
公众:
脚本(){/*…*/}
模板
void AddHandler(const char*handlerName、TFunction&&function)
{
_handlerMap[handlerName]=std::move(函数);
}
无效句柄(常量字符*handlerName,…)
{
_handlerMap[handlerName](…);
}
私人:
typedef std::MapHandlerMapType;
HandlerMapType_handlerMap;
};
//处理函数

handlerOne(){ STR::CURR

让我先说,C++中不需要做小事。我会说,你应该考虑这是否是你的用例中需要的东西。在你的例子中,你需要的是不能真正使用的泛型主义。你无论如何都需要知道你所调用的函数的签名。把它们放在一个容器里有什么用呢

通常,如果您正在编写中间层代码,您会这样做。在您的示例中,这相当于编写允许其他用户调用句柄的代码。一个常见的具体示例是编写一个工厂,其中工厂中的对象可以使用不同的参数进行实例化。但是,这并不是真的“不同”的参数,至少不是没有一些疯狂的转换。解决方案是使所有函数采用相同的参数,但使参数成为一种动态类型,可以存储您想要的任何参数:

using argument_type = std::unordered_map<std::string, boost::any>;

void print(const argument_type & arg) {
  auto to_print = boost::any_cast<std::string>(arg["to_print"]);
  std::cerr << to_print << std::endl;
}

void print_none(const argument_type & arg) {
      std::cerr << "none" << std::endl;
}

using my_func_t = std::function<void(const argument_type &)>;

std::vector<my_func_t> v;
v.emplace_back(print);
v.emplace_back(print_none);

// create some argument_types, feed them to f.
使用参数\u type=std::无序\u映射;
无效打印(常量参数类型和参数){
auto to_print=boost::any_cast(arg[“to_print”]);

std::cerr类型擦除。有多种方法可以实现;选择你的毒药。这是一个很好的开始来阅读它投票。我以前遇到过这个问题,我使用可变模板和boost::任何类似于你的解决方案。嗯,我的第一个解决方案根本不使用可变。那么你使用第二个解决方案了吗?就个人而言,我可能不会ant使用这样的代码,感觉非常脆弱,但如果你有,我很想听听你的经验。是的,我使用第二种解决方案。我个人可能不想使用这样的代码,我非常同意你的看法。我使用第二种解决方案来创建抽象工厂模式,可以注册不同的签名函数来创建产品。@Nirfiedman I看到了一个创建延迟调用函数的方法,它在std::function中存储了一个任意参数函数。std::forward/std::bind组合能够生成更好的代码吗?下面是我看到的
void print(std::string to_print) {
  std::cerr << to_print << std::endl;
}

void print_none() {
      std::cerr << "none" << std::endl;
}


std::vector<boost::any> v;
v.emplace_back(std::function<void(std::string)>(print));
v.emplace_back(std::function<void(void)>(print_none));

template <typename ... Args>
void call(const std::vector & funcs, int index, Args... args) {
  auto f = boost::any_cast<std::function<void(Args...)>>(funcs[index]);
  f(std::forward<Args>(args)...);
}

// unsure if this will actually work
call(f, 0, std::string("hello"));