繁体   English   中英

std::function 和 std::bind:如何使用 function 模板加载 std::bind

[英]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);

在逻辑上是等价的,并且较少充满噪音。 它仍然无法编译; 但是在这将:

installCallback("add01", std::function(add));

由于扣除指南。 绑定版本不会。

作为一般规则,如果您使用标准绑定,请改用 lambda。 ,lambda 可以机械地替换 95% 的绑定使用,在中,它变为 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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM