Boost LambdaLibrary(简称为 BLL)是一个 C++ 模板库,为 C++ 实现了 lambda abstractions 的形式。这个术语起源于函数式编程和 lambda 演算,一个 lambda abstraction 定义一个无名函数。
BLL 的主要动机是为定义供 STL 算法使用的无名函数对象提供灵活性和便利性。在讲解一个库是什么的时候,一行代码往往胜过千言万语,下面这一行输出以空格分隔的某个 STL 容器 a 中的元素:
for_each(a.begin(), a.end(), std::cout<< _1 << ' ');
表达式 std::cout << _1 << ' ' 定义了一个一元的函数对象。变量 _1 是这个函数的形式参数,相当于一个实际参数的 placeholder(占位符)。在 for_each 的每一次迭代中,针对实际参数 a 中的元素调用这个函数。这个实际参数取代了占位符,而这个函数体被求值。
BLL 的本质是让你就像上面那个一样,在紧挨着 STL 算法调用位置的上面,定义小的无名函数对象。
匿名函数—— 又称为lambda函数(lanbu(mu)da,兰布达),已经在多种编程语言中存在,但C++除外。不过在Boost.Lambda库的帮助下,现在C++应用中也可以使用它们了。
注意:lambda函数的目标是令源代码更为紧凑,从而也更容易理解。
Boost.Lambda提供了几个结构来定义匿名函数。代码就被置于执行的地方,从而省去将它包装为一个函数再进行相应的函数调用的开销。
Boost.Lambda定义了三个占位符,名为_1,_2和_3。这些占位符是定义在单独的名字空间的。因此,第一个占位符是通过boost::lambda::_1来引用的。为了满足编译器的要求,必须包含相应的头文件boost/lambda/lambda.hpp。
虽然代码的位置位于std::foreach()的第三个参数处,看起来很怪异,但Boost.Lambda可以写出正常的C++代码。通过使用占位符,容器v的元素可以通过<<传给std::out以将它们输出到标准输出流。
注意:虽然Boost.Lambda非常强大,但也有一些缺点。要在以上例子中插入换行的话,必须用"/n"来代替std::endl才能成功编译。因为,一元std::endl模版函数所要求的类型不同于lambda函数std::cout<<boost::lambda::_1的函数,所以在此不能使用它。
下一个版本的C++标准很可能会将lambda函数作为C++语言本身的组成部分加入,从而消除对单独的库的需要。但是在下一个版本到来并被不同的编译器厂商所采用可能还需要好几年。在此之前,Boost.Lambda被证明是一个完美的替代品。
注意:虽然可以用这些模板函数在C++中构造出复杂的lambda函数,但是必须要考虑其它方面,如可读性和可维护性。因此,lambda函数的好处通常随着它的复杂性而降低。多数情况下,更为合理的方法是用熟悉的C++结构定义一个单独的函数。
#include <string> #include <iostream> #include <boost/lambda/lambda.hpp> #include <boost/lambda/if.hpp> using namespace std; using namespace boost; /** 匿名函数 —— 又称为lambda函数(lan bu(mu)da,兰布达),已经在多种编程语言中存在, * 但C++除外。不过在Boost.Lambda库的帮助下,现在C++应用中也可以使用它们了。 * */ void print(int i) { std::cout << i << std::endl; } int main( int argc, char* argv[] ) { std::vector<int> v; v.push_back(1); v.push_back(2); v.push_back(3); v.push_back(4); std::for_each(v.begin(), v.end(), print); std::cout<<"ok"<<std::endl; std::for_each( v.begin(), v.end(), boost::lambda::if_then( boost::lambda::_1 > 1, //大于1才执行下面 std::cout << boost::lambda::_1 << "\n"<<"hehe\n" //不支持std::endl )); return 0; }