函数对象是指那些可以被传入到其它函数或是从其它函数返回的一类函数。
1. boost::bind
bind提供了一个机制,是函数与几乎不限数量的参数一起使用,就可以得到指定签名的函数。bind会复制传递给它的参数。
#include <boost/bind.hpp> #include <iostream> #include <vector> #include <algorithm> void add(int i, int j) { std::cout << i + j << std::endl; } int main() { std::vector<int> v; v.push_back(1); v.push_back(2); v.push_back(3); std::for_each(v.begin(), v.end(), boost::bind(add, 10, _1)); return 0; }
add()函数要求两个参数,两个参数都必须传递给boost::bind()。第一个参数是10,第二个则是一个占位符,还有其他的占位符_2, _3。
使用这些占位符,boost::bind()可以变为一元、二元或三元的函数。对于_1,boost::bind()变成了一个一元函数,只需要一个参数的函数,而std::for_each()要求一个一元函数作为其第三个参数。程序执行,v中元素的值通过占位符_1传入到医院函数中,并进一步和常数一起传递到add()函数。通过这种机制,std::for_each()只看到了由boost::bind()定义的一元函数,而boost::bind()本身则是调用了另一个函数。
2. boost::ref
由于bind是复制传递给它的参数,如果参数为引用,则需要使用boost::ref(),boost::cref()
#include <boost/bind.hpp> #include <iostream> #include <vector> #include <algorithm> void add(int i, int j, std::ostream& os) { os << i + j << std::endl; } int main() { std::vector<int> v; v.push_back(1); v.push_back(2); v.push_back(3); std::for_each(v.begin(), v.end(), boost::bind(add, 10, _1, boost::ref(std::cout))); }
3. boost::function
用来封装函数指针,
#include <boost/function.hpp> #include <iostream> #include <cstdlib> #include <cstring> int main() { boost::function<int (const char*)> f = std::atoi; std::cout << f("1609") << std::endl; //调用atoi() f = std::strlen; std::cout << f("1609") << std::endl; //调用strlen() return 0; }
boost::function可以定义一个指针,指向具有特定签名的函数。如上,定义了一个指针f,可以指向某个接受一个类型为const char*的参数且返回一个类型为int的值的函数。定义完成后,匹配此签名的函数均可赋值给这个指针呢。
若f未赋予一个函数而被调用,则会抛出一个boost::bad_function_call异常。若将0赋给一个boost::function类型的函数指针,将会释放所赋的函数。释放之后在调用也会导致boost::bad_function_call异常被抛出。要检查一个函数指针是否被赋予某个函数,可以使用empty()或operator bool()操作符。
#include <boost/function.hpp> #include <iostream> struct world { void hello(std::ostream& os) { os << "Hello, world!" << std::endl; } } int main() { boost::function<void (world*, std::ostrema&)> f = &world::hello; world w; f(&w, boost::ref(std::cout)); return 0; }
在调用这样的一个函数时,传入的第一个参数表示了该函数被调用的那个特定对象。因此,在模板定义中的左括号的第一个参数必须是该特定类型的指针,接下来的参数才是表示相应的成员函数的签名。
4. boost::lambda
匿名函数,可以使源代码更为紧凑。
#include <boost/lambda/lambda.hpp> #include <iostream> #include <vector>
#include <algorithm>
int main() {
std::vector<int> v;
v.push_back(1);
v.push_back(2);
v.push_back(3);
std::for_each(v.begin(), v.end(), std::cout << boost::lambda::_1 << " ");
return 0;
}
通过lambda::_1占位符,容器v的元素可以通过<<传给std::cout以将它们输出到标准输出。有一个例子:
#include <boost/lambda/lambda.hpp> #include <boost/lambda/if.hpp> #include <iostream> #include <vector> #include <algorithm> int main() { std::vector<int> v; v.push_back(1); v.push_back(2); v.push_bakc(3); std::for_each(v.begin(), v.end(), boost::lambda::if_then(boost::lambda::_1 > 1, std::cout << boost::lambda::_1 << " ")); return 0; }