boost :: bind在存储时不保存部分参数

时间:2014-02-13 15:32:52

标签: c++ templates boost boost-bind

我正在尝试进行boost :: bind调用并在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>)>而是其他东西,是存储第二个参数值的东西吗?如果是这样,它是什么?

1 个答案:

答案 0 :(得分:2)

由于booststd {bind,function}会产生同样的问题。我将使用std版本进行讨论。我认为问题在于对函数对象的赋值。

callback<int> call = boost::bind(job_callback, _1, a); // compiles

它编译但不正确,因为callback<int> == function<void (int,xxx)>。这不是正确的签名,因为其中一个参数已修复为a

但是这里真正令人困惑的可能是function对象在不是正确的arity时应该接受bind结果的原因?我认为这可能与std::bind中引入额外参数的灵活性有关。我怀疑这也发生在提升中。但我对此并不是百分百肯定。我永远不明白为什么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;
}