1 Boost.Function
Boost.Function位于 #include <boost/function.hpp>
之中,其提供了类似函数指针的功能。但是这个“函数指针”不但能够指向普通的函数而且还能够指向函数对象或者成员函数。我们可以将其当作对函数指针功能的扩展。下面是它的一个使用示例:
#include <iostream>
#include <boost/function.hpp>
struct myStruct
{
int operator ()(const char* str)
{
std::cout<<str<<std::endl;
return 0;
}
};
int main()
{
myStruct mySt;
boost::function<int (const char*)> fPtr;
fPtr = mySt;
fPtr("function object");
fPtr = std::atoi;
std::cout<<fPtr("53")<<std::endl;
}
在这个例子中我们分别给fPtr赋值了一个函数对象和函数,可以看出它们的表现相同。如果我们调用一个没有赋值的function时,会抛出boost::bad_function_call
异常,当我们给function赋值为0时会释放其保存的函数,这时候对其的调用同样会引发上述异常。当我们用function对象来保存一个成员函数时,必须在定义的时候显示的在第一个输入指定是那个类,同时在调用的使用第一个参数必须要是类对象的地址,下面是一个调用示例:
#include <iostream>
#include <boost/function.hpp>
struct myStruct
{
void hello(std::ostream & os)
{
os<<"Hello world!"<<std::endl;
}
};
int main()
{
myStruct mySt;
boost::function<void (myStruct*,std::ostream&)> fPtr = &myStruct::hello;
fPtr(&mySt,boost::ref(std::cout));
}
这里我们使用的是指针传递,当然对应的也可以使用引用传递和值传递,这里不过多介绍了,如果想了解可以参考后面提到的参考文章。另外这里使用到了boost::ref用来传递不可复制的输出流的引用,它提供了一个方便的机制向boost::function传递引用,当然这里也可以不加。
2 Boost::Lambda
Lambda表达式又称匿名函数,用来定义一些小的而且无需关心函数名的函数,在这些场合使用Lambda表达式定义函数能够使得程序看起来更加清晰。但是如果过分的使用lambda表达式又会是程序过于混乱。在使用的过程中必须要根据实际情况进行取舍。lambda表达式的目的是让源代码更加紧凑,也更容易理解。首先我们先看一个不使用lambda的一个示例:
#include <iostream>
#include <vector>
#include <algorithm>
void print(int i)
{
std::cout << i << std::endl;
}
int main()
{
std::vector<int> v;
v.push_back(1);
v.push_back(3);
v.push_back(2);
std::for_each(v.begin(), v.end(), print);
}
这个例子是用来循环打印向量中的元素。对于这个简短的打印函数在每次调用的过程中都要想普通函数那样进栈出栈,十分浪费时间。一个解决办法是使用inline关键字将其声明为在线函数。但是这还存在一个问题,就是代码很不紧凑,这个时候我们就可以使用lambda表达式来解决这个问题,使用示例如下:
#include <iostream>
#include <vector>
#include <algorithm>
#include <boost/lambda/lambda.hpp>
int main()
{
std::vector<int> v;
v.push_back(1);
v.push_back(3);
v.push_back(2);
std::for_each(v.begin(), v.end(), std::cout<<boost::lambda::_1<<"
");
}
这里我们结合lambda表达式和占位符_1
就将上面的函数集成到其调用之处了。boost::lambda
定义了三个占位符,_1,_2,_3
和 boost::bind 不同,它的占位符定义在单独的命名空间中。boost::lambda很强大但是也有缺点,比如上面最后必须使用
而不能使用std::endl
。下面这个例子使用了boost::lambda::if_then()
来输出大于1的元素。
#include <iostream>
#include <vector>
#include <algorithm>
#include <boost/lambda/lambda.hpp>
#include <boost/lambda/if.hpp>
int main()
{
std::vector<int> v;
v.push_back(1);
v.push_back(3);
v.push_back(2);
std::for_each(v.begin(), v.end(),boost::lambda::if_then(boost::lambda::_1>1,
std::cout<<boost::lambda::_1<<"
"));
}
除了boost::lambda::if_then()
,boost.lambda还提供了boost::lambda::if_then_else()
和boost::lambda::if_then_else_return()
模板函数,它们都要求三个参数。另外还提供了用于实现循环、转换操作符,甚至是throw——允许lambda函数抛出异常的模板。
虽然可以用这些来构造复杂的lambda函数,但我们必须要考虑到代码的可读性不能一味地追求代码的紧凑。有时候动手编写一个单独的函数可能是个不错的选择。