[英]std::function and std::bind: how to load a std::bind with a function template
我使用 function 模板来加载 std::bind obj,我的代码:
#include <iostream>
#include <functional>
template<typename RT_, typename ...Args>
void installCallback(const char name[], const std::function<RT_(Args...)> &func)
{
}
int add(int a, int b)
{
return a + b;
}
int main(int argc, char *argv[])
{
installCallback("add01", std::bind(add, std::placeholders::_1, std::placeholders::_2));
installCallback<int, int, int>("add01", std::bind(add, std::placeholders::_1, std::placeholders::_2));// didn't work either
// this work well
std::function<int(int, int)> fun = std::bind(add, std::placeholders::_1, std::placeholders::_2);
installCallback("add02", fun);
return 0;
}
,我得到了这个错误:
/home/tong/Documents/awesome_auto_drive/awe_auto/sample/module/main.cpp:20:90: error: no matching function for call to 'installCallback(const char [6], std::_Bind_helper<false, int (&)(int, int), const std::_Placeholder<1>&, const std::_Placeholder<2>&>::type)' 20 | installCallback("add01", std::bind(add, std::placeholders::_1, std::placeholders::_2)); | ^ $./main.cpp:6:6: note: candidate: 'template<class RT_, class... Args> void installCallback(const char*, std::function<_Res(_ArgTypes...)>&&)' 6 | void installCallback(const char name[], std::function<RT_(Args...)> &&func) | ^~~~~~~~~~~~~~~ $./main.cpp:6:6: note: template argument deduction/substitution failed: $./main.cpp:20:90: note: 'std::_Bind_helper<false, int (&)(int, int), const std::_Placeholder<1>&, const std::_Placeholder<2>&>::type' {aka 'std::_Bind<int (*(std::_Placeholder<1>, std::_Placeholder<2>))(int, int)>'} is not derived from 'std::function<_Res(_ArgTypes...)>' 20 | installCallback("add01", std::bind(add, std::placeholders::_1, std::placeholders::_2)); | ^ sample/module/CMakeFiles/module.dir/build.make:62: recipe for target 'sample/module/CMakeFiles/module.dir/main.cpp.o' failed make[2]: *** [sample/module/CMakeFiles/module.dir/main.cpp.o] Error 1 CMakeFiles/Makefile2:2665: recipe for target 'sample/module/CMakeFiles/module.dir/all' failed make[1]: *** [sample/module/CMakeFiles/module.dir/all] Error 2 Makefile:129: recipe for target 'all' failed make: *** [all] Error 2
谁能告诉我,发生了什么?
您遇到了模板 function 参数推导规则。 std::bind
不返回std::function
,并且您为Args...
传递的int
只是Args...
... 的前缀。 所以 C++ 试图推断出Args...
并因该错误而失败。
快速修复是
template<class Sig>
void installCallback(const char name[], const std::function<Sig> &func)
然后
installCallback<int(int, int)>
这使得installCallback
的主体失去了Args...
现在,
installCallback("add01", std::bind(add, std::placeholders::_1, std::placeholders::_2));
无法工作,因为bind
(a) 不是 std function,并且 (b) 不知道它的参数类型是什么。
在这里也毫无意义。
installCallback("add01", add);
在逻辑上是等价的,并且较少充满噪音。 它仍然无法编译; 但是在c++17这将:
installCallback("add01", std::function(add));
由于扣除指南。 绑定版本不会。
作为一般规则,如果您使用标准绑定,请改用 lambda。 在c++11 中,lambda 可以机械地替换 95% 的绑定使用,在c++14中,它变为 99.9%,剩下的 0.1% 是绑定的特性,你可能不应该使用并且不知道存在(通常直到它存在)以令人惊讶的方式破坏您的代码;将 std 绑定传递给 std 绑定)。
我喜欢@yakk-adam-nevraumont 的回答。 我认为它非常清楚并且恰当地解释了事情; 到目前为止最好的答案,所以我赞成它。 我唯一能做出的其他贡献是,我能够得出一个类似的结论(推导规则不会产生std::function
)使用 boost 库来消除每个表达式的打印类型名称。 请参阅下面从提供的示例@JoeT 修改的代码和此处的工作片段。
您会注意到fun2
的推导类型与fun1
的显式类型不同。
#include <functional>
#include <iostream>
#include <typeinfo>
#include <boost/core/demangle.hpp>
template<typename RT_, typename ...Args>
void installCallback(const char name[], const std::function<RT_(Args...)> &func)
{
}
int add(int a, int b)
{
return a + b;
}
int main(int argc, char *argv[])
{
auto fun1 = std::bind(add, std::placeholders::_1, std::placeholders::_2);
std::function<int(int, int)> fun2 = std::bind(add, std::placeholders::_1, std::placeholders::_2);
char const* name = typeid( fun1 ).name();
// Outputs: std::_Bind<int (*(std::_Placeholder<1>, std::_Placeholder<2>))(int, int)>
std::cout << boost::core::demangle(typeid(fun1).name()) << std::endl;
// Outputs: std::function<int (int, int)>
std::cout << boost::core::demangle(typeid(fun2).name()) << std::endl;
return 0;
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.