如何解决std::function 和 std::bind:如何使用函数模板加载 std::bind
我使用一个函数模板来加载一个 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::placeholders::_2));// didn't work either
// this work well
std::function<int(int,int)> fun = std::bind(add,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::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,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::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
谁能告诉我,发生了什么?
解决方法
您遇到了模板函数参数推导规则。 std::bind
不返回 std::function
,您为 int
传递的 Args...
只是 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 函数,并且 (b) 不知道它的参数类型是什么。
这里也没有意义。
installCallback("add01",add);
在逻辑上是等价的,噪音较少。它仍然不会编译;但是在 c++17 中,这将:
installCallback("add01",std::function(add));
由于扣除指南。绑定版本不会。
作为一般规则,如果您使用的是 std 绑定,请改用 lambda。在 c++11 中,lambdas 可以机械地替换 95% 的绑定使用,而在 c++14 中它变成了 99.9%,剩下的 0.1% 是你可能不应该使用并且不知道存在的绑定功能(通常不会,直到它以令人惊讶的方式破坏您的代码;将 std bind 传递给 std bind)。
,我喜欢@yakk-adam-nevraumont 的回答。我认为它非常清楚并且恰当地解释了事情;到目前为止的最佳答案,所以我赞成它。我能做出的唯一其他贡献是,我能够使用 boost 库来对每个表达式的打印类型名称进行去错乱,得出类似的结论(推导规则不产生 std::function
)。请参阅下面从提供的示例 @JoeT 和工作片段 here 修改的代码。
您会注意到 fun1
的推导类型与 fun2
的显式类型不同。
#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::_2);
std::function<int(int,int)> fun2 = std::bind(add,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;
}
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。