81

以下代码导致 cl.exe 崩溃 (MS VS2005)。
我正在尝试使用 boost bind 来创建一个调用 myclass 方法的函数:

#include "stdafx.h"
#include <boost/function.hpp>
#include <boost/bind.hpp>
#include <functional>

class myclass {
public:
    void fun1()       { printf("fun1()\n");      }
    void fun2(int i)  { printf("fun2(%d)\n", i); }

    void testit() {
        boost::function<void ()>    f1( boost::bind( &myclass::fun1, this ) );
        boost::function<void (int)> f2( boost::bind( &myclass::fun2, this ) ); //fails

        f1();
        f2(111);
    }
};

int main(int argc, char* argv[]) {
    myclass mc;
    mc.testit();
    return 0;
}

我究竟做错了什么?

4

3 回答 3

110

请改用以下内容:

boost::function<void (int)> f2( boost::bind( &myclass::fun2, this, _1 ) );

这会将传递给函数对象的第一个参数转发给使用占位符的函数 - 您必须告诉Boost.Bind如何处理参数。使用您的表达式,它会尝试将其解释为不带参数的成员函数。
有关常见的使用模式,请参见此处此处

请注意,VC8s cl.exe 经常因Boost.Bind误用而崩溃- 如果有疑问,请使用带有 gcc 的测试用例,如果您通读输出,您可能会得到很好的提示,例如模板参数Bind -internals 被实例化。

于 2010-02-20T23:40:33.337 回答
1

Boost.Bind是一个库,它简化和概括了最初需要std::bind1st()std::bind2nd()的功能

示例 1.1:具有兼容函数的std::for_each()

#include <vector>
#include <algorithm>
#include <iostream>

void print(int i)
{
  std::cout << i << '\n';
}

int main()
{
  std::vector<int> v{1, 3, 2};
  std::for_each(v.begin(), v.end(), print);
}

std::for_each()的第三个参数是需要唯一参数的函数或函数对象。在示例 1.1中,std::for_each()将容器 v 中的数字作为唯一参数一个接一个地传递给 print()。

如果你需要传入一个签名不符合算法要求的函数,那就更难了。例如,如果您希望print()接受输出流作为附加参数,则不能再将其与std::for_each()一起使用。

例 1.2。std::for_each()std::bind1st()

#include <vector>
#include <algorithm>
#include <functional>
#include <iostream>

class print : public std::binary_function<std::ostream*, int, void>
{
public:
  void operator()(std::ostream *os, int i) const
  {
    *os << i << '\n';
  }
};

int main()
{
  std::vector<int> v{1, 3, 2};
  std::for_each(v.begin(), v.end(), std::bind1st(print{}, &std::cout));
}

示例 1.1一样,示例 1.2将 v 中的所有数字写入标准输出。但是,这一次,输出流作为参数传递给 print()。为此,函数print()被定义为从std::binary_function派生的函数对象。

使用Boost.Bind,您无需将print()从函数转换为函数对象。相反,您使用在boost/bind.hpp中定义的函数模板boost::bind()

例 1.3:std::for_each()boost::bind()

#include <boost/bind.hpp>
#include <vector>
#include <algorithm>
#include <iostream>

void print(std::ostream *os, int i)
{
  *os << i << '\n';
}

int main()
{
  std::vector<int> v{1, 3, 2};
  std::for_each(v.begin(), v.end(), boost::bind(print, &std::cout, _1));
}

示例 1.3使用 print() 作为函数,而不是函数对象。因为 print() 需要两个参数,所以函数不能直接传递给std::for_each()。相反,boost::bind()被传递给std::for_each()并且 print() 作为第一个参数被传递给boost::bind()

由于 print() 需要两个参数,因此这两个参数也必须传递给boost::bind()。它们是指向std::cout_1的指针。

_1是占位符。Boost.Bin d 定义了从_1_9的占位符。这些占位符告诉boost::bind()返回一个函数对象,该对象期望与具有最大数量的占位符一样多的参数。如果像例 1.3中一样,只使用占位符_1,则boost::bind( ) 返回一个一元函数对象——一个需要唯一参数的函数对象。在这种情况下这是必需的,因为std::for_each()只传递一个参数。

std::for_each()调用一元函数对象。传递给函数对象的值——来自容器v的数字——占据占位符_1的位置。boost::bind()获取数字和指向 std::cout 的指针并将它们转发给 print()。

请注意boost::bind()std::bind1st()std::bind2nd()一样,按值获取参数。为了防止调用程序尝试复制std::cout, print() 需要一个指向流的指针。Boost.Ref 提供了一个允许您通过引用传递参数的函数。

示例 1.4说明了如何使用boost::bind()定义二进制函数对象。它使用算法std::sort(),它需要一个二进制函数作为它的第三个参数。

例 1.4std::sort()boost::bind()

#include <boost/bind.hpp>
#include <vector>
#include <algorithm>
#include <iostream>

bool compare(int i, int j)
{
  return i > j;
}

int main()
{
  std::vector<int> v{1, 3, 2};
  std::sort(v.begin(), v.end(), boost::bind(compare, _1, _2));
  for (int i : v)
    std::cout << i << '\n';
}

示例 1.4中,由于使用了占位符_2,因此创建了一个二进制函数对象。算法std::sort()使用来自容器 v 的两个值调用此二进制函数对象,并计算返回值以对容器进行排序。函数 compare() 被定义为按降序对v进行排序。

由于compare()是二进制函数,因此可以直接将其传递给std::sort()但是,使用boost::bind()仍然有意义,因为它允许您更改参数的顺序。例如,如果您想按升序对容器进行排序但不想更改 compare() ,则可以使用boost::bind( )

例 1.5std::sort()boost::bind()并更改了占位符的顺序

#include <boost/bind.hpp>
#include <vector>
#include <algorithm>
#include <iostream>

bool compare(int i, int j)
{
  return i > j;
}

int main()
{
  std::vector<int> v{1, 3, 2};
  std::sort(v.begin(), v.end(), boost::bind(compare, _2, _1));
  for (int i : v)
    std::cout << i << '\n';
}
于 2021-06-30T03:46:00.507 回答
0

以下对我有用。

class test_component
{
private:
    void on_wait_complete(const int i);
};

void test_component::on_wait_complete (const int i)
{
    cout << "on_wait_complete was called" << endl;

    return;
}

int main()
{
    // timerPtr_ is a variable declared in class test_component.
    timerPtr_->async_wait(boost::bind(&test_component::on_wait_complete, this, _1));
}
于 2022-01-29T11:28:09.813 回答