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