我正在尝试进行提升::绑定调用并将传递的参数的值保存在boost::function中,我偶然发现了我无法解释的情况:
#include <boost/bind.hpp>
#include <boost/function.hpp>
#include <memory>
#include <iostream>
template <class T>
using callback = boost::function<void (int, std::shared_ptr<T>)>;
class work
{
public:
int value;
};
void job_callback(int v, std::shared_ptr<int> work)
{
*work = v;
}
int main()
{
std::shared_ptr<int> a(new int(10));
boost::bind(job_callback, _1, a)(1); // compiles and works with 1 arg, *a is 1
callback<int> call = boost::bind(job_callback, _1, a); // compiles
call(2, a); // compiles and works with 2 args, *a is 2
call(3); // does not compile with 1 arg
return 0;
}
我不明白为什么boost::bind(job_callback, _1, a)(1)
有效,即使只向生成的函子提供了一个参数 - 所以第二个参数被传递 - 但call(3)
不会编译并出现以下错误:
/usr/include/boost/function/function_template.hpp:761:17: note: boost::function2<R, T1, T2>::result_type boost::function2<R, T1, T2>::operator()(T0, T1) const [with R = void; T0 = int; T1 = std::shared_ptr<int>; boost::function2<R, T1, T2>::result_type = void]
/usr/include/boost/function/function_template.hpp:761:17: note: candidate expects 2 arguments, 1 provided
该boost::bind
调用的返回类型是否不是boost::function<void (int, shared_ptr<int>)>
而是其他东西,存储第二个参数的值?如果是这样,它是什么?
因为boost
和std
{bind,function}
会产生相同的问题。我将使用std
版本进行讨论。我认为问题出在函数对象的赋值上。
callback<int> call = boost::bind(job_callback, _1, a); // compiles
它可以编译,但不正确,因为callback<int> == function<void (int,xxx)>
.这不是正确的签名,因为两个参数之一已固定为 a
。
但这里真正令人困惑的是,为什么function
对象应该接受bind
结果,而它不是正确的arity?我认为这可能与std::bind
中引入的处理额外参数的灵活性有关。我怀疑这也发生在提升中。但我对此不是100%确定。我从来不明白为什么bind
应该容忍不正确数量的参数。
正确的用法是
function<void (int)> call = std::bind(job_callback, _1, a); //also compiles
代码使用 std::{function,bind}
#include <functional>
#include <memory>
#include <iostream>
using namespace std;
using namespace std::placeholders;
template <class T>
using callback = std::function<void (int, std::shared_ptr<T>)>;
class work
{
public:
int value;
};
void job_callback(int v, std::shared_ptr<int> work)
{
*work = v;
}
int main()
{
std::shared_ptr<int> a(new int(10));
std::bind(job_callback, _1, a)(1); // compiles and works with 1 arg, *a is 1
//callback<int> call = std::bind(job_callback, _1, a); // compiles
function<void (int)> call = std::bind(job_callback, _1, a); //also compiles
//call(2, a); // compiles and works with 2 args, *a is 2
call(3); // does not compile with 1 arg
return 0;
}