以下代码导致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;
}
我做错了什么?
答案 0 :(得分:98)
请改用以下内容:
boost::function<void (int)> f2( boost::bind( &myclass::fun2, this, _1 ) );
这会使用占位符将传递给函数对象的第一个参数转发给函数 - 您必须告诉 Boost.Bind 如何处理参数。使用你的表达式,它会尝试将其解释为不带参数的成员函数 参见例如常见使用模式here或here。
请注意,VC8s cl.exe会在 Boost.Bind 上经常崩溃 - 如果有疑问,请使用带有gcc的测试用例,你可能会得到很好的提示,例如模板参数 Bind < / em> -internals如果你通读输出就被实例化了。
答案 1 :(得分:0)
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() 一起使用。< /p>
例 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(),它在 boost/bind.hpp 中定义。
示例 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.Bind 定义了从 _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.4。 std::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.5。 std::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';
}