函数绑定的目的

时间:2014-12-05 11:31:38

标签: c++ boost bind

我正在学习c ++ Boost库的asio编程。我遇到过许多使用函数bind()的例子,它将函数指针作为参数。

我无法理解bind()函数的用法。这就是为什么我难以理解使用增强库asio的程序。

我不是在寻求任何代码。我只想知道bind()函数或其任何等效函数的使用。 提前谢谢。

3 个答案:

答案 0 :(得分:5)

来自cppreference

  

函数模板绑定为f生成转发调用包装器。   调用这个包装器相当于用它的一些调用f   与args绑定的参数。

检查example below演示绑定

#include <iostream>
#include <functional>

 using namespace std;

int my_f(int a, int b)
{
    return 2 * a + b;
}

int main()
{
    using namespace std::placeholders;  // for _1, _2, _3...

     // Invert the order of arguments
     auto my_f_inv = bind(my_f, _2, _1);        // 2 args b and a
    // Fix first argument as 10
    auto my_f_1_10 = bind(my_f, 10, _1);        // 1 arg b
    // Fix second argument as 10
    auto my_f_2_10 = bind(my_f, _1, 10);        // 1 arg a
    // Fix both arguments as 10
    auto my_f_both_10 = bind(my_f, 10, 10);     // no args

    cout << my_f(5, 15) << endl; // expect 25
    cout << my_f_inv(5, 15) << endl; // expect 35
    cout << my_f_1_10(5) << endl; // expect 25
    cout << my_f_2_10(5) << endl; // expect 20
    cout << my_f_both_10() << endl; // expect 30

    return 0;
}

您可以使用bind来操作现有函数的参数顺序或修复一些参数。这在stl容器和算法中特别有用,您可以在其中传递其签名与您的需求匹配的现有库函数。

例如,如果您想将容器中的所有双打转换为2,那么您可以执行以下操作:

std::transform(begin(dbl_vec),
               end(dbl_vec),
               begin(dbl_vec),
               std::bind(std::pow, _1, 2));

Live example here

答案 1 :(得分:2)

您发布到boost::asio服务的任务必须可以使用零参数调用,以便服务可以存储它们并在它具有备用资源(即空闲线程)后调用它们。假设您希望它调用函数void purr(int kitty),以便以可以使用的格式将此服务提供给您需要绑定 kitty参数到{ {1}}功能。这将为您提供一个可以调用的对象,purr没有您可以提供给服务的参数。

当然,使用C ++ 11和lambda函数,现在最好的方法是执行()并避免完全使用io_service.post([&](){ purr(3); });

答案 2 :(得分:2)

它允许您将您自己的数据与您希望库调用的函数相关联(或者#34; bind&#34;),而不需要库知道您的数据。

由于您正在查看Boost.Asio,请查看他们的tutorial for binding arguments to a handler。他们有一个他们想要用作处理程序的函数,它需要指向自己的数据,计时器本身和一个计数器:

void print(const boost::system::error_code& /*e*/,
    boost::asio::deadline_timer* t, int* count)
{
    // ...
}

计时器的async_wait功能会在计时器到期时调用用户提供的功能;但只提供这些参数中的第一个。处理程序的格式为

void handler(
    const boost::system::error_code& error // Result of operation.
);

因此我们可以使用bind将我们的函数(想要三个参数)转换为只想要一个参数的函数,方法是指定要作为另外两个传递的值:

t.async_wait(boost::bind(print,
    boost::asio::placeholders::error, &t, &count));

bind的结果是一个函数对象(即,类函数的一个对象,它重载了函数调用操作符operator()),在这种情况下只需要一个参数。 placeholders::error参数表示第一个参数仍然是新函数类型的参数;调用新函数时,另外两个参数被赋予&t&count的值。所以,如果我们自己打电话:

auto f = boost::bind(print, boost::asio::placeholders::error, &t, &count)
f(some_error);

这与使用这些参数调用原始函数具有相同的效果:

print(some_error, &t, &count);

现在,当计时器到期时,我们的函数被调用,带有我们提供的参数,而Asio库不需要了解它们。